@gobing-ai/spur 0.3.92 → 0.3.93

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.
Files changed (56) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/pipeline-budgets.json +0 -7
  3. package/config/plugin-scripts.json +10 -0
  4. package/config/templates/AGENTS.md +4 -0
  5. package/config/templates/docs/02_ROADMAP.md +2 -0
  6. package/config/templates/docs/03_ARCHITECTURE.md +3 -1
  7. package/config/templates/docs/04_DESIGN.md +2 -0
  8. package/config/templates/docs/99_PROJECT_CONSTITUTION.md +10 -2
  9. package/config/workflow-candidates.json +72 -1
  10. package/config/workflows/feature-verification.yaml +1 -0
  11. package/config/workflows/history-anatomy.yaml +2 -0
  12. package/config/workflows/idea-pipeline.yaml +67 -18
  13. package/config/workflows/pr-review.yaml +8 -0
  14. package/config/workflows/task-pipeline.yaml +180 -39
  15. package/config/workflows/wayfinder-resolution.yaml +5 -0
  16. package/config/workflows/wrapup-pipeline.yaml +55 -14
  17. package/package.json +9 -9
  18. package/plugins/sp/README.md +7 -2
  19. package/plugins/sp/commands/dev-run.md +2 -2
  20. package/plugins/sp/commands/dev-runall.md +2 -2
  21. package/plugins/sp/lib/idea-handoff.generated.mjs +8 -4
  22. package/plugins/sp/lib/inline-run.generated.d.mts +1 -0
  23. package/plugins/sp/lib/inline-run.generated.mjs +24 -16
  24. package/plugins/sp/plugin.json +1 -1
  25. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +1 -1
  26. package/plugins/sp/scripts/inline-run-setup.mjs +75 -3
  27. package/plugins/sp/scripts/inline-run-setup.ts +133 -3
  28. package/plugins/sp/scripts/quality-gate.mjs +248 -6
  29. package/plugins/sp/scripts/quality-gate.ts +410 -9
  30. package/plugins/sp/scripts/residual-scan.mjs +12 -4
  31. package/plugins/sp/scripts/residual-scan.ts +32 -6
  32. package/plugins/sp/scripts/task-diffstat.mjs +156 -0
  33. package/plugins/sp/scripts/task-diffstat.ts +229 -0
  34. package/plugins/sp/scripts/wrapup-drift-probe.mjs +181 -0
  35. package/plugins/sp/scripts/wrapup-drift-probe.ts +258 -0
  36. package/plugins/sp/scripts/wrapup-steps.mjs +60 -1
  37. package/plugins/sp/scripts/wrapup-steps.ts +89 -4
  38. package/plugins/sp/skills/brainstorm/SKILL.md +2 -0
  39. package/plugins/sp/skills/brainstorm/references/workflows.md +17 -2
  40. package/plugins/sp/skills/code-verification/SKILL.md +2 -2
  41. package/plugins/sp/skills/code-verification/references/secu-review.md +3 -2
  42. package/plugins/sp/skills/spur-check/SKILL.md +112 -0
  43. package/plugins/sp/skills/spur-dev/SKILL.md +2 -1
  44. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +14 -2
  45. package/plugins/sp/skills/spur-dev/references/document-authoring.md +85 -0
  46. package/plugins/sp/skills/spur-dev/references/execution-batch.md +1 -1
  47. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +8 -0
  48. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +3 -2
  49. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +19 -1
  50. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +5 -5
  51. package/plugins/sp/skills/spur-dev/templates/design.md +31 -0
  52. package/plugins/sp/skills/spur-dev/templates/plan.md +32 -0
  53. package/plugins/sp/skills/spur-doctor/SKILL.md +60 -14
  54. package/schemas/state-machine-workflow.schema.json +4 -0
  55. package/spur.js +1117 -472
  56. package/config/workflows/decision-routing-example.yaml +0 -134
@@ -387,7 +387,12 @@ END`;var MEASURE_COLS="messages, tool_calls, skill_calls, fresh_input_tokens, ca
387
387
  ''
388
388
  )
389
389
  ELSE ''
390
- END`;var POST_WATERMARK_TABLES=[...KEYED_ROLLUP_TABLES,...GLOBAL_RANKED_ROLLUP_TABLES,"history_daily_stats","history_board_source_daily"];var HISTORY_IMPORT_SCHEMA_VERSION="0.5.5",HISTORY_IMPORT_SCHEMA_SQL=`
390
+ END`;var POST_WATERMARK_TABLES=[...KEYED_ROLLUP_TABLES,...GLOBAL_RANKED_ROLLUP_TABLES,"history_daily_stats","history_board_source_daily"];init_zod();import{createHash}from"node:crypto";function stableJson(value){if(Array.isArray(value))return`[${value.map((entry)=>entry===void 0?"null":stableJson(entry)).join(",")}]`;if(value!==null&&typeof value==="object"){let record2=value;return`{${Object.keys(record2).filter((key)=>record2[key]!==void 0).sort().map((key)=>`${JSON.stringify(key)}:${stableJson(record2[key])}`).join(",")}}`}return JSON.stringify(value)??"null"}function sha256(value){return createHash("sha256").update(stableJson(value)).digest("hex")}var MESSAGE_MAPPER_KEYS=["_codexUsageCarrier","session_id","seq","turn_index","role","record_type","disposition","ts","duration_ms","model","input_tokens","output_tokens","cache_read_tokens","cache_write_tokens","cost_usd","content_text","cwd","provenance","run_id","task_wbs","request_id"],TOOL_CALL_MAPPER_KEYS=["_messageSplitIndex","session_id","seq","tool_name","call_id","args_digest","args_raw","status","started_at","completed_at","duration_ms","result_bytes","error_text"],SKILL_CALL_MAPPER_KEYS=["_messageSplitIndex","session_id","seq","skill_name","invocation_kind","skill_path","args_raw","args_digest","call_id","status","started_at","completed_at","duration_ms"];function identityFieldMap(keys){let map2={};for(let key of keys)map2[key]=key;return map2}var HARNESS_SKILL_PACKAGES=new Set(["sp","rd3"]);function canonicalizeSkillName(raw){let name=raw.trim();if(name.startsWith("/")||name.startsWith("$"))name=name.slice(1);if(name.startsWith("skill:"))name=name.slice(6);let canonical=name.match(/^([a-z][a-z0-9]*):([a-z0-9-]+)$/);if(canonical!==null&&HARNESS_SKILL_PACKAGES.has(canonical[1]??""))return name;let dialect=name.match(/^([a-z][a-z0-9]*)-([a-z0-9-]+)$/);if(dialect!==null&&HARNESS_SKILL_PACKAGES.has(dialect[1]??""))return`${dialect[1]}:${dialect[2]}`;return name}function extractSkillCalls(raw,context,identity){switch(context?.source){case"claude":return detectClaudeSkillCalls(raw,identity);case"pi":return detectPiSkillCalls(raw,identity);case"omp":return detectOmpSkillCalls(raw,identity);case"codex":return detectCodexSkillCalls(raw,identity);case"agy":return detectAgySkillCalls(raw,identity);case"gemini":return detectGeminiSkillCalls(raw,identity);case"grok":return detectGrokSkillCalls(raw,identity);default:return[]}}function skillCallEntry(record2){return{targetTable:"history_skill_call",record:record2}}function skillRecord(identity,skillName,invocationKind,extra={}){return{_messageSplitIndex:identity.messageSplitIndex,session_id:identity.sessionId,seq:identity.seq,skill_name:canonicalizeSkillName(skillName),invocation_kind:invocationKind,skill_path:null,args_raw:null,args_digest:null,call_id:null,status:"ok",started_at:null,completed_at:null,duration_ms:null,...extra}}function skillNameFromPath(path){let normalized=path.replace(/\\/g,"/"),bySkillsSegment=normalized.match(/\/skills\/([^/]+)\/SKILL\.md$/i);if(bySkillsSegment!==null)return bySkillsSegment[1]??"";let stem=normalized.slice(0,normalized.length-9);return stem.split("/").pop()??stem}function detectClaudeSkillCalls(raw,identity){let contentBlocks=raw.content??o(raw.message).content;if(!Array.isArray(contentBlocks))return[];let rows=[];for(let block of contentBlocks){if(typeof block!=="object"||block===null)continue;let b=block;if(b.type!=="tool_use"||b.name!=="Skill")continue;let input=b.input??{},skill=s(input.skill);if(skill===void 0)continue;rows.push(skillRecord(identity,skill,s(o(b.caller).type)==="direct"?"user":"model",{args_raw:maybeArgsRaw("claude","Skill",input)??null,args_digest:argsDigest(input),call_id:s(b.id)??null}))}return rows}var PI_SKILL_WRAPPER=/<skill\s+name="([^"]+)"(?:\s+location="([^"]*)")?\s*>/g;function detectPiSkillCalls(raw,identity){let msg=raw.message;if(piRole(msg?.role??raw.role??raw.recordType??raw.type)!=="user")return[];let text=extractContentText(msg?.content??raw.content);if(text===void 0)return[];let rows=[];for(let match of text.matchAll(PI_SKILL_WRAPPER))rows.push(skillRecord(identity,match[1]??"","user",{skill_path:match[2]||null}));return rows}function detectOmpSkillCalls(raw,identity){let msg=raw.message;if(mapRole(msg?.role??raw.type??raw.role)!=="assistant")return[];let contentBlocks=msg?.content??raw.content;if(!Array.isArray(contentBlocks))return[];let rows=[];for(let block of contentBlocks){let call=normalizeOmpToolCall(block);if(call===null||call.name!=="Skill")continue;let input=call.input??call.arguments,skill=s(input?.skill);if(skill===void 0)continue;rows.push(skillRecord(identity,skill,"model",{args_raw:maybeArgsRaw("omp","Skill",input)??null,args_digest:argsDigest(input),call_id:s(call.id)??null}))}return rows}var CODEX_SKILL_BLOCK=/<skill>\s*<name>([^<]+)<\/name>\s*<path>([^<]+)<\/path>\s*<\/skill>/g;function detectCodexSkillCalls(raw,identity){let payload=raw.payload??raw,recordType=String(raw.type??""),payloadType=String(payload.type??""),role;if(recordType==="response_item")role=payloadType==="message"?mapRole(payload.role):payloadType==="agent_message"?"assistant":"meta";else if(recordType==="user"||recordType==="assistant")role=mapRole(recordType);else if(recordType==="message")role=mapRole(raw.role??payload.role);else return[];if(role!=="user")return[];let text=extractContentText(payload.content??raw.content)??s(payload.text,raw.text);if(text===void 0)return[];let rows=[];for(let match of text.matchAll(CODEX_SKILL_BLOCK))rows.push(skillRecord(identity,match[1]??"","user",{skill_path:match[2]??null}));return rows}function detectAgySkillCalls(raw,identity){if(String(raw.type??"")!=="PLANNER_RESPONSE"||!Array.isArray(raw.tool_calls))return[];let rows=[];for(let tc of raw.tool_calls){if(s(tc.name,tc.tool_name)!=="view_file")continue;let args=tc.args??tc.arguments??{};if(args.toolAction!=="Viewing skill file")continue;let path=s(args.AbsolutePath,args.absolute_path);if(path===void 0||!path.replace(/\\/g,"/").endsWith("/SKILL.md"))continue;let skillName=s(args.toolSummary)?.match(/SKILL\.md for (.+)$/)?.[1]??skillNameFromPath(path);rows.push(skillRecord(identity,skillName,"model",{skill_path:path,args_raw:maybeArgsRaw("agy","view_file",args)??null,args_digest:argsDigest(args)}))}return rows}var GEMINI_L0_PREFIX=/^\s*\/((?:sp|rd3)-[a-z0-9-]+)/;function detectGeminiSkillCalls(raw,identity){if(String(raw.type??"")!=="user")return[];let content=geminiContent(raw);if(content===null)return[];let match=content.match(GEMINI_L0_PREFIX);if(match===null)return[];return[skillRecord(identity,match[1]??"","user")]}function detectGrokSkillCalls(raw,identity){let n=normalizeGrokRecord(raw);if(n.recordType!=="tool_call"||n.toolName!=="read_file")return[];let meta3=n.body._meta??raw._meta??{};if(o(meta3["x.ai/tool"]).namespace!=="grok_build")return[];let targetFile=s(o(n.toolArgs).target_file);if(targetFile===void 0||!targetFile.replace(/\\/g,"/").endsWith("/SKILL.md"))return[];return[skillRecord(identity,skillNameFromPath(targetFile),"model",{skill_path:targetFile,args_raw:maybeArgsRaw("grok","read_file",n.toolArgs)??null,args_digest:argsDigest(n.toolArgs),started_at:n.ts??null})]}function argsDigest(args){let redacted=redactArgs(args);return sha256(redacted)}function redactArgs(args){if(typeof args==="string"){if(args.length>80)return"[REDACTED:long]";if(/[A-Za-z0-9+/]{40,}=*|[A-Za-z0-9_-]{20,}/.test(args))return"[REDACTED:secret]";return args}if(Array.isArray(args))return args.map(redactArgs);if(args!==null&&typeof args==="object"){let result={};for(let[key,value]of Object.entries(args))result[key]=redactArgs(value);return result}return args}var BASH_COMMAND_MAX_CHARS=8192,GENERIC_ARGS_MAX_CHARS=8192;function bashCommandOf(args){if(args===null||typeof args!=="object")return;let rec=args,command=rec.command??rec.CommandLine??rec.cmd??rec.script;if(typeof command==="string")return command;if(Array.isArray(command))return command.map(String).join(" ");return}var BULKY_PAYLOAD_KEYS=new Set(["content","codecontent","replacementcontent","targetcontent","filedata","buffer","blob","image","imagebase64"]);function normalizeKey(key){return key.toLowerCase().replace(/[^a-z0-9]/g,"")}function isShellTool(toolName){return/^(?:bash|shell|cmd|command|exec|execcommand|executecommand|runcommand|shellcommand|runshellcommand)$/.test(normalizeKey(toolName))}function sanitizeValue(value){if(typeof value==="string")return value.length>1000?`${value.slice(0,1000)}[truncated ${value.length} chars]`:value;if(Array.isArray(value))return value.map(sanitizeValue);if(value!==null&&typeof value==="object"){let out={};for(let[key,entry]of Object.entries(value))out[key]=typeof entry==="string"&&entry.length>120&&BULKY_PAYLOAD_KEYS.has(normalizeKey(key))?`[omitted ${entry.length} chars]`:sanitizeValue(entry);return out}return value}function serializeBounded(value){let serialized=JSON.stringify(sanitizeValue(value));if(serialized.length<=GENERIC_ARGS_MAX_CHARS)return serialized;let preview=serialized;for(;;){let wrapper=JSON.stringify({_truncated:!0,omittedChars:serialized.length-preview.length,preview});if(wrapper.length<=GENERIC_ARGS_MAX_CHARS)return wrapper;preview=preview.slice(0,preview.length-(wrapper.length-GENERIC_ARGS_MAX_CHARS))}}function maybeArgsRaw(_source,toolName,args){if(args===void 0||args===null)return;let value=args;if(typeof args==="string")try{value=JSON.parse(args)}catch{return args.length>BASH_COMMAND_MAX_CHARS?args.slice(0,BASH_COMMAND_MAX_CHARS):args}if(value!==null&&typeof value==="object"){let cmd=bashCommandOf(value);if(cmd!==void 0&&isShellTool(toolName))return cmd.length>BASH_COMMAND_MAX_CHARS?cmd.slice(0,BASH_COMMAND_MAX_CHARS):cmd;return serializeBounded(value)}return JSON.stringify(value)}function claudeSplit(raw,context){let entries=[],sessionId=s(raw.sessionId,raw.conversation_uuid)??"unknown",seq=typeof raw.seq==="number"?raw.seq:typeof raw.messageIndex==="number"?raw.messageIndex:0,ts=timestampOf(raw.ts,raw.timestamp,raw.createdAt),role=mapRole(raw.type??raw.role),recordType=String(raw.type??""),model=s(raw.model,o(raw.message).model),cwd=s(raw.cwd,raw.dir);if(raw.subtype==="turn_duration"&&typeof raw.durationMs==="number")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"system",record_type:"turn_duration",disposition:"meta",ts,duration_ms:raw.durationMs,content_text:null,provenance:"ambient"}}),entries;if(recordType==="attachment"||recordType.startsWith("file-history"))return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,provenance:"ambient"}}),entries;let usage=typeof raw.usage==="object"&&raw.usage!==null?raw.usage:o(raw.message).usage,inputTokens=raw.inputTokens??usage?.input_tokens,outputTokens=raw.outputTokens??usage?.output_tokens,cacheRead=usage?.cacheReadTokens??usage?.cache_read_tokens??usage?.cache_read_input_tokens,cacheWrite=usage?.cacheWriteTokens??usage?.cache_write_tokens??usage?.cache_creation_input_tokens,costUsd=computeCost(inputTokens,outputTokens,model),contentBlocks=raw.content??o(raw.message).content,contentText=extractContentText(contentBlocks),messageSplitIndex=entries.length;if(entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,turn_index:typeof raw.turnIndex==="number"?raw.turnIndex:void 0,role,record_type:recordType,disposition:"keep",ts,duration_ms:void 0,model:model??null,input_tokens:inputTokens??null,output_tokens:outputTokens??null,cache_read_tokens:cacheRead??null,cache_write_tokens:cacheWrite??null,cost_usd:costUsd??null,content_text:contentText??null,cwd:cwd??null,provenance:"ambient",request_id:s(raw.requestId)??null}}),Array.isArray(contentBlocks)&&role==="assistant")for(let block of contentBlocks){if(typeof block!=="object"||block===null)continue;let b=block;if(b.type==="tool_use")entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq,call_id:s(b.id),tool_name:String(b.name??""),args_digest:argsDigest(b.input),args_raw:maybeArgsRaw("claude",String(b.name??""),b.input),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function piSplit(raw,context){let msg=raw.message,recordType=String(raw.type??raw.recordType??""),sessionId=sessionIdFromContext(context,raw),seq=context?.sourceLine??(typeof raw.seq==="number"?raw.seq:0),ts=timestampOf(raw.timestamp,raw.createdAt,raw.ts);if(recordType==="title"||recordType==="title_change"||recordType==="service_tier_change"||recordType==="session_info"||recordType==="ttsr_injection"||recordType==="session_init"||recordType==="session"||recordType==="model_change"||recordType==="thinking_level_change"||recordType==="compaction"||recordType==="custom"||recordType==="custom_message"||recordType.startsWith("custom."))return[{targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,provenance:"ambient"}}];let entries=[],role=piRole(msg?.role??raw.role??recordType),model=s(raw.model,o(msg).model),cwd=s(raw.cwd,raw.dir),usage=msg?.usage??raw.usage,inputTokens=usage?.input??usage?.input_tokens??void 0,outputTokens=usage?.output??usage?.output_tokens??void 0,cacheRead=usage?.cacheRead??usage?.cache_read_tokens??void 0,cacheWrite=usage?.cacheWrite??usage?.cache_write_tokens??void 0,costObj=msg?.cost??raw.cost,costUsd=typeof costObj?.total==="number"?costObj.total:computeCost(inputTokens,outputTokens,model),contentBlocks=msg?.content??raw.content,durationMs=typeof msg?.duration==="number"&&Number.isFinite(msg.duration)?msg.duration:void 0,messageSplitIndex=entries.length;if(entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition:"keep",ts,duration_ms:durationMs,model:model??null,input_tokens:inputTokens??null,output_tokens:outputTokens??null,cache_read_tokens:cacheRead??null,cache_write_tokens:cacheWrite??null,cost_usd:costUsd??null,content_text:extractContentText(contentBlocks)??s(raw.content,raw.text,msg?.content)??null,cwd:cwd??null,provenance:"ambient"}}),Array.isArray(contentBlocks)&&role==="assistant")for(let block of contentBlocks){let call=normalizeOmpToolCall(block);if(call===null)continue;entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq,tool_name:String(call.name??""),call_id:s(call.id),args_digest:argsDigest(call.input??call.arguments),args_raw:maybeArgsRaw("pi",String(call.name??""),call.input??call.arguments),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function piRole(type){let t=String(type??"").toLowerCase();if(t==="toolresult"||t==="tool_result"||t==="bashexecution"||t==="tool")return"user";let mapped=mapRole(t);if(mapped==="user"||mapped==="assistant"||mapped==="system")return mapped;return"unknown"}function ompSplit(raw,context){let msg=raw.message,recordType=String(raw.type??""),sessionId=sessionIdFromContext(context,raw),seq=context?.sourceLine??(typeof raw.seq==="number"?raw.seq:0),ts=timestampOf(raw.ts,raw.timestamp,raw.createdAt);if(recordType==="title"||recordType==="title_change"||recordType==="service_tier_change"||recordType==="ttsr_injection"||recordType==="session_init"||recordType==="session"||recordType==="model_change"||recordType==="thinking_level_change"||recordType==="compaction"||recordType==="custom"||recordType==="custom_message"||recordType.startsWith("custom."))return[{targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,provenance:"ambient"}}];let entries=[],role=mapRole(msg?.role??raw.type??raw.role),model=s(raw.model,o(msg).model),cwd=s(raw.cwd,raw.dir),usage=msg?.usage??raw.usage,inputTokens=usage?.input??usage?.input_tokens??void 0,outputTokens=usage?.output??usage?.output_tokens??void 0,cacheRead=usage?.cacheRead??usage?.cache_read_tokens??void 0,cacheWrite=usage?.cacheWrite??usage?.cache_write_tokens??void 0,costObj=msg?.cost??raw.cost,costUsd=typeof costObj?.total==="number"?costObj.total:computeCost(inputTokens,outputTokens,model),contentBlocks=msg?.content??raw.content,durationMs=typeof msg?.duration==="number"&&Number.isFinite(msg.duration)?msg.duration:void 0,messageSplitIndex=entries.length;if(entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition:"keep",ts,duration_ms:durationMs,model:model??null,input_tokens:inputTokens??null,output_tokens:outputTokens??null,cache_read_tokens:cacheRead??null,cache_write_tokens:cacheWrite??null,cost_usd:costUsd??null,content_text:extractContentText(contentBlocks)??s(raw.content,raw.text,msg?.content)??null,cwd:cwd??null,provenance:"ambient"}}),Array.isArray(contentBlocks)&&role==="assistant")for(let block of contentBlocks){let call=normalizeOmpToolCall(block);if(call===null)continue;entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq,tool_name:String(call.name??""),call_id:s(call.id),args_digest:argsDigest(call.input??call.arguments),args_raw:maybeArgsRaw("omp",String(call.name??""),call.input??call.arguments),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function normalizeOmpToolCall(block){if(typeof block!=="object"||block===null)return null;let nested=o(block.toolCall);if(Object.keys(nested).length>0)return nested;if(block.type==="toolCall")return block;return null}function codexSplit(raw,context){let entries=[],payload=raw.payload??raw,seq=typeof raw.seq==="number"?raw.seq:0,ts=timestampOf(raw.timestamp,raw.ts,payload.ts),recordType=String(raw.type??""),payloadType=String(payload.type??""),isShortFormat=recordType===""&&raw.id!==void 0&&raw.timestamp!==void 0&&raw.instructions!==void 0,explicitSessionId=s(raw.session_id,o(raw.session_meta).id);if(explicitSessionId===void 0&&recordType==="session_meta")explicitSessionId=s(payload.id,o(raw.payload).id);if(explicitSessionId===void 0&&isShortFormat)explicitSessionId=s(raw.id);let pathSessionId=context?.sourceFile?sessionIdFromSourcePath("codex",context.sourceFile):void 0,sessionId=explicitSessionId??pathSessionId??"unknown";if(isShortFormat)return[{targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:"short_format",disposition:"meta",ts,provenance:"ambient"}}];let role,disposition,contentText,usage;if(recordType==="response_item")if(payloadType==="message")role=mapRole(payload.role),disposition="keep",contentText=extractContentText(payload.content)??s(payload.text)??null;else if(payloadType==="agent_message")role="assistant",disposition="keep",contentText=extractContentText(payload.content)??s(payload.text,payload.message)??null;else if(payloadType==="reasoning")role="assistant",disposition="keep",contentText=extractContentText(payload.summary)??s(payload.text)??null;else if(payloadType==="function_call"||payloadType==="custom_tool_call")role="tool",disposition="keep",contentText=null;else role="meta",disposition="meta",contentText=s(payload.text)??null;else if(recordType==="user"||recordType==="assistant")role=mapRole(recordType),disposition="keep",contentText=extractContentText(payload.content)??s(raw.content,payload.text)??null;else if(recordType==="message")role=mapRole(raw.role??payload.role),disposition="keep",contentText=extractContentText(payload.content??raw.content)??s(payload.text,raw.text)??null;else if(recordType==="event_msg")role="meta",disposition="meta",contentText=s(payload.message,payload.text)??null,usage=o(o(payload.info).last_token_usage);else role="meta",disposition="meta",contentText=s(payload.text,raw.instructions)??null;let model=s(raw.model,payload.model,o(o(raw.turn_context).payload).model),cwd=s(raw.cwd,raw.dir),tokenCount=payload.token_count,usageInput=usage?.input_tokens??tokenCount?.input??tokenCount?.input_tokens??void 0,usageOutput=usage?.output_tokens??tokenCount?.output??tokenCount?.output_tokens??void 0,cacheRead=usage?.cached_input_tokens??void 0,turnPayload=raw.turn_context?.payload,turnInputTokens=turnPayload?.input_tokens,turnOutputTokens=turnPayload?.output_tokens,finalInput=usageInput!==void 0?usageInput:turnInputTokens,finalOutput=usageOutput!==void 0?usageOutput:turnOutputTokens,costUsd=computeCost(finalInput,finalOutput,model),usageCarrier=finalInput!==void 0||finalOutput!==void 0?{input:finalInput??null,output:finalOutput??null,cacheRead:cacheRead??null}:void 0,stripUsage=role==="meta"&&usageCarrier!==void 0,messageSplitIndex=entries.length;entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition,ts,duration_ms:void 0,model:model??null,input_tokens:stripUsage?null:finalInput??null,output_tokens:stripUsage?null:finalOutput??null,cache_read_tokens:stripUsage?null:cacheRead??null,...usageCarrier!==void 0?{_codexUsageCarrier:usageCarrier}:{},cache_write_tokens:null,cost_usd:costUsd??null,content_text:contentText,cwd:cwd??null,provenance:"ambient"}});let toolItems=[];if((recordType==="response_item"||recordType==="function_call"||recordType==="custom_tool_call")&&(payloadType==="function_call"||payloadType==="custom_tool_call"))toolItems.push(payload);else if(payload.response_item)toolItems.push(payload.response_item);else if(Array.isArray(payload.response_items))toolItems.push(...payload.response_items);for(let item of toolItems){let fc=item.function_call??item,toolName=s(fc.name)??"",args=fc.arguments??fc.input;entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq,tool_name:toolName,call_id:s(fc.call_id),args_digest:argsDigest(args),args_raw:maybeArgsRaw("codex",toolName,args),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function agySplit(raw,context){let entries=[],recordType=String(raw.type??""),explicitSessionId=s(raw.session_id,raw.conversation_id,raw.conversationId),pathSessionId=context?.sourceFile?sessionIdFromSourcePath("agy",context.sourceFile):void 0,sessionId=explicitSessionId??pathSessionId??"unknown",seq=typeof raw.seq==="number"?raw.seq:typeof raw.step_index==="number"?raw.step_index:context?.sourceLine??0,ts=timestampOf(raw.created_at,raw.timestamp,raw.ts),role,disposition,contentText=null,messageRecordType=recordType;if(raw.display!==void 0)role="user",disposition="keep",contentText=s(raw.display)??null,messageRecordType=recordType.length>0?recordType:"USER_INPUT";else switch(recordType){case"USER_INPUT":case"ASK_QUESTION":role="user",disposition="keep",contentText=s(raw.content,raw.text,raw.message)??null;break;case"PLANNER_RESPONSE":role="assistant",disposition="keep",contentText=s(raw.content,raw.text,raw.message,raw.plan)??null;break;case"ERROR_MESSAGE":role="system",disposition="keep",contentText=s(raw.content,raw.text,raw.message)??null;break;case"RUN_COMMAND":case"VIEW_FILE":case"GREP_SEARCH":case"LIST_DIRECTORY":case"READ_URL_CONTENT":role="tool",disposition="keep",contentText=s(raw.content,raw.command,raw.file_path,raw.pattern)??null;break;case"CODE_ACTION":case"INVOKE_SUBAGENT":role="tool",disposition="keep",contentText=s(raw.content,raw.text)??null;break;case"CONVERSATION_HISTORY":case"CHECKPOINT":case"GENERIC":role="meta",disposition="meta",contentText=s(raw.content,raw.text)??null;break;default:if(recordType.length===0)role="unknown",disposition="unknown";else role="meta",disposition="meta",contentText=s(raw.content,raw.text)??null;break}let messageSplitIndex=entries.length;if(entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:messageRecordType,disposition,ts,duration_ms:void 0,model:null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:contentText,cwd:s(raw.workspace,raw.cwd)??null,provenance:"ambient"}}),recordType==="PLANNER_RESPONSE"&&Array.isArray(raw.tool_calls))for(let tc of raw.tool_calls)entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq:typeof tc.step_index==="number"?tc.step_index:seq,tool_name:String(tc.name??tc.tool_name??""),args_digest:argsDigest(tc.input??tc.arguments),args_raw:maybeArgsRaw("agy",String(tc.name??tc.tool_name??""),tc.input??tc.arguments),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}});for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function geminiSplit(raw,context){let recordType=String(raw.type??(raw.kind!==void 0?"session":raw.$set!==void 0?"state":"")),state=o(raw.$set),sessionId=sessionIdFromContext(context,raw),seq=context?.sourceLine??0,ts=timestampOf(raw.timestamp,raw.startTime,raw.lastUpdated,state.lastUpdated);if(recordType==="session"||recordType==="state")return[{targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,content_text:s(state.summary)??null,provenance:"ambient"}}];let role=recordType==="gemini"?"assistant":recordType==="user"?"user":"system",tokens=o(raw.tokens),content=geminiContent(raw),entries=[{targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition:"keep",ts,duration_ms:null,model:s(raw.model)??null,input_tokens:numberOrNull(tokens.input),output_tokens:numberOrNull(tokens.output),cache_read_tokens:numberOrNull(tokens.cached),cache_write_tokens:null,cost_usd:null,content_text:content,cwd:null,provenance:"ambient"}}];if(Array.isArray(raw.toolCalls))for(let value of raw.toolCalls){if(value===null||typeof value!=="object"||Array.isArray(value))continue;let tool=value,status=s(tool.status)??"unknown",timestamp=s(tool.timestamp),result=tool.result??tool.resultDisplay;entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:0,session_id:sessionId,seq,tool_name:s(tool.name,tool.displayName)??"unknown",args_digest:argsDigest(tool.args),args_raw:maybeArgsRaw("gemini",s(tool.name,tool.displayName)??"",tool.args),status,started_at:timestamp,completed_at:timestamp,duration_ms:null,result_bytes:result===void 0?null:new TextEncoder().encode(JSON.stringify(result)).byteLength,error_text:status==="error"?s(tool.resultDisplay,tool.result)??null:null}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex:0}))entries.push(skillCallEntry(record2));return entries}function dshSplit(raw,context){let recordType=String(raw.type??"");if(recordType==="session")return[{targetTable:"history_message",record:{session_id:s(raw.id)??sessionIdFromSourcePath("deepseek",context?.sourceFile??"")??"unknown",seq:0,role:"meta",record_type:"session",disposition:"meta",ts:timestampOf(raw.createdAt),cwd:s(raw.cwd)??null,content_text:null,provenance:"ambient"}}];if(recordType!=="user/message"&&recordType!=="assistant/message")return[];let data=o(raw.data),msg=o(data.message),seq=typeof raw.seq==="number"?raw.seq:context?.sourceLine??0,sessionId=sessionIdFromSourcePath("deepseek",context?.sourceFile??"")??"unknown",role=recordType==="user/message"?"user":"assistant",source=o(data.source??msg.source),model=s(source.model,o(data.model??msg.model).model),usage=data.usage??msg.usage,messageId=s(msg.id,data.id);return[{targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition:"keep",...messageId!==void 0?{source_record_id:messageId}:{},ts:timestampOf(raw.time,data.time,msg.time),duration_ms:null,model:model??null,input_tokens:numberOrNull(usage?.input_tokens??usage?.input)??null,output_tokens:numberOrNull(usage?.output_tokens??usage?.output)??null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:extractContentText(data.content??msg.content)??s(data.text,msg.text)??null,cwd:null,provenance:"ambient"}}]}var UUID_PATTERN="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}",AGY_BRAIN_REGEX=new RegExp(`(?:^|\\/)brain\\/(${UUID_PATTERN})(?:\\/|$)`,"i"),DSH_SESSION_REGEX=new RegExp(`(?:^|\\/)session-(${UUID_PATTERN})(?:\\/|$)`,"i"),CODEX_ROLLOUT_REGEX=new RegExp(`(?:^|-|_)(${UUID_PATTERN})$`,"i");function sessionIdFromSourcePath(source,sourceFile){let normalized=sourceFile.replace(/\\/g,"/"),sLower=source.toLowerCase();if(sLower==="agy"||sLower==="antigravity")return normalized.match(AGY_BRAIN_REGEX)?.[1];if(sLower==="deepseek")return normalized.match(DSH_SESSION_REGEX)?.[1];if(sLower==="codex"){let basename=normalized.split("/").at(-1)??"";if(basename.startsWith("rollout-")&&basename.endsWith(".jsonl"))return basename.slice(0,-6).match(CODEX_ROLLOUT_REGEX)?.[1]}return}function sessionIdFromContext(context,raw){if(context!==void 0){let file2=context.sourceFile.split("/").at(-1);if(file2!==void 0)return file2.replace(/\.jsonl$/,"")}return s(raw.sessionId,raw.id)??"unknown"}function geminiContent(raw){let content=extractContentText(raw.content)??s(raw.text),thoughts=Array.isArray(raw.thoughts)?raw.thoughts.map((value)=>value!==null&&typeof value==="object"?s(o(value).description):void 0).filter((value)=>value!==void 0).join(`
391
+ `):"";return[content,thoughts].filter((value)=>value!==void 0&&value.length>0).join(`
392
+ `)||null}function numberOrNull(value){return typeof value==="number"&&Number.isFinite(value)?value:null}function normalizeGrokRecord(raw){let params=raw.params,update=params?.update,isUpdatesShape=typeof raw.method==="string"&&params!==void 0&&update!==void 0,body=isUpdatesShape?update:raw,recordType=String((isUpdatesShape?update?.sessionUpdate:raw.type)??raw.sessionUpdate??raw.eventType??(raw.file_snapshots!==void 0||raw.after_snapshots!==void 0?"file_snapshot":raw.prompt!==void 0?"user_message":raw.answer!==void 0||raw.question!==void 0?"assistant":"")),sessionId=s(params?.sessionId,raw.session_id,raw.sessionId,raw.parentSessionId,raw.btwSessionId,raw.params?.sessionId)??"unknown",ts=normalizeTs(raw.ts??raw.timestamp??raw.created_at??raw.askedAt??body.ts??body.timestamp),seq=typeof raw.seq==="number"?raw.seq:typeof body.seq==="number"?body.seq:0,meta3=body._meta??params?._meta??raw._meta,model=s(meta3?.modelId,body.model,raw.model),contentText=extractGrokContent(body.content??body.text??raw.content??raw.text??raw.prompt??(raw.answer!==void 0||raw.question!==void 0?[raw.question,raw.answer].filter((value)=>typeof value==="string").join(`
393
+ `):void 0)),usage=body.usage??raw.usage,toolMeta=meta3?.["x.ai/tool"],titleFallback=s(body.title)?.split("`")[0]?.trim(),toolName=s(toolMeta?.name,body.kind,body.tool_name,body.name,raw.tool_name,raw.name)??(titleFallback!==void 0&&titleFallback.length>0&&titleFallback.length<=40?titleFallback:""),toolArgs=body.rawInput??body.input??body.arguments??toolMeta?.input??raw.input??raw.arguments,toolStatus=s(body.status,raw.outcome,raw.status)??"ok",durationMs=typeof body.duration_ms==="number"?body.duration_ms:typeof raw.duration_ms==="number"?raw.duration_ms:typeof usage?.apiDurationMs==="number"?usage.apiDurationMs:void 0,errorText=body.error!==void 0?String(body.error):raw.error!==void 0?String(raw.error):void 0,hasTypeDiscriminator=recordType.length>0||isUpdatesShape;return{recordType,sessionId,ts,seq,body,model,contentText,usage,toolName,toolArgs,toolStatus,durationMs,errorText,hasTypeDiscriminator}}function normalizeTs(value){return timestampOf(value)}function extractGrokContent(content){if(typeof content==="string")return content;if(content!==null&&typeof content==="object"&&!Array.isArray(content)){let c=content;if(typeof c.text==="string")return c.text;if(typeof c.content==="string")return c.content}if(Array.isArray(content)){let parts=[];for(let block of content)if(typeof block==="string")parts.push(block);else if(block!==null&&typeof block==="object"){let b=block;if(typeof b.text==="string")parts.push(b.text)}return parts.length>0?parts.join(`
394
+ `):null}return null}var GROK_META_TYPES=new Set(["phase_changed","permission_requested","permission_resolved","mcp_server_starting","mcp_server_connected","mcp_config_resolved","mcp_managed_config_result","mcp_transport_decode_error","mcp_init_completed","mcp_health_check","loop_started","first_token","agent_thought_chunk","hook_execution","plan","session_recap","task_backgrounded","task_completed","retry_state","auto_compact_started","auto_compact_completed","compaction_checkpoint","image_compressed","reasoning","system","turn_started","turn_ended","yolo_toggled"]);function grokSplit(raw,context){let entries=[],n=normalizeGrokRecord(raw),{recordType,sessionId,ts,seq}=n;if(recordType==="turn_completed"){let usage=n.usage,modelUsage=usage?.modelUsage,modelFromUsage=modelUsage!==null&&typeof modelUsage==="object"?Object.keys(modelUsage)[0]:void 0,model=s(n.model,modelFromUsage),inputTokens=usage?.inputTokens??usage?.input??usage?.input_tokens,outputTokens=usage?.outputTokens??usage?.output??usage?.output_tokens,cacheRead=usage?.cachedReadTokens??usage?.cache_read_tokens;return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:n.durationMs??usage?.apiDurationMs??null,model:model??null,input_tokens:inputTokens??null,output_tokens:outputTokens??null,cache_read_tokens:cacheRead??null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries}if(recordType==="tool_started")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:void 0,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:0,session_id:sessionId,seq,tool_name:n.toolName,args_digest:argsDigest(n.toolArgs),args_raw:maybeArgsRaw("grok",n.toolName,n.toolArgs),status:n.toolStatus||"ok",started_at:ts,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:n.errorText}}),entries;if(recordType==="tool_completed")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:n.durationMs??null,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:0,session_id:sessionId,seq,tool_name:n.toolName,args_digest:null,args_raw:void 0,status:n.toolStatus||"ok",started_at:void 0,completed_at:ts,duration_ms:n.durationMs,result_bytes:void 0,error_text:n.errorText}}),entries;if(recordType==="tool_call"||recordType==="tool_call_update"){entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:void 0,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:0,session_id:sessionId,seq,tool_name:n.toolName,args_digest:argsDigest(n.toolArgs),args_raw:maybeArgsRaw("grok",n.toolName,n.toolArgs),status:n.toolStatus||"ok",started_at:recordType==="tool_call"?ts:void 0,completed_at:recordType==="tool_call_update"?ts:void 0,duration_ms:n.durationMs,result_bytes:void 0,error_text:n.errorText}});for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex:0}))entries.push(skillCallEntry(record2));return entries}if(recordType==="user"||recordType==="user_message"||recordType==="user_message_chunk"||recordType==="message")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"user",record_type:recordType||"user_message",disposition:"keep",ts,duration_ms:void 0,model:null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries;if(recordType==="assistant"||recordType==="agent_message_chunk")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:void 0,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries;if(GROK_META_TYPES.has(recordType))return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,duration_ms:n.durationMs??null,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries;if(!n.hasTypeDiscriminator||recordType.length===0)return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"unknown",record_type:stableFieldShape(raw),disposition:"unknown",ts,duration_ms:void 0,model:null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries;return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,duration_ms:n.durationMs??null,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries}function o(value){return typeof value==="object"&&value!==null?value:{}}function s(...values){for(let value of values){if(typeof value==="string"&&value.length>0)return value;if(typeof value==="number"&&Number.isFinite(value))return String(value)}return}function timestampOf(...values){for(let value of values){if(typeof value==="number"&&Number.isFinite(value)){let ms=value>1000000000000?value:value*1000;return new Date(ms).toISOString()}if(typeof value==="string"&&value.length>0){let asNum=Number(value);if(Number.isFinite(asNum)&&/^\d+(\.\d+)?$/.test(value.trim())){let ms=asNum>1000000000000?asNum:asNum*1000;return new Date(ms).toISOString()}return value}}return}function mapRole(type){let t=String(type??"").toLowerCase();if(t==="user"||t==="human"||t==="developer")return"user";if(t==="assistant"||t==="ai"||t==="model")return"assistant";if(t==="system"||t==="error")return"system";return t||"unknown"}function computeCost(inputTokens,outputTokens,model){if(inputTokens===void 0||inputTokens===null)return;if(outputTokens===void 0||outputTokens===null)return;let inputRate=model?.toLowerCase().includes("claude")?3:1,outputRate=model?.toLowerCase().includes("claude")?15:5;return(inputTokens*inputRate+outputTokens*outputRate)/1e6}function extractContentText(content){if(typeof content==="string")return content;if(!Array.isArray(content))return;let parts=[];for(let block of content){if(typeof block!=="object"||block===null)continue;let b=block;if(typeof b.text==="string")parts.push(b.text)}return parts.length>0?parts.join(`
395
+ `):void 0}function stableFieldShape(raw){return Object.keys(raw).map((k)=>k.toLowerCase()).sort().join("+")}var CLAUDE_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),PI_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),OMP_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),CODEX_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),AGY_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),GROK_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),GEMINI_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),DSH_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(["source_record_id"])),passthroughSchema=exports_external.object({}).passthrough(),CLAUDE_SCHEMA=passthroughSchema,PI_SCHEMA=passthroughSchema,OMP_SCHEMA=passthroughSchema,CODEX_SCHEMA=passthroughSchema,AGY_SCHEMA=passthroughSchema,GROK_SCHEMA=passthroughSchema,GEMINI_SCHEMA=passthroughSchema,DSH_SCHEMA=passthroughSchema;var HISTORY_IMPORT_SCHEMA_VERSION="0.5.7",HISTORY_IMPORT_SCHEMA_SQL=`
391
396
  CREATE TABLE IF NOT EXISTS history_import_checkpoint (
392
397
  source TEXT NOT NULL,
393
398
  source_file TEXT NOT NULL,
@@ -504,12 +509,7 @@ CREATE INDEX IF NOT EXISTS idx_history_skill_call_message_hash
504
509
  ON history_skill_call(message_hash);
505
510
  CREATE INDEX IF NOT EXISTS idx_history_skill_call_invocation_kind
506
511
  ON history_skill_call(invocation_kind);
507
- `.trim();init_zod();init_zod();import{createHash}from"node:crypto";function stableJson(value){if(Array.isArray(value))return`[${value.map((entry)=>entry===void 0?"null":stableJson(entry)).join(",")}]`;if(value!==null&&typeof value==="object"){let record2=value;return`{${Object.keys(record2).filter((key)=>record2[key]!==void 0).sort().map((key)=>`${JSON.stringify(key)}:${stableJson(record2[key])}`).join(",")}}`}return JSON.stringify(value)??"null"}function sha256(value){return createHash("sha256").update(stableJson(value)).digest("hex")}var MESSAGE_MAPPER_KEYS=["_codexUsageCarrier","session_id","seq","turn_index","role","record_type","disposition","ts","duration_ms","model","input_tokens","output_tokens","cache_read_tokens","cache_write_tokens","cost_usd","content_text","cwd","provenance","run_id","task_wbs","request_id"],TOOL_CALL_MAPPER_KEYS=["_messageSplitIndex","session_id","seq","tool_name","call_id","args_digest","args_raw","status","started_at","completed_at","duration_ms","result_bytes","error_text"],SKILL_CALL_MAPPER_KEYS=["_messageSplitIndex","session_id","seq","skill_name","invocation_kind","skill_path","args_raw","args_digest","call_id","status","started_at","completed_at","duration_ms"];function identityFieldMap(keys){let map2={};for(let key of keys)map2[key]=key;return map2}var HARNESS_SKILL_PACKAGES=new Set(["sp","rd3"]);function canonicalizeSkillName(raw){let name=raw.trim();if(name.startsWith("/")||name.startsWith("$"))name=name.slice(1);if(name.startsWith("skill:"))name=name.slice(6);let canonical=name.match(/^([a-z][a-z0-9]*):([a-z0-9-]+)$/);if(canonical!==null&&HARNESS_SKILL_PACKAGES.has(canonical[1]??""))return name;let dialect=name.match(/^([a-z][a-z0-9]*)-([a-z0-9-]+)$/);if(dialect!==null&&HARNESS_SKILL_PACKAGES.has(dialect[1]??""))return`${dialect[1]}:${dialect[2]}`;return name}function extractSkillCalls(raw,context,identity){switch(context?.source){case"claude":return detectClaudeSkillCalls(raw,identity);case"pi":return detectPiSkillCalls(raw,identity);case"omp":return detectOmpSkillCalls(raw,identity);case"codex":return detectCodexSkillCalls(raw,identity);case"agy":return detectAgySkillCalls(raw,identity);case"gemini":return detectGeminiSkillCalls(raw,identity);case"grok":return detectGrokSkillCalls(raw,identity);default:return[]}}function skillCallEntry(record2){return{targetTable:"history_skill_call",record:record2}}function skillRecord(identity,skillName,invocationKind,extra={}){return{_messageSplitIndex:identity.messageSplitIndex,session_id:identity.sessionId,seq:identity.seq,skill_name:canonicalizeSkillName(skillName),invocation_kind:invocationKind,skill_path:null,args_raw:null,args_digest:null,call_id:null,status:"ok",started_at:null,completed_at:null,duration_ms:null,...extra}}function skillNameFromPath(path){let normalized=path.replace(/\\/g,"/"),bySkillsSegment=normalized.match(/\/skills\/([^/]+)\/SKILL\.md$/i);if(bySkillsSegment!==null)return bySkillsSegment[1]??"";let stem=normalized.slice(0,normalized.length-9);return stem.split("/").pop()??stem}function detectClaudeSkillCalls(raw,identity){let contentBlocks=raw.content??o(raw.message).content;if(!Array.isArray(contentBlocks))return[];let rows=[];for(let block of contentBlocks){if(typeof block!=="object"||block===null)continue;let b=block;if(b.type!=="tool_use"||b.name!=="Skill")continue;let input=b.input??{},skill=s(input.skill);if(skill===void 0)continue;rows.push(skillRecord(identity,skill,s(o(b.caller).type)==="direct"?"user":"model",{args_raw:maybeArgsRaw("claude","Skill",input)??null,args_digest:argsDigest(input),call_id:s(b.id)??null}))}return rows}var PI_SKILL_WRAPPER=/<skill\s+name="([^"]+)"(?:\s+location="([^"]*)")?\s*>/g;function detectPiSkillCalls(raw,identity){let msg=raw.message;if(piRole(msg?.role??raw.role??raw.recordType??raw.type)!=="user")return[];let text=extractContentText(msg?.content??raw.content);if(text===void 0)return[];let rows=[];for(let match of text.matchAll(PI_SKILL_WRAPPER))rows.push(skillRecord(identity,match[1]??"","user",{skill_path:match[2]||null}));return rows}function detectOmpSkillCalls(raw,identity){let msg=raw.message;if(mapRole(msg?.role??raw.type??raw.role)!=="assistant")return[];let contentBlocks=msg?.content??raw.content;if(!Array.isArray(contentBlocks))return[];let rows=[];for(let block of contentBlocks){let call=normalizeOmpToolCall(block);if(call===null||call.name!=="Skill")continue;let input=call.input??call.arguments,skill=s(input?.skill);if(skill===void 0)continue;rows.push(skillRecord(identity,skill,"model",{args_raw:maybeArgsRaw("omp","Skill",input)??null,args_digest:argsDigest(input),call_id:s(call.id)??null}))}return rows}var CODEX_SKILL_BLOCK=/<skill>\s*<name>([^<]+)<\/name>\s*<path>([^<]+)<\/path>\s*<\/skill>/g;function detectCodexSkillCalls(raw,identity){let payload=raw.payload??raw,recordType=String(raw.type??""),payloadType=String(payload.type??""),role;if(recordType==="response_item")role=payloadType==="message"?mapRole(payload.role):payloadType==="agent_message"?"assistant":"meta";else if(recordType==="user"||recordType==="assistant")role=mapRole(recordType);else if(recordType==="message")role=mapRole(raw.role??payload.role);else return[];if(role!=="user")return[];let text=extractContentText(payload.content??raw.content)??s(payload.text,raw.text);if(text===void 0)return[];let rows=[];for(let match of text.matchAll(CODEX_SKILL_BLOCK))rows.push(skillRecord(identity,match[1]??"","user",{skill_path:match[2]??null}));return rows}function detectAgySkillCalls(raw,identity){if(String(raw.type??"")!=="PLANNER_RESPONSE"||!Array.isArray(raw.tool_calls))return[];let rows=[];for(let tc of raw.tool_calls){if(s(tc.name,tc.tool_name)!=="view_file")continue;let args=tc.args??tc.arguments??{};if(args.toolAction!=="Viewing skill file")continue;let path=s(args.AbsolutePath,args.absolute_path);if(path===void 0||!path.replace(/\\/g,"/").endsWith("/SKILL.md"))continue;let skillName=s(args.toolSummary)?.match(/SKILL\.md for (.+)$/)?.[1]??skillNameFromPath(path);rows.push(skillRecord(identity,skillName,"model",{skill_path:path,args_raw:maybeArgsRaw("agy","view_file",args)??null,args_digest:argsDigest(args)}))}return rows}var GEMINI_L0_PREFIX=/^\s*\/((?:sp|rd3)-[a-z0-9-]+)/;function detectGeminiSkillCalls(raw,identity){if(String(raw.type??"")!=="user")return[];let content=geminiContent(raw);if(content===null)return[];let match=content.match(GEMINI_L0_PREFIX);if(match===null)return[];return[skillRecord(identity,match[1]??"","user")]}function detectGrokSkillCalls(raw,identity){let n=normalizeGrokRecord(raw);if(n.recordType!=="tool_call"||n.toolName!=="read_file")return[];let meta3=n.body._meta??raw._meta??{};if(o(meta3["x.ai/tool"]).namespace!=="grok_build")return[];let targetFile=s(o(n.toolArgs).target_file);if(targetFile===void 0||!targetFile.replace(/\\/g,"/").endsWith("/SKILL.md"))return[];return[skillRecord(identity,skillNameFromPath(targetFile),"model",{skill_path:targetFile,args_raw:maybeArgsRaw("grok","read_file",n.toolArgs)??null,args_digest:argsDigest(n.toolArgs),started_at:n.ts??null})]}function argsDigest(args){let redacted=redactArgs(args);return sha256(redacted)}function redactArgs(args){if(typeof args==="string"){if(args.length>80)return"[REDACTED:long]";if(/[A-Za-z0-9+/]{40,}=*|[A-Za-z0-9_-]{20,}/.test(args))return"[REDACTED:secret]";return args}if(Array.isArray(args))return args.map(redactArgs);if(args!==null&&typeof args==="object"){let result={};for(let[key,value]of Object.entries(args))result[key]=redactArgs(value);return result}return args}var BASH_COMMAND_MAX_CHARS=8192,GENERIC_ARGS_MAX_CHARS=8192;function bashCommandOf(args){if(args===null||typeof args!=="object")return;let rec=args,command=rec.command??rec.CommandLine??rec.cmd??rec.script;if(typeof command==="string")return command;if(Array.isArray(command))return command.map(String).join(" ");return}var BULKY_PAYLOAD_KEYS=new Set(["content","codecontent","replacementcontent","targetcontent","filedata","buffer","blob","image","imagebase64"]);function normalizeKey(key){return key.toLowerCase().replace(/[^a-z0-9]/g,"")}function isShellTool(toolName){return/^(?:bash|shell|cmd|command|exec|execcommand|executecommand|runcommand|shellcommand|runshellcommand)$/.test(normalizeKey(toolName))}function sanitizeValue(value){if(typeof value==="string")return value.length>1000?`${value.slice(0,1000)}[truncated ${value.length} chars]`:value;if(Array.isArray(value))return value.map(sanitizeValue);if(value!==null&&typeof value==="object"){let out={};for(let[key,entry]of Object.entries(value))out[key]=typeof entry==="string"&&entry.length>120&&BULKY_PAYLOAD_KEYS.has(normalizeKey(key))?`[omitted ${entry.length} chars]`:sanitizeValue(entry);return out}return value}function serializeBounded(value){let serialized=JSON.stringify(sanitizeValue(value));if(serialized.length<=GENERIC_ARGS_MAX_CHARS)return serialized;let preview=serialized;for(;;){let wrapper=JSON.stringify({_truncated:!0,omittedChars:serialized.length-preview.length,preview});if(wrapper.length<=GENERIC_ARGS_MAX_CHARS)return wrapper;preview=preview.slice(0,preview.length-(wrapper.length-GENERIC_ARGS_MAX_CHARS))}}function maybeArgsRaw(_source,toolName,args){if(args===void 0||args===null)return;let value=args;if(typeof args==="string")try{value=JSON.parse(args)}catch{return args.length>BASH_COMMAND_MAX_CHARS?args.slice(0,BASH_COMMAND_MAX_CHARS):args}if(value!==null&&typeof value==="object"){let cmd=bashCommandOf(value);if(cmd!==void 0&&isShellTool(toolName))return cmd.length>BASH_COMMAND_MAX_CHARS?cmd.slice(0,BASH_COMMAND_MAX_CHARS):cmd;return serializeBounded(value)}return JSON.stringify(value)}function claudeSplit(raw,context){let entries=[],sessionId=s(raw.sessionId,raw.conversation_uuid)??"unknown",seq=typeof raw.seq==="number"?raw.seq:typeof raw.messageIndex==="number"?raw.messageIndex:0,ts=timestampOf(raw.ts,raw.timestamp,raw.createdAt),role=mapRole(raw.type??raw.role),recordType=String(raw.type??""),model=s(raw.model,o(raw.message).model),cwd=s(raw.cwd,raw.dir);if(raw.subtype==="turn_duration"&&typeof raw.durationMs==="number")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"system",record_type:"turn_duration",disposition:"meta",ts,duration_ms:raw.durationMs,content_text:null,provenance:"ambient"}}),entries;if(recordType==="attachment"||recordType.startsWith("file-history"))return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,provenance:"ambient"}}),entries;let usage=typeof raw.usage==="object"&&raw.usage!==null?raw.usage:o(raw.message).usage,inputTokens=raw.inputTokens??usage?.input_tokens,outputTokens=raw.outputTokens??usage?.output_tokens,cacheRead=usage?.cacheReadTokens??usage?.cache_read_tokens??usage?.cache_read_input_tokens,cacheWrite=usage?.cacheWriteTokens??usage?.cache_write_tokens??usage?.cache_creation_input_tokens,costUsd=computeCost(inputTokens,outputTokens,model),contentBlocks=raw.content??o(raw.message).content,contentText=extractContentText(contentBlocks),messageSplitIndex=entries.length;if(entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,turn_index:typeof raw.turnIndex==="number"?raw.turnIndex:void 0,role,record_type:recordType,disposition:"keep",ts,duration_ms:void 0,model:model??null,input_tokens:inputTokens??null,output_tokens:outputTokens??null,cache_read_tokens:cacheRead??null,cache_write_tokens:cacheWrite??null,cost_usd:costUsd??null,content_text:contentText??null,cwd:cwd??null,provenance:"ambient",request_id:s(raw.requestId)??null}}),Array.isArray(contentBlocks)&&role==="assistant")for(let block of contentBlocks){if(typeof block!=="object"||block===null)continue;let b=block;if(b.type==="tool_use")entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq,call_id:s(b.id),tool_name:String(b.name??""),args_digest:argsDigest(b.input),args_raw:maybeArgsRaw("claude",String(b.name??""),b.input),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function piSplit(raw,context){let msg=raw.message,recordType=String(raw.type??raw.recordType??""),sessionId=sessionIdFromContext(context,raw),seq=context?.sourceLine??(typeof raw.seq==="number"?raw.seq:0),ts=timestampOf(raw.timestamp,raw.createdAt,raw.ts);if(recordType==="title"||recordType==="title_change"||recordType==="service_tier_change"||recordType==="session_info"||recordType==="ttsr_injection"||recordType==="session_init"||recordType==="session"||recordType==="model_change"||recordType==="thinking_level_change"||recordType==="compaction"||recordType==="custom"||recordType==="custom_message"||recordType.startsWith("custom."))return[{targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,provenance:"ambient"}}];let entries=[],role=piRole(msg?.role??raw.role??recordType),model=s(raw.model,o(msg).model),cwd=s(raw.cwd,raw.dir),usage=msg?.usage??raw.usage,inputTokens=usage?.input??usage?.input_tokens??void 0,outputTokens=usage?.output??usage?.output_tokens??void 0,cacheRead=usage?.cacheRead??usage?.cache_read_tokens??void 0,cacheWrite=usage?.cacheWrite??usage?.cache_write_tokens??void 0,costObj=msg?.cost??raw.cost,costUsd=typeof costObj?.total==="number"?costObj.total:computeCost(inputTokens,outputTokens,model),contentBlocks=msg?.content??raw.content,durationMs=typeof msg?.duration==="number"&&Number.isFinite(msg.duration)?msg.duration:void 0,messageSplitIndex=entries.length;if(entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition:"keep",ts,duration_ms:durationMs,model:model??null,input_tokens:inputTokens??null,output_tokens:outputTokens??null,cache_read_tokens:cacheRead??null,cache_write_tokens:cacheWrite??null,cost_usd:costUsd??null,content_text:extractContentText(contentBlocks)??s(raw.content,raw.text,msg?.content)??null,cwd:cwd??null,provenance:"ambient"}}),Array.isArray(contentBlocks)&&role==="assistant")for(let block of contentBlocks){let call=normalizeOmpToolCall(block);if(call===null)continue;entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq,tool_name:String(call.name??""),call_id:s(call.id),args_digest:argsDigest(call.input??call.arguments),args_raw:maybeArgsRaw("pi",String(call.name??""),call.input??call.arguments),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function piRole(type){let t=String(type??"").toLowerCase();if(t==="toolresult"||t==="tool_result"||t==="bashexecution"||t==="tool")return"user";let mapped=mapRole(t);if(mapped==="user"||mapped==="assistant"||mapped==="system")return mapped;return"unknown"}function ompSplit(raw,context){let msg=raw.message,recordType=String(raw.type??""),sessionId=sessionIdFromContext(context,raw),seq=context?.sourceLine??(typeof raw.seq==="number"?raw.seq:0),ts=timestampOf(raw.ts,raw.timestamp,raw.createdAt);if(recordType==="title"||recordType==="title_change"||recordType==="service_tier_change"||recordType==="ttsr_injection"||recordType==="session_init"||recordType==="session"||recordType==="model_change"||recordType==="thinking_level_change"||recordType==="compaction"||recordType==="custom"||recordType==="custom_message"||recordType.startsWith("custom."))return[{targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,provenance:"ambient"}}];let entries=[],role=mapRole(msg?.role??raw.type??raw.role),model=s(raw.model,o(msg).model),cwd=s(raw.cwd,raw.dir),usage=msg?.usage??raw.usage,inputTokens=usage?.input??usage?.input_tokens??void 0,outputTokens=usage?.output??usage?.output_tokens??void 0,cacheRead=usage?.cacheRead??usage?.cache_read_tokens??void 0,cacheWrite=usage?.cacheWrite??usage?.cache_write_tokens??void 0,costObj=msg?.cost??raw.cost,costUsd=typeof costObj?.total==="number"?costObj.total:computeCost(inputTokens,outputTokens,model),contentBlocks=msg?.content??raw.content,durationMs=typeof msg?.duration==="number"&&Number.isFinite(msg.duration)?msg.duration:void 0,messageSplitIndex=entries.length;if(entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition:"keep",ts,duration_ms:durationMs,model:model??null,input_tokens:inputTokens??null,output_tokens:outputTokens??null,cache_read_tokens:cacheRead??null,cache_write_tokens:cacheWrite??null,cost_usd:costUsd??null,content_text:extractContentText(contentBlocks)??s(raw.content,raw.text,msg?.content)??null,cwd:cwd??null,provenance:"ambient"}}),Array.isArray(contentBlocks)&&role==="assistant")for(let block of contentBlocks){let call=normalizeOmpToolCall(block);if(call===null)continue;entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq,tool_name:String(call.name??""),call_id:s(call.id),args_digest:argsDigest(call.input??call.arguments),args_raw:maybeArgsRaw("omp",String(call.name??""),call.input??call.arguments),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function normalizeOmpToolCall(block){if(typeof block!=="object"||block===null)return null;let nested=o(block.toolCall);if(Object.keys(nested).length>0)return nested;if(block.type==="toolCall")return block;return null}function codexSplit(raw,context){let entries=[],payload=raw.payload??raw,seq=typeof raw.seq==="number"?raw.seq:0,ts=timestampOf(raw.timestamp,raw.ts,payload.ts),recordType=String(raw.type??""),payloadType=String(payload.type??""),isShortFormat=recordType===""&&raw.id!==void 0&&raw.timestamp!==void 0&&raw.instructions!==void 0,explicitSessionId=s(raw.session_id,o(raw.session_meta).id);if(explicitSessionId===void 0&&recordType==="session_meta")explicitSessionId=s(payload.id,o(raw.payload).id);if(explicitSessionId===void 0&&isShortFormat)explicitSessionId=s(raw.id);let pathSessionId=context?.sourceFile?sessionIdFromSourcePath("codex",context.sourceFile):void 0,sessionId=explicitSessionId??pathSessionId??"unknown";if(isShortFormat)return[{targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:"short_format",disposition:"meta",ts,provenance:"ambient"}}];let role,disposition,contentText,usage;if(recordType==="response_item")if(payloadType==="message")role=mapRole(payload.role),disposition="keep",contentText=extractContentText(payload.content)??s(payload.text)??null;else if(payloadType==="agent_message")role="assistant",disposition="keep",contentText=extractContentText(payload.content)??s(payload.text,payload.message)??null;else if(payloadType==="reasoning")role="assistant",disposition="keep",contentText=extractContentText(payload.summary)??s(payload.text)??null;else if(payloadType==="function_call"||payloadType==="custom_tool_call")role="tool",disposition="keep",contentText=null;else role="meta",disposition="meta",contentText=s(payload.text)??null;else if(recordType==="user"||recordType==="assistant")role=mapRole(recordType),disposition="keep",contentText=extractContentText(payload.content)??s(raw.content,payload.text)??null;else if(recordType==="message")role=mapRole(raw.role??payload.role),disposition="keep",contentText=extractContentText(payload.content??raw.content)??s(payload.text,raw.text)??null;else if(recordType==="event_msg")role="meta",disposition="meta",contentText=s(payload.message,payload.text)??null,usage=o(o(payload.info).last_token_usage);else role="meta",disposition="meta",contentText=s(payload.text,raw.instructions)??null;let model=s(raw.model,payload.model,o(o(raw.turn_context).payload).model),cwd=s(raw.cwd,raw.dir),tokenCount=payload.token_count,usageInput=usage?.input_tokens??tokenCount?.input??tokenCount?.input_tokens??void 0,usageOutput=usage?.output_tokens??tokenCount?.output??tokenCount?.output_tokens??void 0,cacheRead=usage?.cached_input_tokens??void 0,turnPayload=raw.turn_context?.payload,turnInputTokens=turnPayload?.input_tokens,turnOutputTokens=turnPayload?.output_tokens,finalInput=usageInput!==void 0?usageInput:turnInputTokens,finalOutput=usageOutput!==void 0?usageOutput:turnOutputTokens,costUsd=computeCost(finalInput,finalOutput,model),usageCarrier=finalInput!==void 0||finalOutput!==void 0?{input:finalInput??null,output:finalOutput??null,cacheRead:cacheRead??null}:void 0,stripUsage=role==="meta"&&usageCarrier!==void 0,messageSplitIndex=entries.length;entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition,ts,duration_ms:void 0,model:model??null,input_tokens:stripUsage?null:finalInput??null,output_tokens:stripUsage?null:finalOutput??null,cache_read_tokens:stripUsage?null:cacheRead??null,...usageCarrier!==void 0?{_codexUsageCarrier:usageCarrier}:{},cache_write_tokens:null,cost_usd:costUsd??null,content_text:contentText,cwd:cwd??null,provenance:"ambient"}});let toolItems=[];if((recordType==="response_item"||recordType==="function_call"||recordType==="custom_tool_call")&&(payloadType==="function_call"||payloadType==="custom_tool_call"))toolItems.push(payload);else if(payload.response_item)toolItems.push(payload.response_item);else if(Array.isArray(payload.response_items))toolItems.push(...payload.response_items);for(let item of toolItems){let fc=item.function_call??item,toolName=s(fc.name)??"",args=fc.arguments??fc.input;entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq,tool_name:toolName,call_id:s(fc.call_id),args_digest:argsDigest(args),args_raw:maybeArgsRaw("codex",toolName,args),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function agySplit(raw,context){let entries=[],recordType=String(raw.type??""),explicitSessionId=s(raw.session_id,raw.conversation_id,raw.conversationId),pathSessionId=context?.sourceFile?sessionIdFromSourcePath("agy",context.sourceFile):void 0,sessionId=explicitSessionId??pathSessionId??"unknown",seq=typeof raw.seq==="number"?raw.seq:typeof raw.step_index==="number"?raw.step_index:context?.sourceLine??0,ts=timestampOf(raw.created_at,raw.timestamp,raw.ts),role,disposition,contentText=null,messageRecordType=recordType;if(raw.display!==void 0)role="user",disposition="keep",contentText=s(raw.display)??null,messageRecordType=recordType.length>0?recordType:"USER_INPUT";else switch(recordType){case"USER_INPUT":case"ASK_QUESTION":role="user",disposition="keep",contentText=s(raw.content,raw.text,raw.message)??null;break;case"PLANNER_RESPONSE":role="assistant",disposition="keep",contentText=s(raw.content,raw.text,raw.message,raw.plan)??null;break;case"ERROR_MESSAGE":role="system",disposition="keep",contentText=s(raw.content,raw.text,raw.message)??null;break;case"RUN_COMMAND":case"VIEW_FILE":case"GREP_SEARCH":case"LIST_DIRECTORY":case"READ_URL_CONTENT":role="tool",disposition="keep",contentText=s(raw.content,raw.command,raw.file_path,raw.pattern)??null;break;case"CODE_ACTION":case"INVOKE_SUBAGENT":role="tool",disposition="keep",contentText=s(raw.content,raw.text)??null;break;case"CONVERSATION_HISTORY":case"CHECKPOINT":case"GENERIC":role="meta",disposition="meta",contentText=s(raw.content,raw.text)??null;break;default:if(recordType.length===0)role="unknown",disposition="unknown";else role="meta",disposition="meta",contentText=s(raw.content,raw.text)??null;break}let messageSplitIndex=entries.length;if(entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:messageRecordType,disposition,ts,duration_ms:void 0,model:null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:contentText,cwd:s(raw.workspace,raw.cwd)??null,provenance:"ambient"}}),recordType==="PLANNER_RESPONSE"&&Array.isArray(raw.tool_calls))for(let tc of raw.tool_calls)entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:messageSplitIndex,session_id:sessionId,seq:typeof tc.step_index==="number"?tc.step_index:seq,tool_name:String(tc.name??tc.tool_name??""),args_digest:argsDigest(tc.input??tc.arguments),args_raw:maybeArgsRaw("agy",String(tc.name??tc.tool_name??""),tc.input??tc.arguments),status:"ok",started_at:void 0,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:void 0}});for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex}))entries.push(skillCallEntry(record2));return entries}function geminiSplit(raw,context){let recordType=String(raw.type??(raw.kind!==void 0?"session":raw.$set!==void 0?"state":"")),state=o(raw.$set),sessionId=sessionIdFromContext(context,raw),seq=context?.sourceLine??0,ts=timestampOf(raw.timestamp,raw.startTime,raw.lastUpdated,state.lastUpdated);if(recordType==="session"||recordType==="state")return[{targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,content_text:s(state.summary)??null,provenance:"ambient"}}];let role=recordType==="gemini"?"assistant":recordType==="user"?"user":"system",tokens=o(raw.tokens),content=geminiContent(raw),entries=[{targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition:"keep",ts,duration_ms:null,model:s(raw.model)??null,input_tokens:numberOrNull(tokens.input),output_tokens:numberOrNull(tokens.output),cache_read_tokens:numberOrNull(tokens.cached),cache_write_tokens:null,cost_usd:null,content_text:content,cwd:null,provenance:"ambient"}}];if(Array.isArray(raw.toolCalls))for(let value of raw.toolCalls){if(value===null||typeof value!=="object"||Array.isArray(value))continue;let tool=value,status=s(tool.status)??"unknown",timestamp=s(tool.timestamp),result=tool.result??tool.resultDisplay;entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:0,session_id:sessionId,seq,tool_name:s(tool.name,tool.displayName)??"unknown",args_digest:argsDigest(tool.args),args_raw:maybeArgsRaw("gemini",s(tool.name,tool.displayName)??"",tool.args),status,started_at:timestamp,completed_at:timestamp,duration_ms:null,result_bytes:result===void 0?null:new TextEncoder().encode(JSON.stringify(result)).byteLength,error_text:status==="error"?s(tool.resultDisplay,tool.result)??null:null}})}for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex:0}))entries.push(skillCallEntry(record2));return entries}function dshSplit(raw,context){let recordType=String(raw.type??"");if(recordType==="session")return[{targetTable:"history_message",record:{session_id:s(raw.id)??sessionIdFromSourcePath("deepseek",context?.sourceFile??"")??"unknown",seq:0,role:"meta",record_type:"session",disposition:"meta",ts:timestampOf(raw.createdAt),cwd:s(raw.cwd)??null,content_text:null,provenance:"ambient"}}];if(recordType!=="user/message"&&recordType!=="assistant/message")return[];let data=o(raw.data),msg=o(data.message),seq=typeof raw.seq==="number"?raw.seq:context?.sourceLine??0,sessionId=sessionIdFromSourcePath("deepseek",context?.sourceFile??"")??"unknown",role=recordType==="user/message"?"user":"assistant",source=o(data.source??msg.source),model=s(source.model,o(data.model??msg.model).model),usage=data.usage??msg.usage,messageId=s(msg.id,data.id);return[{targetTable:"history_message",record:{session_id:sessionId,seq,role,record_type:recordType,disposition:"keep",...messageId!==void 0?{source_record_id:messageId}:{},ts:timestampOf(raw.time,data.time,msg.time),duration_ms:null,model:model??null,input_tokens:numberOrNull(usage?.input_tokens??usage?.input)??null,output_tokens:numberOrNull(usage?.output_tokens??usage?.output)??null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:extractContentText(data.content??msg.content)??s(data.text,msg.text)??null,cwd:null,provenance:"ambient"}}]}var UUID_PATTERN="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}",AGY_BRAIN_REGEX=new RegExp(`(?:^|\\/)brain\\/(${UUID_PATTERN})(?:\\/|$)`,"i"),DSH_SESSION_REGEX=new RegExp(`(?:^|\\/)session-(${UUID_PATTERN})(?:\\/|$)`,"i"),CODEX_ROLLOUT_REGEX=new RegExp(`(?:^|-|_)(${UUID_PATTERN})$`,"i");function sessionIdFromSourcePath(source,sourceFile){let normalized=sourceFile.replace(/\\/g,"/"),sLower=source.toLowerCase();if(sLower==="agy"||sLower==="antigravity")return normalized.match(AGY_BRAIN_REGEX)?.[1];if(sLower==="deepseek")return normalized.match(DSH_SESSION_REGEX)?.[1];if(sLower==="codex"){let basename=normalized.split("/").at(-1)??"";if(basename.startsWith("rollout-")&&basename.endsWith(".jsonl"))return basename.slice(0,-6).match(CODEX_ROLLOUT_REGEX)?.[1]}return}function sessionIdFromContext(context,raw){if(context!==void 0){let file2=context.sourceFile.split("/").at(-1);if(file2!==void 0)return file2.replace(/\.jsonl$/,"")}return s(raw.sessionId,raw.id)??"unknown"}function geminiContent(raw){let content=extractContentText(raw.content)??s(raw.text),thoughts=Array.isArray(raw.thoughts)?raw.thoughts.map((value)=>value!==null&&typeof value==="object"?s(o(value).description):void 0).filter((value)=>value!==void 0).join(`
508
- `):"";return[content,thoughts].filter((value)=>value!==void 0&&value.length>0).join(`
509
- `)||null}function numberOrNull(value){return typeof value==="number"&&Number.isFinite(value)?value:null}function normalizeGrokRecord(raw){let params=raw.params,update=params?.update,isUpdatesShape=typeof raw.method==="string"&&params!==void 0&&update!==void 0,body=isUpdatesShape?update:raw,recordType=String((isUpdatesShape?update?.sessionUpdate:raw.type)??raw.sessionUpdate??raw.eventType??(raw.file_snapshots!==void 0||raw.after_snapshots!==void 0?"file_snapshot":raw.prompt!==void 0?"user_message":raw.answer!==void 0||raw.question!==void 0?"assistant":"")),sessionId=s(params?.sessionId,raw.session_id,raw.sessionId,raw.parentSessionId,raw.btwSessionId,raw.params?.sessionId)??"unknown",ts=normalizeTs(raw.ts??raw.timestamp??raw.created_at??raw.askedAt??body.ts??body.timestamp),seq=typeof raw.seq==="number"?raw.seq:typeof body.seq==="number"?body.seq:0,meta3=body._meta??params?._meta??raw._meta,model=s(meta3?.modelId,body.model,raw.model),contentText=extractGrokContent(body.content??body.text??raw.content??raw.text??raw.prompt??(raw.answer!==void 0||raw.question!==void 0?[raw.question,raw.answer].filter((value)=>typeof value==="string").join(`
510
- `):void 0)),usage=body.usage??raw.usage,toolMeta=meta3?.["x.ai/tool"],titleFallback=s(body.title)?.split("`")[0]?.trim(),toolName=s(toolMeta?.name,body.kind,body.tool_name,body.name,raw.tool_name,raw.name)??(titleFallback!==void 0&&titleFallback.length>0&&titleFallback.length<=40?titleFallback:""),toolArgs=body.rawInput??body.input??body.arguments??toolMeta?.input??raw.input??raw.arguments,toolStatus=s(body.status,raw.outcome,raw.status)??"ok",durationMs=typeof body.duration_ms==="number"?body.duration_ms:typeof raw.duration_ms==="number"?raw.duration_ms:typeof usage?.apiDurationMs==="number"?usage.apiDurationMs:void 0,errorText=body.error!==void 0?String(body.error):raw.error!==void 0?String(raw.error):void 0,hasTypeDiscriminator=recordType.length>0||isUpdatesShape;return{recordType,sessionId,ts,seq,body,model,contentText,usage,toolName,toolArgs,toolStatus,durationMs,errorText,hasTypeDiscriminator}}function normalizeTs(value){return timestampOf(value)}function extractGrokContent(content){if(typeof content==="string")return content;if(content!==null&&typeof content==="object"&&!Array.isArray(content)){let c=content;if(typeof c.text==="string")return c.text;if(typeof c.content==="string")return c.content}if(Array.isArray(content)){let parts=[];for(let block of content)if(typeof block==="string")parts.push(block);else if(block!==null&&typeof block==="object"){let b=block;if(typeof b.text==="string")parts.push(b.text)}return parts.length>0?parts.join(`
511
- `):null}return null}var GROK_META_TYPES=new Set(["phase_changed","permission_requested","permission_resolved","mcp_server_starting","mcp_server_connected","mcp_config_resolved","mcp_managed_config_result","mcp_transport_decode_error","mcp_init_completed","mcp_health_check","loop_started","first_token","agent_thought_chunk","hook_execution","plan","session_recap","task_backgrounded","task_completed","retry_state","auto_compact_started","auto_compact_completed","compaction_checkpoint","image_compressed","reasoning","system","turn_started","turn_ended","yolo_toggled"]);function grokSplit(raw,context){let entries=[],n=normalizeGrokRecord(raw),{recordType,sessionId,ts,seq}=n;if(recordType==="turn_completed"){let usage=n.usage,modelUsage=usage?.modelUsage,modelFromUsage=modelUsage!==null&&typeof modelUsage==="object"?Object.keys(modelUsage)[0]:void 0,model=s(n.model,modelFromUsage),inputTokens=usage?.inputTokens??usage?.input??usage?.input_tokens,outputTokens=usage?.outputTokens??usage?.output??usage?.output_tokens,cacheRead=usage?.cachedReadTokens??usage?.cache_read_tokens;return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:n.durationMs??usage?.apiDurationMs??null,model:model??null,input_tokens:inputTokens??null,output_tokens:outputTokens??null,cache_read_tokens:cacheRead??null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries}if(recordType==="tool_started")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:void 0,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:0,session_id:sessionId,seq,tool_name:n.toolName,args_digest:argsDigest(n.toolArgs),args_raw:maybeArgsRaw("grok",n.toolName,n.toolArgs),status:n.toolStatus||"ok",started_at:ts,completed_at:void 0,duration_ms:void 0,result_bytes:void 0,error_text:n.errorText}}),entries;if(recordType==="tool_completed")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:n.durationMs??null,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:0,session_id:sessionId,seq,tool_name:n.toolName,args_digest:null,args_raw:void 0,status:n.toolStatus||"ok",started_at:void 0,completed_at:ts,duration_ms:n.durationMs,result_bytes:void 0,error_text:n.errorText}}),entries;if(recordType==="tool_call"||recordType==="tool_call_update"){entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:void 0,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries.push({targetTable:"history_tool_call",record:{_messageSplitIndex:0,session_id:sessionId,seq,tool_name:n.toolName,args_digest:argsDigest(n.toolArgs),args_raw:maybeArgsRaw("grok",n.toolName,n.toolArgs),status:n.toolStatus||"ok",started_at:recordType==="tool_call"?ts:void 0,completed_at:recordType==="tool_call_update"?ts:void 0,duration_ms:n.durationMs,result_bytes:void 0,error_text:n.errorText}});for(let record2 of extractSkillCalls(raw,context,{sessionId,seq,messageSplitIndex:0}))entries.push(skillCallEntry(record2));return entries}if(recordType==="user"||recordType==="user_message"||recordType==="user_message_chunk"||recordType==="message")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"user",record_type:recordType||"user_message",disposition:"keep",ts,duration_ms:void 0,model:null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries;if(recordType==="assistant"||recordType==="agent_message_chunk")return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"assistant",record_type:recordType,disposition:"keep",ts,duration_ms:void 0,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries;if(GROK_META_TYPES.has(recordType))return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,duration_ms:n.durationMs??null,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries;if(!n.hasTypeDiscriminator||recordType.length===0)return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"unknown",record_type:stableFieldShape(raw),disposition:"unknown",ts,duration_ms:void 0,model:null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries;return entries.push({targetTable:"history_message",record:{session_id:sessionId,seq,role:"meta",record_type:recordType,disposition:"meta",ts,duration_ms:n.durationMs??null,model:n.model??null,input_tokens:null,output_tokens:null,cache_read_tokens:null,cache_write_tokens:null,cost_usd:null,content_text:n.contentText,cwd:null,provenance:"ambient"}}),entries}function o(value){return typeof value==="object"&&value!==null?value:{}}function s(...values){for(let value of values){if(typeof value==="string"&&value.length>0)return value;if(typeof value==="number"&&Number.isFinite(value))return String(value)}return}function timestampOf(...values){for(let value of values){if(typeof value==="number"&&Number.isFinite(value)){let ms=value>1000000000000?value:value*1000;return new Date(ms).toISOString()}if(typeof value==="string"&&value.length>0){let asNum=Number(value);if(Number.isFinite(asNum)&&/^\d+(\.\d+)?$/.test(value.trim())){let ms=asNum>1000000000000?asNum:asNum*1000;return new Date(ms).toISOString()}return value}}return}function mapRole(type){let t=String(type??"").toLowerCase();if(t==="user"||t==="human"||t==="developer")return"user";if(t==="assistant"||t==="ai"||t==="model")return"assistant";if(t==="system"||t==="error")return"system";return t||"unknown"}function computeCost(inputTokens,outputTokens,model){if(inputTokens===void 0||inputTokens===null)return;if(outputTokens===void 0||outputTokens===null)return;let inputRate=model?.toLowerCase().includes("claude")?3:1,outputRate=model?.toLowerCase().includes("claude")?15:5;return(inputTokens*inputRate+outputTokens*outputRate)/1e6}function extractContentText(content){if(typeof content==="string")return content;if(!Array.isArray(content))return;let parts=[];for(let block of content){if(typeof block!=="object"||block===null)continue;let b=block;if(typeof b.text==="string")parts.push(b.text)}return parts.length>0?parts.join(`
512
- `):void 0}function stableFieldShape(raw){return Object.keys(raw).map((k)=>k.toLowerCase()).sort().join("+")}var CLAUDE_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),PI_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),OMP_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),CODEX_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),AGY_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),GROK_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),GEMINI_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS,SKILL_CALL_MAPPER_KEYS)),DSH_FIELD_MAP=identityFieldMap(MESSAGE_MAPPER_KEYS.concat(["source_record_id"])),passthroughSchema=exports_external.object({}).passthrough(),CLAUDE_SCHEMA=passthroughSchema,PI_SCHEMA=passthroughSchema,OMP_SCHEMA=passthroughSchema,CODEX_SCHEMA=passthroughSchema,AGY_SCHEMA=passthroughSchema,GROK_SCHEMA=passthroughSchema,GEMINI_SCHEMA=passthroughSchema,DSH_SCHEMA=passthroughSchema;var sourceRecordSchema=exports_external.object({source_record_id:exports_external.string().min(1),created_at:exports_external.string().min(1),content:exports_external.string().min(1),role:exports_external.string().optional(),model:exports_external.string().optional()}).passthrough();function firstString(...values){for(let value of values){if(typeof value==="string"&&value.length>0)return value;if(typeof value==="number"&&Number.isFinite(value))return String(value)}return}function defaultCreatedAt(value){return firstString(value)??new Date(0).toISOString()}function defaultRecordId(value,raw,context){return firstString(value,raw.id,raw.uuid,raw.message_id,raw.messageId,raw.session_id,raw.sessionId,raw.conversation_id)??`${context.source}:${context.sourceFile}:${context.sourceLine}:${context.splitIndex}`}function defaultContent(value,raw){return firstString(value,raw.content,raw.text,raw.message,raw.prompt,raw.response,raw.output)}function transforms(){return{source_record_id:defaultRecordId,created_at:defaultCreatedAt,content:defaultContent,role:(value,raw)=>firstString(value,raw.role,raw.type),model:(value,raw)=>firstString(value,raw.model,raw.model_name,raw.modelName)}}function sourceDefinition(source,displayName,defaultRoots,filePatterns){return{source,displayName,defaultRoots,filePatterns,targetTable:`history_etl_${source}`,splitConfig:source==="pi"?{mode:"one-to-many",field:"messages"}:{mode:"one-to-one"},fieldMap:{id:"source_record_id",uuid:"source_record_id",message_id:"source_record_id",messageId:"source_record_id",session_id:"source_record_id",sessionId:"source_record_id",conversation_id:"source_record_id",timestamp:"created_at",created_at:"created_at",createdAt:"created_at",time:"created_at",content:"content",text:"content",message:"content",prompt:"content",response:"content",output:"content",role:"role",type:"role",model:"model",model_name:"model",modelName:"model"},fieldTransforms:transforms(),schema:sourceRecordSchema}}function customSourceDefinition(source,displayName,defaultRoots,filePatterns,split,fieldMap,schema){return{source,displayName,defaultRoots,filePatterns,targetTable:`history_etl_${source}`,splitConfig:{mode:"custom",split},fieldMap,fieldTransforms:{},schema}}var SOURCE_DEFINITIONS={pi:customSourceDefinition("pi","Pi",[".pi/agent/sessions"],["*.jsonl"],piSplit,PI_FIELD_MAP,PI_SCHEMA),claude:customSourceDefinition("claude","Claude Code",[".claude/projects"],["*.jsonl"],claudeSplit,CLAUDE_FIELD_MAP,CLAUDE_SCHEMA),codex:customSourceDefinition("codex","Codex",[".codex/sessions"],["*.jsonl"],codexSplit,CODEX_FIELD_MAP,CODEX_SCHEMA),omp:customSourceDefinition("omp","OMP",[".omp/agent/sessions"],["*.jsonl"],ompSplit,OMP_FIELD_MAP,OMP_SCHEMA),grok:customSourceDefinition("grok","Grok",[".grok/sessions"],["*.jsonl"],grokSplit,GROK_FIELD_MAP,GROK_SCHEMA),agy:{...customSourceDefinition("agy","Antigravity CLI",[".gemini/antigravity-cli"],["*.jsonl"],agySplit,AGY_FIELD_MAP,AGY_SCHEMA),corruptLinePolicy:"skip"},gemini:customSourceDefinition("gemini","Gemini CLI",[".gemini/tmp",".config/gemini"],["*.jsonl"],geminiSplit,GEMINI_FIELD_MAP,GEMINI_SCHEMA),deepseek:{...customSourceDefinition("deepseek","DeepSeek dsh",[".dsh/sessions"],["session.v3.jsonl","session.v3.jsonl.zstd"],dshSplit,DSH_FIELD_MAP,DSH_SCHEMA),corruptLinePolicy:"skip"},opencode:sourceDefinition("opencode","OpenCode",[".opencode",".local/share/opencode"],["*.jsonl"]),antigravity:sourceDefinition("antigravity","Antigravity",[".antigravity"],["*.jsonl"]),openclaw:sourceDefinition("openclaw","OpenClaw",[".openclaw"],["*.jsonl"])};var TYPED_HISTORY_TABLES=["history_message","history_tool_call","history_skill_call"];var BOOKKEEPING_HISTORY_TABLES=["history_import_checkpoint","history_import_ledger"],IMPORTER_OWNED_TABLES=[...TYPED_HISTORY_TABLES,...BOOKKEEPING_HISTORY_TABLES,...Object.values(SOURCE_DEFINITIONS).map((def)=>def.targetTable)];var SPUR_OWNED_HISTORY_TABLES=["history_run_session","history_task_session","history_tool_alias_map","history_daily_stats","history_board_loop_findings","history_board_message_5m","history_board_model_stats","history_board_ranked_steps","history_board_rollup_meta","history_board_rollup_watermark","history_board_rollup_bucket","history_board_session_stats","history_board_skill_5m","history_board_source_daily","history_board_source_stats","history_board_dimension_daily","history_board_kpi_window","history_board_tool_5m","history_board_tool_stats"],HISTORY_RESET_TABLES=[...IMPORTER_OWNED_TABLES,...SPUR_OWNED_HISTORY_TABLES];var IMPORTER_SCHEMA_LEDGER_PREFIX="importer_schema@";class ActionRunDao{db;constructor(db2){this.db=db2}async completedAtById(id){return(await this.db.queryFirst("SELECT completed_at FROM action_runs WHERE id = ?",id))?.completed_at??null}async setStartedAt(id,startedAt){await this.db.run("UPDATE action_runs SET started_at = ? WHERE id = ?",startedAt,id)}async actionRowsByRunId(runId){try{return await this.db.queryAll("SELECT id, node, kind, status, duration_ms, ok, result_json, started_at, completed_at, created_at FROM action_runs WHERE run_id = ? ORDER BY created_at",runId)}catch(error51){if(error51 instanceof Error&&error51.message.includes("no such table: action_runs"))return[];throw error51}}}init_dist4();init_schema();init_schema();init_schema();var workspacesTable=defineTable("workspaces",{id:text("id").primaryKey(),name:text("name").notNull().unique(),root:text("root").notNull(),purpose:text("purpose"),defaultAgent:text("default_agent"),...standardColumns}),workspaces=workspacesTable.table;var runsTable=defineTable("runs",{id:text("id").primaryKey(),workspaceId:text("workspace_id").references(()=>workspaces.id),workflowName:text("workflow_name"),mode:text("mode"),status:text("status").notNull(),agent:text("agent"),externalKey:text("external_key"),startedAt:integer2("started_at").notNull(),completedAt:integer2("completed_at"),metadataJson:text("metadata_json").notNull().default("{}"),...standardColumns}),runs=runsTable.table;var artifactsTable=defineTable("artifacts",{id:text("id").primaryKey(),runId:text("run_id").references(()=>runs.id),path:text("path").notNull(),kind:text("kind").notNull(),...standardColumns}),artifacts=artifactsTable.table;function createId(prefix){return`${prefix}_${crypto.randomUUID()}`}class ArtifactDao extends EntityDao{constructor(adapter){super(adapter,artifacts,[artifacts.id],"artifacts")}record(input){return super.create({id:createId("artifact"),runId:input.runId??null,path:input.path,kind:input.kind})}artifactsByRunId(runId){return this.adapter.queryAll("SELECT path, kind FROM artifacts WHERE run_id = ? ORDER BY id",runId)}artifactsWithIdByRunId(runId){return this.adapter.queryAll("SELECT id, path, kind FROM artifacts WHERE run_id = ? ORDER BY id",runId)}}init_schema();var phaseRunsTable=defineTable("phase_runs",{id:text("id").primaryKey(),runId:text("run_id").notNull().references(()=>runs.id),phase:text("phase").notNull(),status:text("status").notNull(),startedAt:integer2("started_at"),completedAt:integer2("completed_at"),...standardColumns}),phaseRuns=phaseRunsTable.table;init_dist4();function normalizePersistedWorkflowLayer(layer){if(layer==="bundled")return"shared";if(layer==="project"||layer==="registered"||layer==="shared")return layer;return null}class RunDao extends EntityDao{constructor(adapter){super(adapter,runs,[runs.id],"runs")}open(input={}){return super.create({id:createId("run"),workspaceId:input.workspaceId??null,status:input.status??"pending",agent:input.agent??null,startedAt:Date.now(),completedAt:null})}traceRows(filter){return this.adapter.queryAll(`SELECT id, workflow_name, mode, status, agent, started_at, completed_at, metadata_json
512
+ `.trim();init_zod();var sourceRecordSchema=exports_external.object({source_record_id:exports_external.string().min(1),created_at:exports_external.string().min(1),content:exports_external.string().min(1),role:exports_external.string().optional(),model:exports_external.string().optional()}).passthrough();function firstString(...values){for(let value of values){if(typeof value==="string"&&value.length>0)return value;if(typeof value==="number"&&Number.isFinite(value))return String(value)}return}function defaultCreatedAt(value){return firstString(value)??new Date(0).toISOString()}function defaultRecordId(value,raw,context){return firstString(value,raw.id,raw.uuid,raw.message_id,raw.messageId,raw.session_id,raw.sessionId,raw.conversation_id)??`${context.source}:${context.sourceFile}:${context.sourceLine}:${context.splitIndex}`}function defaultContent(value,raw){return firstString(value,raw.content,raw.text,raw.message,raw.prompt,raw.response,raw.output)}function transforms(){return{source_record_id:defaultRecordId,created_at:defaultCreatedAt,content:defaultContent,role:(value,raw)=>firstString(value,raw.role,raw.type),model:(value,raw)=>firstString(value,raw.model,raw.model_name,raw.modelName)}}function sourceDefinition(source,displayName,defaultRoots,filePatterns){return{source,displayName,defaultRoots,filePatterns,targetTable:`history_etl_${source}`,splitConfig:source==="pi"?{mode:"one-to-many",field:"messages"}:{mode:"one-to-one"},fieldMap:{id:"source_record_id",uuid:"source_record_id",message_id:"source_record_id",messageId:"source_record_id",session_id:"source_record_id",sessionId:"source_record_id",conversation_id:"source_record_id",timestamp:"created_at",created_at:"created_at",createdAt:"created_at",time:"created_at",content:"content",text:"content",message:"content",prompt:"content",response:"content",output:"content",role:"role",type:"role",model:"model",model_name:"model",modelName:"model"},fieldTransforms:transforms(),schema:sourceRecordSchema}}function customSourceDefinition(source,displayName,defaultRoots,filePatterns,split,fieldMap,schema){return{source,displayName,defaultRoots,filePatterns,targetTable:`history_etl_${source}`,splitConfig:{mode:"custom",split},fieldMap,fieldTransforms:{},schema}}var SOURCE_DEFINITIONS={pi:customSourceDefinition("pi","Pi",[".pi/agent/sessions"],["*.jsonl"],piSplit,PI_FIELD_MAP,PI_SCHEMA),claude:customSourceDefinition("claude","Claude Code",[".claude/projects"],["*.jsonl"],claudeSplit,CLAUDE_FIELD_MAP,CLAUDE_SCHEMA),codex:customSourceDefinition("codex","Codex",[".codex/sessions"],["*.jsonl"],codexSplit,CODEX_FIELD_MAP,CODEX_SCHEMA),omp:customSourceDefinition("omp","OMP",[".omp/agent/sessions"],["*.jsonl"],ompSplit,OMP_FIELD_MAP,OMP_SCHEMA),grok:customSourceDefinition("grok","Grok",[".grok/sessions"],["*.jsonl"],grokSplit,GROK_FIELD_MAP,GROK_SCHEMA),agy:{...customSourceDefinition("agy","Antigravity CLI",[".gemini/antigravity-cli"],["*.jsonl"],agySplit,AGY_FIELD_MAP,AGY_SCHEMA),corruptLinePolicy:"skip"},gemini:customSourceDefinition("gemini","Gemini CLI",[".gemini/tmp",".config/gemini"],["*.jsonl"],geminiSplit,GEMINI_FIELD_MAP,GEMINI_SCHEMA),deepseek:{...customSourceDefinition("deepseek","DeepSeek dsh",[".dsh/sessions"],["session.v3.jsonl","session.v3.jsonl.zstd"],dshSplit,DSH_FIELD_MAP,DSH_SCHEMA),corruptLinePolicy:"skip"},opencode:sourceDefinition("opencode","OpenCode",[".opencode",".local/share/opencode"],["*.jsonl"]),antigravity:sourceDefinition("antigravity","Antigravity",[".antigravity"],["*.jsonl"]),openclaw:sourceDefinition("openclaw","OpenClaw",[".openclaw"],["*.jsonl"])};var TYPED_HISTORY_TABLES=["history_message","history_tool_call","history_skill_call"];var BOOKKEEPING_HISTORY_TABLES=["history_import_checkpoint","history_import_ledger"],IMPORTER_OWNED_TABLES=[...TYPED_HISTORY_TABLES,...BOOKKEEPING_HISTORY_TABLES,...Object.values(SOURCE_DEFINITIONS).map((def)=>def.targetTable)];var SPUR_OWNED_HISTORY_TABLES=["history_run_session","history_task_session","history_tool_alias_map","history_daily_stats","history_board_loop_findings","history_board_message_5m","history_board_model_stats","history_board_ranked_steps","history_board_rollup_meta","history_board_rollup_watermark","history_board_rollup_bucket","history_board_session_stats","history_board_skill_5m","history_board_source_daily","history_board_source_stats","history_board_dimension_daily","history_board_kpi_window","history_board_tool_5m","history_board_tool_stats"],HISTORY_RESET_TABLES=[...IMPORTER_OWNED_TABLES,...SPUR_OWNED_HISTORY_TABLES];var IMPORTER_SCHEMA_LEDGER_PREFIX="importer_schema@";class ActionRunDao{db;constructor(db2){this.db=db2}async completedAtById(id){return(await this.db.queryFirst("SELECT completed_at FROM action_runs WHERE id = ?",id))?.completed_at??null}async setStartedAt(id,startedAt){await this.db.run("UPDATE action_runs SET started_at = ? WHERE id = ?",startedAt,id)}async actionRowsByRunId(runId){try{return await this.db.queryAll("SELECT id, node, kind, status, duration_ms, ok, result_json, started_at, completed_at, created_at FROM action_runs WHERE run_id = ? ORDER BY created_at",runId)}catch(error51){if(error51 instanceof Error&&error51.message.includes("no such table: action_runs"))return[];throw error51}}}init_dist4();init_schema();init_schema();init_schema();var workspacesTable=defineTable("workspaces",{id:text("id").primaryKey(),name:text("name").notNull().unique(),root:text("root").notNull(),purpose:text("purpose"),defaultAgent:text("default_agent"),...standardColumns}),workspaces=workspacesTable.table;var runsTable=defineTable("runs",{id:text("id").primaryKey(),workspaceId:text("workspace_id").references(()=>workspaces.id),workflowName:text("workflow_name"),mode:text("mode"),status:text("status").notNull(),agent:text("agent"),externalKey:text("external_key"),startedAt:integer2("started_at").notNull(),completedAt:integer2("completed_at"),metadataJson:text("metadata_json").notNull().default("{}"),...standardColumns}),runs=runsTable.table;var artifactsTable=defineTable("artifacts",{id:text("id").primaryKey(),runId:text("run_id").references(()=>runs.id),path:text("path").notNull(),kind:text("kind").notNull(),...standardColumns}),artifacts=artifactsTable.table;function createId(prefix){return`${prefix}_${crypto.randomUUID()}`}class ArtifactDao extends EntityDao{constructor(adapter){super(adapter,artifacts,[artifacts.id],"artifacts")}record(input){return super.create({id:createId("artifact"),runId:input.runId??null,path:input.path,kind:input.kind})}artifactsByRunId(runId){return this.adapter.queryAll("SELECT path, kind FROM artifacts WHERE run_id = ? ORDER BY id",runId)}artifactsWithIdByRunId(runId){return this.adapter.queryAll("SELECT id, path, kind FROM artifacts WHERE run_id = ? ORDER BY id",runId)}}init_schema();var phaseRunsTable=defineTable("phase_runs",{id:text("id").primaryKey(),runId:text("run_id").notNull().references(()=>runs.id),phase:text("phase").notNull(),status:text("status").notNull(),startedAt:integer2("started_at"),completedAt:integer2("completed_at"),...standardColumns}),phaseRuns=phaseRunsTable.table;init_dist4();function normalizePersistedWorkflowLayer(layer){if(layer==="bundled")return"shared";if(layer==="project"||layer==="registered"||layer==="shared")return layer;return null}class RunDao extends EntityDao{constructor(adapter){super(adapter,runs,[runs.id],"runs")}open(input={}){return super.create({id:createId("run"),workspaceId:input.workspaceId??null,status:input.status??"pending",agent:input.agent??null,startedAt:Date.now(),completedAt:null})}traceRows(filter){return this.adapter.queryAll(`SELECT id, workflow_name, mode, status, agent, started_at, completed_at, metadata_json
513
513
  FROM runs
514
514
  WHERE (?1 IS NULL OR workflow_name = ?1)
515
515
  AND (?2 IS NULL OR status = ?2)
@@ -520,7 +520,7 @@ CREATE INDEX IF NOT EXISTS idx_history_skill_call_invocation_kind
520
520
  OR (started_at = ?4 AND id < ?5)
521
521
  )
522
522
  ORDER BY started_at DESC, id DESC
523
- LIMIT ?6`,filter.workflow??null,filter.status??null,filter.since??null,filter.before?.started_at??null,filter.before?.id??null,filter.limit)}traceRowById(runId){return this.adapter.queryFirst("SELECT id, workflow_name, mode, status, agent, started_at, completed_at, metadata_json FROM runs WHERE id = ?",runId)}mergeMetadata(runId,patch){return this.adapter.run(`UPDATE runs
523
+ LIMIT ?6`,filter.workflow??null,filter.status??null,filter.since??null,filter.before?.started_at??null,filter.before?.id??null,filter.limit)}traceRowById(runId){return this.adapter.queryFirst("SELECT id, workflow_name, mode, status, agent, started_at, completed_at, terminal_reason, metadata_json FROM runs WHERE id = ?",runId)}mergeMetadata(runId,patch){return this.adapter.run(`UPDATE runs
524
524
  SET metadata_json = json_patch(
525
525
  COALESCE(NULLIF(metadata_json, ''), '{}'),
526
526
  ?1
@@ -551,7 +551,7 @@ CREATE INDEX IF NOT EXISTS idx_history_skill_call_invocation_kind
551
551
  ORDER BY started_at ASC`,cutoffIso)}async finalizeStale(runId,reason){let nowIso=new Date().toISOString();await this.adapter.run(`UPDATE runs
552
552
  SET status = 'failed', completed_at = ?1, updated_at = ?1,
553
553
  metadata_json = json_set(COALESCE(NULLIF(metadata_json, ''), '{}'), '$.staleReason', ?2)
554
- WHERE id = ?3 AND status IN ('running', 'pending')`,nowIso,reason,runId)}async setPid(runId,pid){await this.adapter.run("UPDATE runs SET pid = ? WHERE id = ?",pid,runId)}async getPid(runId){return(await this.adapter.queryFirst("SELECT pid FROM runs WHERE id = ?",runId))?.pid??null}}init_schema();var transitionRunsTable=defineTable("transition_runs",{id:text("id").primaryKey(),runId:text("run_id").notNull().references(()=>runs.id),fromState:text("from_state").notNull(),toState:text("to_state").notNull(),trigger:text("trigger"),status:text("status").notNull(),...standardColumns}),transitionRuns=transitionRunsTable.table;init_schema();var workflowStatesTable=defineTable("workflow_states",{id:text("id").primaryKey(),runId:text("run_id").notNull().references(()=>runs.id),state:text("state").notNull(),dataJson:text("data_json").notNull(),...standardColumns}),workflowStates=workflowStatesTable.table;init_dist6();class WorkflowValidationError extends Error{details;constructor(message,details){super(message);this.details=details,this.name="WorkflowValidationError"}}class FSMError extends Error{details;constructor(message,details){super(message);this.details=details,this.name="FSMError"}}class RunCollisionError extends Error{constructor(runId){super(`Workflow run "${runId}" already exists`);this.name="RunCollisionError"}}class WorkflowResumeError extends Error{details;constructor(message,details){super(message);this.details=details,this.name="WorkflowResumeError"}}init_dist7();init_dist6();var RUNTIME_BUILTIN_KEYS=["workflow","runId","task","state","node","iteration","run","runtime"];function runtimeBuiltins(workflowName,stateOrNodeId,runId,transitionsTaken,mode){return{workflow:workflowName,runId,task:workflowName,state:stateOrNodeId,node:stateOrNodeId,iteration:transitionsTaken,run:runId,runtime:mode}}function allowedEnv(names,source=getProcessEnv()){return Object.fromEntries(names.flatMap((name)=>source[name]===void 0?[]:[[name,source[name]]]))}class RunLifecycle{workflowName;mode;runId;externalKey;persistence;events;logger;ownerAttempt;constructor(runId,workflowName,mode,deps,externalKey){this.workflowName=workflowName,this.mode=mode,this.runId=runId,this.externalKey=externalKey,this.persistence=deps.persistence,this.events=deps.events??(deps.lifecycleBus?new EventBus({lifecycleBus:deps.lifecycleBus}):void 0),this.logger=(deps.logger??getLogger2("workflow")).child({runId,workflow:workflowName,mode})}static forExternalTransition(workflowName,runId,deps,externalKey){return new RunLifecycle(runId,workflowName,"state-machine",deps,externalKey)}static async run(workflowName,mode,deps,options,loop){return await traceAsync("workflow.run",async()=>{let startedAt=new Date().toISOString(),proposed={...RunLifecycle.runRecord(options.runId??crypto.randomUUID(),workflowName,mode,startedAt,options.metadata,options.externalKey),owner_attempt:crypto.randomUUID()},record2=proposed;if(options.externalKey===void 0)await deps.persistence.createRun(proposed);else if(record2=await deps.persistence.createOrAttachRun(proposed),record2.owner_attempt!==proposed.owner_attempt){let snapshot=await deps.persistence.loadLatestStateSnapshot(record2.id);return{runId:record2.id,workflowName:record2.workflow_name,mode:record2.mode==="transition-flow"?"transition-flow":"state-machine",status:record2.status,finalState:snapshot?.state??"",transitionsTaken:snapshotTransitions(snapshot?.data)}}let extKey=record2.external_key??void 0,lifecycle=new RunLifecycle(record2.id,workflowName,mode,deps,extKey);return lifecycle.ownerAttempt=proposed.owner_attempt??void 0,lifecycle.logger.info("workflow run started"),addSpanEvent("workflow.run.started",{workflowName,mode,runId:lifecycle.runId,dryRun:options.dryRun??!1}),lifecycle.events?.emit("workflow.run.started",{workflowName,mode,runId:lifecycle.runId,dryRun:options.dryRun??!1,externalKey:extKey,severity:"info"}),await lifecycle.execute(loop)},{attributes:{"workflow.name":workflowName,"workflow.mode":mode}})}static async resume(workflowName,mode,deps,runId,externalKey,loop,ownerAttempt){return await traceAsync("workflow.run",async()=>{let lifecycle=new RunLifecycle(runId,workflowName,mode,deps,externalKey);return lifecycle.ownerAttempt=ownerAttempt,lifecycle.logger.info("workflow run resumed"),await lifecycle.execute(loop)},{attributes:{"workflow.name":workflowName,"workflow.mode":mode}})}async finalizeAsOwner(status,completedAt){if(this.ownerAttempt===void 0){await this.persistence.finalizeRun(this.runId,status,completedAt);return}if(await this.persistence.finalizeRun(this.runId,status,completedAt,{ownerAttempt:this.ownerAttempt})===!1)throw this.events?.emit("workflow.run.stale_owner",{runId:this.runId,ownerAttemptId:this.ownerAttempt,status,severity:"warning"}),new WorkflowResumeError(`stale owner "${this.ownerAttempt}" cannot finalize run "${this.runId}" as "${status}": ownership was lost`)}async execute(loop){try{return await loop(this)}catch(error51){try{await this.finalizeAsOwner("failed",new Date().toISOString())}catch(finalizeError){throw AggregateError([error51,finalizeError],"Workflow execution and failure persistence failed")}throw error51}}async enter(stateOrNodeId,transitionsTaken,persist=!0,vars){if(persist){let data={transitionsTaken};if(vars!==void 0)data.effectiveVars=vars;await this.persistence.saveWorkflowState(this.runId,stateOrNodeId,data),await this.persistence.savePhase(this.runId,stateOrNodeId,"running")}addSpanEvent("workflow.node.enter",{runId:this.runId,node:stateOrNodeId,transitionsTaken}),this.events?.emit("workflow.node.enter",{runId:this.runId,node:stateOrNodeId,transitionsTaken,severity:"info"})}async commitHop(from,to,trigger,transitionsTaken,phase,vars){let data={transitionsTaken};if(vars!==void 0)data.effectiveVars=vars;await this.persistence.commitTransition(this.runId,from,to,trigger,to,data,phase),addSpanEvent("workflow.node.transition",{runId:this.runId,from,to,...trigger===null?{}:{trigger}}),this.events?.emit("workflow.node.transition",{runId:this.runId,from,to,trigger,externalKey:this.externalKey,severity:"info"})}async recordTransition(from,to,trigger){await this.persistence.saveTransition(this.runId,from,to,trigger),addSpanEvent("workflow.node.transition",{runId:this.runId,from,to,...trigger===null?{}:{trigger}}),this.events?.emit("workflow.node.transition",{runId:this.runId,from,to,trigger,externalKey:this.externalKey,severity:"info"})}async done(finalState,transitionsTaken){return await this.persistence.savePhase(this.runId,finalState,"done"),await this.finalizeAsOwner("done",new Date().toISOString()),this.logger.info("workflow run done",{finalState,transitionsTaken}),addSpanEvent("workflow.run.done",{runId:this.runId,finalState,transitionsTaken}),this.events?.emit("workflow.run.done",{runId:this.runId,finalState,transitionsTaken,externalKey:this.externalKey,severity:"info"}),this.result("done",finalState,transitionsTaken)}async fail(finalState,transitionsTaken,reason="failed"){return await this.persistence.savePhase(this.runId,finalState,"failed"),await this.finalizeAsOwner("failed",new Date().toISOString()),addSpanEvent("workflow.run.failed",{runId:this.runId,finalState,reason}),this.events?.emit("workflow.run.failed",{runId:this.runId,finalState,reason,externalKey:this.externalKey,severity:"error"}),this.logger.warn("workflow run failed",{finalState,transitionsTaken,reason}),this.result("failed",finalState,transitionsTaken,reason)}async pause(stateOrNodeId,transitionsTaken,vars,lastActionResult){let data={transitionsTaken};if(vars!==void 0)data.effectiveVars=vars;if(lastActionResult!==void 0)data.lastActionResult={ok:lastActionResult.ok};return await this.persistence.saveWorkflowState(this.runId,stateOrNodeId,data),await this.persistence.savePhase(this.runId,stateOrNodeId,"paused"),await this.finalizeAsOwner("paused",new Date().toISOString()),this.logger.info("workflow run paused",{stateOrNodeId,transitionsTaken}),addSpanEvent("workflow.run.paused",{runId:this.runId,node:stateOrNodeId,transitionsTaken}),this.events?.emit("workflow.run.paused",{runId:this.runId,node:stateOrNodeId,transitionsTaken,externalKey:this.externalKey,severity:"warning"}),this.result("paused",stateOrNodeId,transitionsTaken)}actionStart(stateOrNodeId,kind){addSpanEvent("workflow.action.start",{runId:this.runId,node:stateOrNodeId,kind}),this.events?.emit("workflow.action.start",{runId:this.runId,node:stateOrNodeId,kind,severity:"info"})}actionDone(stateOrNodeId,kind,durationMs,ok){addSpanEvent("workflow.action.done",{runId:this.runId,node:stateOrNodeId,kind,durationMs,ok}),this.events?.emit("workflow.action.done",{runId:this.runId,node:stateOrNodeId,kind,durationMs,ok,severity:ok?"info":"error"})}warnActionFailed(stateOrNodeId,transitionsTaken,error51){addSpanEvent("workflow.action.failed_continue",{runId:this.runId,node:stateOrNodeId,transitionsTaken,...error51===void 0?{}:{error:error51}}),this.events?.emit("workflow.action.failed_continue",{runId:this.runId,node:stateOrNodeId,transitionsTaken,...error51===void 0?{}:{error:error51},severity:"warning"}),this.logger.warn("action failed (continuing)",{node:stateOrNodeId,transitionsTaken,error:error51})}guardEvaluated(from,to,kind,passed){this.events?.emit("workflow.guard.evaluated",{runId:this.runId,from,to,kind,passed,externalKey:this.externalKey,severity:passed?"info":"warning"})}hitlAsk(node,kind,message){this.events?.emit("workflow.hitl.ask",{runId:this.runId,node,kind,message,severity:"info"})}hitlResponse(node,ok){this.events?.emit("workflow.hitl.response",{runId:this.runId,node,ok,severity:ok?"info":"warning"})}result(status,finalState,transitionsTaken,reason){return{runId:this.runId,workflowName:this.workflowName,mode:this.mode,status,finalState,transitionsTaken,...reason===void 0?{}:{reason}}}static runRecord(runId,workflowName,mode,startedAt,metadata,externalKey){return{id:runId,workflow_name:workflowName,mode,status:"running",started_at:startedAt,metadata_json:JSON.stringify(metadata??{}),completed_at:null,external_key:externalKey??null}}}function snapshotTransitions(data){let value=data?.transitionsTaken;return typeof value==="number"&&Number.isSafeInteger(value)&&value>=0?value:0}function snapshotActionResult(data){let value=data?.lastActionResult;return value!==null&&typeof value==="object"&&"ok"in value&&typeof value.ok==="boolean"?{ok:value.ok}:void 0}class CapabilityRegistry{kind;capabilities=new Map;constructor(kind){this.kind=kind}register(name,capability,origin2="extension"){this.capabilities.set(name,{capability,origin:origin2})}has(name){return this.capabilities.has(name)}get(name){let entry=this.capabilities.get(name);if(entry===void 0)throw Error(`Unknown ${this.kind}: ${name}`);return entry.capability}getEntry(name){return this.capabilities.get(name)}list(){return[...this.capabilities.keys()]}entries(){return[...this.capabilities.entries()]}}function assertRelativeExtensionPath(path8,options={}){let where=options.sourceName!==void 0?` declared by "${options.sourceName}"`:"";if(/^([/\\]|[A-Za-z]:[/\\])/.test(path8))throw Error(`extension path "${path8}"${where} must be relative (no absolute paths)`);if(path8.split(/[/\\]/).includes(".."))throw Error(`extension path "${path8}"${where} must not contain ".." traversal`)}init_zod();var RESERVED_VAR_NAMES=new Set(["task","state","node","iteration","run","runtime"]),IDENTIFIER=/^[A-Za-z_][A-Za-z0-9_]*$/,VarsSchema=exports_external.record(exports_external.string(),exports_external.string()).superRefine((vars,ctx)=>{for(let key of Object.keys(vars)){if(!IDENTIFIER.test(key))ctx.addIssue({code:"custom",message:`Invalid variable name "${key}" (must be a valid identifier)`});if(RESERVED_VAR_NAMES.has(key))ctx.addIssue({code:"custom",message:`Variable name "${key}" is reserved for runtime use`})}}),EnvSchema=exports_external.object({allow:exports_external.array(exports_external.string().regex(IDENTIFIER,"env.allow entries must be valid identifiers")).optional()}),relativeExtensionPath=exports_external.string().min(1).superRefine((value,ctx)=>{try{assertRelativeExtensionPath(value)}catch(error51){ctx.addIssue({code:"custom",message:error51 instanceof Error?error51.message:"invalid extension path"})}}),WorkflowExtensionsSchema=exports_external.object({actions:exports_external.array(relativeExtensionPath).optional(),guards:exports_external.array(relativeExtensionPath).optional()}).strict(),ActionDefSchema=exports_external.object({kind:exports_external.string().min(1),options:exports_external.record(exports_external.string(),exports_external.unknown()).optional(),onError:exports_external.enum(["fail","continue"]).optional()}),GuardDefSchema=exports_external.object({kind:exports_external.string().min(1),options:exports_external.record(exports_external.string(),exports_external.unknown()).optional()}),StateMachineWorkflowDefSchema=exports_external.object({$schema:exports_external.string().optional(),kind:exports_external.literal("state-machine").optional(),name:exports_external.string().min(1),version:exports_external.string().optional(),description:exports_external.string().optional(),initialState:exports_external.string().min(1),terminalStates:exports_external.array(exports_external.string().min(1)).optional(),failureStates:exports_external.array(exports_external.string().min(1)).optional(),iterationBound:exports_external.number().int().positive().optional(),defaultOnError:exports_external.enum(["fail","continue"]).optional(),vars:VarsSchema.optional(),env:EnvSchema.optional(),states:exports_external.array(exports_external.object({id:exports_external.string().min(1),description:exports_external.string().optional(),onEnter:exports_external.array(ActionDefSchema).optional(),onExit:exports_external.array(ActionDefSchema).optional(),pause:exports_external.boolean().optional(),resumeRerun:exports_external.boolean().optional()}).strict()),transitions:exports_external.array(exports_external.object({from:exports_external.string().min(1),to:exports_external.string().min(1),description:exports_external.string().optional(),trigger:exports_external.string().optional(),guard:GuardDefSchema.optional()}).strict()),extensions:WorkflowExtensionsSchema.optional()}).strict(),TransitionFlowWorkflowDefSchema=exports_external.object({$schema:exports_external.string().optional(),kind:exports_external.literal("transition-flow"),name:exports_external.string().min(1),version:exports_external.string().optional(),description:exports_external.string().optional(),initialNode:exports_external.string().min(1),terminalNodes:exports_external.array(exports_external.string().min(1)).optional(),iterationBound:exports_external.number().int().positive().optional(),defaultOnError:exports_external.enum(["fail","continue"]).optional(),vars:VarsSchema.optional(),env:EnvSchema.optional(),nodes:exports_external.array(exports_external.object({id:exports_external.string().min(1),description:exports_external.string().optional(),type:exports_external.enum(["action","gate","parallel","decision"]).optional(),action:ActionDefSchema.optional(),pause:exports_external.boolean().optional(),resumeRerun:exports_external.boolean().optional()}).strict()),edges:exports_external.array(exports_external.object({from:exports_external.string().min(1),to:exports_external.string().min(1),description:exports_external.string().optional(),condition:GuardDefSchema.optional()}).strict()),extensions:WorkflowExtensionsSchema.optional()}).strict(),WorkflowDefSchema=exports_external.union([StateMachineWorkflowDefSchema,TransitionFlowWorkflowDefSchema]);async function loadWorkflowDef(path8,options={}){return parseWorkflowDef(await loadStructuredConfig(path8,options),path8)}function validateWorkflowDef(workflow){if(workflow.kind==="transition-flow")validateTransitionFlow(workflow);else validateStateMachine(workflow)}function validateStateMachine(workflow){let errors6=[],ids=workflow.states.map((state)=>state.id),states=new Set(ids),terminals=new Set(workflow.terminalStates??[]),failures=new Set(workflow.failureStates??[]);for(let id of duplicates(ids))errors6.push(`State "${id}" is declared more than once`);for(let failure of failures)if(!states.has(failure))errors6.push(`Failure state "${failure}" is not declared`);else if(!terminals.has(failure))errors6.push(`Failure state "${failure}" must also be declared as a terminal state`);if(!states.has(workflow.initialState))errors6.push(`Initial state "${workflow.initialState}" is not declared`);else if(terminals.has(workflow.initialState))errors6.push(`Initial state "${workflow.initialState}" must not be a terminal state`);for(let terminal of terminals)if(!states.has(terminal))errors6.push(`Terminal state "${terminal}" is not declared`);let outboundByState=new Map;for(let transition of workflow.transitions){if(!states.has(transition.from))errors6.push(`Transition source "${transition.from}" is not declared`);if(!states.has(transition.to))errors6.push(`Transition target "${transition.to}" is not declared`);let list=outboundByState.get(transition.from)??[];list.push(transition),outboundByState.set(transition.from,list)}for(let state of workflow.states){let outbound=outboundByState.get(state.id)??[];if(terminals.has(state.id)){if(outbound.length>0)errors6.push(`Terminal state "${state.id}" must not declare transitions`);continue}let ungatedIndex=outbound.findIndex((transition)=>transition.guard===void 0);if(ungatedIndex!==-1&&ungatedIndex<outbound.length-1)errors6.push(`State "${state.id}" has an unguarded transition that is not last; later transitions are unreachable`)}errors6.push(...checkVariableReferences(collectActionOptions(workflow),workflow.vars,workflow.env)),throwIfErrors(workflow,errors6)}function parseWorkflowDef(parsed,source){let result=selectWorkflowSchema(parsed).safeParse(parsed);if(!result.success)throw new WorkflowValidationError(`Workflow definition failed schema validation for ${source}: ${formatWorkflowIssues(result.error.issues)}`,result.error.issues);return validateWorkflowDef(result.data),result.data}function selectWorkflowSchema(parsed){if(parsed!==null&&typeof parsed==="object"){let value=parsed;if(value.kind==="transition-flow"||"nodes"in value||"edges"in value||"initialNode"in value)return TransitionFlowWorkflowDefSchema}return StateMachineWorkflowDefSchema}function formatWorkflowIssues(issues){return issues.map((issue2)=>{let path8=issue2.path.map(String).join(".");return path8.length>0?`${path8}: ${issue2.message}`:issue2.message}).join("; ")}function validateTransitionFlow(workflow){let errors6=[],ids=workflow.nodes.map((node)=>node.id),nodes=new Set(ids);for(let id of duplicates(ids))errors6.push(`Node "${id}" is declared more than once`);if(!nodes.has(workflow.initialNode))errors6.push(`Initial node "${workflow.initialNode}" is not declared`);let seenEdges=new Set;for(let edge of workflow.edges){if(!nodes.has(edge.from))errors6.push(`Edge source "${edge.from}" is not declared`);if(!nodes.has(edge.to))errors6.push(`Edge target "${edge.to}" is not declared`);let key=`${edge.from}→${edge.to}`;if(seenEdges.has(key))errors6.push(`Duplicate edge "${key}"`);seenEdges.add(key)}for(let terminal of workflow.terminalNodes??[]){if(!nodes.has(terminal))errors6.push(`Terminal node "${terminal}" is not declared`);if(workflow.edges.some((edge)=>edge.from===terminal))errors6.push(`Terminal node "${terminal}" must not declare edges`)}for(let node of workflow.nodes){let outbound=workflow.edges.filter((edge)=>edge.from===node.id),unconditional=outbound.findIndex((edge)=>edge.condition===void 0);if(unconditional!==-1&&unconditional<outbound.length-1)errors6.push(`Node "${node.id}" has an unconditional edge that is not last; later edges are unreachable`)}errors6.push(...checkVariableReferences(collectActionOptions(workflow),workflow.vars,workflow.env)),throwIfErrors(workflow,errors6)}function duplicates(ids){let seen=new Set,dupes=new Set;for(let id of ids){if(seen.has(id))dupes.add(id);seen.add(id)}return[...dupes]}function collectActionOptions(workflow){let optionSets=[],actions=workflow.kind==="transition-flow"?workflow.nodes.flatMap((node)=>node.action?[node.action]:[]):workflow.states.flatMap((state)=>[...state.onEnter??[],...state.onExit??[]]);for(let action of actions)if(action.options)optionSets.push(action.options);return optionSets}var RUNTIME_TEMPLATE_NAMESPACES=new Set(RUNTIME_BUILTIN_KEYS);function checkVariableReferences(optionSets,vars,env2){let declaredVars=new Set(Object.keys(vars??{})),allowedEnv2=new Set(env2?.allow??[]),errors6=[],reference=/\$\{([^}]+)\}/g;for(let options of optionSets)for(let value of Object.values(options)){if(typeof value!=="string")continue;for(let match of value.matchAll(reference)){let expr=(match[1]??"").trim(),[namespace,name]=expr.includes(".")?expr.split(".",2):[expr,void 0];if(namespace==="vars"){if(name!==void 0&&!declaredVars.has(name))errors6.push(`Unknown variable reference "\${${expr}}" (no var "${name}" declared)`)}else if(namespace==="env"){if(name!==void 0&&!allowedEnv2.has(name))errors6.push(`Env reference "\${${expr}}" is not in env.allow`)}else if(namespace!==void 0&&!RUNTIME_TEMPLATE_NAMESPACES.has(namespace))errors6.push(`Unknown template reference "\${${expr}}"`)}}return errors6}function throwIfErrors(workflow,errors6){if(errors6.length>0)throw new WorkflowValidationError(`Workflow "${workflow.name}" is invalid: ${errors6.join("; ")}`,errors6)}init_dist6();var TEMPLATE_REF=/\$\{([^}]+)\}/g;function mergeVars(workflowVars={},overrideVars={}){return{...workflowVars,...overrideVars}}function mergeSetVars(vars,setVars){if(setVars===void 0)return vars;let filtered={};for(let[key,value]of Object.entries(setVars))if(typeof value==="string")filtered[key]=value;return mergeVars(vars,filtered)}function resolveTemplates(value,context4){if(typeof value==="string")return resolveTemplateString(value,context4);if(Array.isArray(value))return value.map((entry)=>resolveTemplates(entry,context4));if(value!==null&&typeof value==="object")return Object.fromEntries(Object.entries(value).map(([key,entry])=>[key,resolveTemplates(entry,context4)]));return value}function resolveTemplateString(value,context4){return value.replace(TEMPLATE_REF,(_match,name)=>{return lookupRef(name,context4)})}function lookupRef(name,context4){if(name.startsWith("vars.")){let key=name.slice(5),resolved2=context4.vars[key];if(resolved2===void 0)throw new WorkflowValidationError(`Workflow variable "${key}" is not defined`);return resolved2}if(name.startsWith("env.")){let key=name.slice(4),resolved2=context4.env[key];if(resolved2===void 0)throw new WorkflowValidationError(`Environment variable "${key}" is not defined`);return resolved2}let resolved=context4.builtins?.[name];if(resolved===void 0)throw new WorkflowValidationError(`Workflow builtin "${name}" is not defined`);return String(resolved)}var SHELL_ENV_OPTION="__wfShellEnv",SHELL_BINDING=/^\$\{__WF_\d+\}$/,SHELL_BINDING_ANY=/\$\{__WF_\d+\}|\$__WF_\d+\b/;function resolveShellCommandTemplates(options,context4){let{command,args,...rest}=options;if(typeof command!=="string")return resolveTemplates(rest,context4);if(args!==void 0&&!Array.isArray(args))throw Error(`shell action "args" must be a string array when defined; got ${typeof args}`);if(Array.isArray(args)&&args.length>0)return{...resolveTemplates(rest,context4),command:resolveTemplateString(command,context4),args:resolveTemplates(args,context4)};let env2={},index2=0;if(!(SHELL_ENV_OPTION in options)&&SHELL_BINDING_ANY.test(command))throw Error("shell command must not contain the reserved $__WF_ placeholder namespace; it is minted by the template-binding pass");let existingBindings=options[SHELL_ENV_OPTION];if(existingBindings!==void 0&&typeof existingBindings==="object"&&existingBindings!==null){Object.assign(env2,existingBindings);while(`__WF_${index2}`in env2)index2++}let bound=command.replace(TEMPLATE_REF,(match,name)=>{if(SHELL_BINDING.test(match))return match;let key=`__WF_${index2++}`;return env2[key]=lookupRef(name,context4),`\${${key}}`});return{...resolveTemplates(rest,context4),command:bound,[SHELL_ENV_OPTION]:env2}}function resolveOnErrorPolicy(actionOnError,workflowDefault,runOptionOverride){return actionOnError??workflowDefault??runOptionOverride??"fail"}class WorkflowEngineHost{lifecycleBus;actions=new CapabilityRegistry("workflow action");guards=new CapabilityRegistry("workflow guard");constructor(lifecycleBus){this.lifecycleBus=lifecycleBus}registerAction(action,origin2="extension"){return this.actions.register(action.kind,action,origin2),this}registerGuard(guard,origin2="extension"){return this.guards.register(guard.kind,guard,origin2),this}hasAction(kind){return this.actions.has(kind)}hasGuard(kind){return this.guards.has(kind)}listActions(){return this.actions.list()}listGuards(){return this.guards.list()}actionOrigin(kind){return this.actions.getEntry(kind)?.origin}guardOrigin(kind){return this.guards.getEntry(kind)?.origin}async runAction(kind,options,context4){if(!this.actions.has(kind))throw new WorkflowValidationError(`Unknown workflow action "${kind}"`);return await this.actions.get(kind).execute(options,context4)}async evaluateGuard(kind,options,context4){return(await this.evaluateGuardResult(kind,options,context4)).passed}async evaluateGuardResult(kind,options,context4){if(!this.guards.has(kind))throw new WorkflowValidationError(`Unknown workflow guard "${kind}"`);let result=await this.guards.get(kind).evaluate(options,context4);return typeof result==="boolean"?{passed:result}:result}}function createDefaultWorkflowEngineHost(options={}){let host=new WorkflowEngineHost(options.lifecycleBus);return host.registerAction(new NoteActionRunner,"builtin"),host.registerAction(new ShellActionRunner(options.processExecutor??nodeBunFactory2.createProcessExecutor()),"builtin"),host.registerAction(new EventEmitActionRunner,"builtin"),host.registerGuard(new ShellGuardRunner(options.processExecutor??nodeBunFactory2.createProcessExecutor()),"builtin"),host.registerGuard({kind:"always",evaluate:async()=>!0},"builtin"),host.registerGuard({kind:"never",evaluate:async()=>!1},"builtin"),host.registerGuard({kind:"action-ok",evaluate:async(_options,context4)=>context4.lastActionResult?.ok===!0},"builtin"),host}class NoteActionRunner{kind="note";async execute(options,context4){let message=String(options.message??"");return context4?.events?.emit("workflow.hitl.note",{runId:context4.runId,node:context4.stateOrNodeId,message,severity:"info"}),{ok:!0,data:{message}}}}class EventEmitActionRunner{kind="event.emit";async execute(options,context4){let name=String(options.name??"");if(!name)return{ok:!1,error:'event.emit requires a non-empty "name" option'};let payload=options.payload??{};return context4?.events?.emit("workflow.custom",{name,payload,severity:"info"}),{ok:!0,data:{name,payload}}}}async function spawnShellCommand(processExecutor,options,workdir){let command=stringOption(options,"command"),explicitArgs=arrayOption(options,"args"),spawn2=explicitArgs.length===0?{command:"/bin/sh",args:["-c",command]}:{command,args:explicitArgs},timeout=optionalTimeoutOption(options),envOption=options[SHELL_ENV_OPTION],env2=envOption!==null&&typeof envOption==="object"?envOption:void 0,result=await processExecutor.run({command:spawn2.command,args:spawn2.args,cwd:optionalStringOption(options,"cwd",workdir),...env2!==void 0?{env:env2,envMode:"merge"}:{},...timeout!==void 0?{timeout}:{},rejectOnError:!1,forceBuffered:!0});return{stdout:result.stdout,stderr:result.stderr,exitCode:result.exitCode,timedOut:result.outcome==="timeout"}}class ShellActionRunner{processExecutor;kind="shell";constructor(processExecutor){this.processExecutor=processExecutor}async execute(options,context4){let spawn2=await spawnShellCommand(this.processExecutor,options,context4.workdir);if(spawn2.timedOut){let timeout=optionalTimeoutOption(options);return{ok:!1,data:{stdout:spawn2.stdout,stderr:spawn2.stderr,exitCode:spawn2.exitCode,timedOut:!0},error:`Shell action timed out after ${timeout}ms`}}let command=stringOption(options,"command");return{ok:spawn2.exitCode===0,data:{stdout:spawn2.stdout,stderr:spawn2.stderr,exitCode:spawn2.exitCode},...spawn2.exitCode===0?{}:{error:`Command "${command}" exited with ${spawn2.exitCode}`}}}}class ShellGuardRunner{processExecutor;kind="shell";constructor(processExecutor){this.processExecutor=processExecutor}async evaluate(options,context4){let spawn2=await spawnShellCommand(this.processExecutor,options,context4.workdir);return{passed:!spawn2.timedOut&&spawn2.exitCode===0,report:{stdout:spawn2.stdout,stderr:spawn2.stderr,exitCode:spawn2.exitCode,...spawn2.timedOut?{timedOut:!0}:{}}}}}function stringOption(options,key,fallback){let value=options[key];if(typeof value==="string")return value;if(fallback!==void 0)return fallback;throw new WorkflowValidationError(`Action option "${key}" must be a string`)}function optionalStringOption(options,key,fallback){let value=options[key];if(typeof value==="string")return value;if(value===void 0)return fallback;throw new WorkflowValidationError(`Action option "${key}" must be a string`)}function arrayOption(options,key){let value=options[key];if(value===void 0)return[];if(Array.isArray(value)&&value.every((entry)=>typeof entry==="string"))return value;throw new WorkflowValidationError(`Action option "${key}" must be a string array`)}function optionalTimeoutOption(options){let value=options.timeout;if(value===void 0)return;if(typeof value==="number"&&Number.isFinite(value)&&value>0)return value;throw new WorkflowValidationError('shell option "timeout" must be a positive number of milliseconds')}var WORKFLOW_ENGINE_SCHEMA_SQL=`
554
+ WHERE id = ?3 AND status IN ('running', 'pending')`,nowIso,reason,runId)}async setPid(runId,pid){await this.adapter.run("UPDATE runs SET pid = ? WHERE id = ?",pid,runId)}async getPid(runId){return(await this.adapter.queryFirst("SELECT pid FROM runs WHERE id = ?",runId))?.pid??null}}init_schema();var transitionRunsTable=defineTable("transition_runs",{id:text("id").primaryKey(),runId:text("run_id").notNull().references(()=>runs.id),fromState:text("from_state").notNull(),toState:text("to_state").notNull(),trigger:text("trigger"),status:text("status").notNull(),...standardColumns}),transitionRuns=transitionRunsTable.table;init_schema();var workflowStatesTable=defineTable("workflow_states",{id:text("id").primaryKey(),runId:text("run_id").notNull().references(()=>runs.id),state:text("state").notNull(),dataJson:text("data_json").notNull(),...standardColumns}),workflowStates=workflowStatesTable.table;init_dist6();class WorkflowValidationError extends Error{details;constructor(message,details){super(message);this.details=details,this.name="WorkflowValidationError"}}class FSMError extends Error{details;constructor(message,details){super(message);this.details=details,this.name="FSMError"}}class RunCollisionError extends Error{constructor(runId){super(`Workflow run "${runId}" already exists`);this.name="RunCollisionError"}}class WorkflowResumeError extends Error{details;constructor(message,details){super(message);this.details=details,this.name="WorkflowResumeError"}}init_dist7();init_dist6();var RUNTIME_BUILTIN_KEYS=["workflow","runId","task","state","node","iteration","run","runtime"];function runtimeBuiltins(workflowName,stateOrNodeId,runId,transitionsTaken,mode){return{workflow:workflowName,runId,task:workflowName,state:stateOrNodeId,node:stateOrNodeId,iteration:transitionsTaken,run:runId,runtime:mode}}function allowedEnv(names,source=getProcessEnv()){return Object.fromEntries(names.flatMap((name)=>source[name]===void 0?[]:[[name,source[name]]]))}class RunLifecycle{workflowName;mode;runId;externalKey;persistence;events;logger;ownerAttempt;constructor(runId,workflowName,mode,deps,externalKey){this.workflowName=workflowName,this.mode=mode,this.runId=runId,this.externalKey=externalKey,this.persistence=deps.persistence,this.events=deps.events??(deps.lifecycleBus?new EventBus({lifecycleBus:deps.lifecycleBus}):void 0),this.logger=(deps.logger??getLogger2("workflow")).child({runId,workflow:workflowName,mode})}static forExternalTransition(workflowName,runId,deps,externalKey){return new RunLifecycle(runId,workflowName,"state-machine",deps,externalKey)}static async run(workflowName,mode,deps,options,loop){return await traceAsync("workflow.run",async()=>{let startedAt=new Date().toISOString(),proposed={...RunLifecycle.runRecord(options.runId??crypto.randomUUID(),workflowName,mode,startedAt,options.metadata,options.externalKey),owner_attempt:crypto.randomUUID()},record2=proposed;if(options.externalKey===void 0)await deps.persistence.createRun(proposed);else if(record2=await deps.persistence.createOrAttachRun(proposed),record2.owner_attempt!==proposed.owner_attempt){let snapshot=await deps.persistence.loadLatestStateSnapshot(record2.id);return{runId:record2.id,workflowName:record2.workflow_name,mode:record2.mode==="transition-flow"?"transition-flow":"state-machine",status:record2.status,finalState:snapshot?.state??"",transitionsTaken:snapshotTransitions(snapshot?.data)}}let extKey=record2.external_key??void 0,lifecycle=new RunLifecycle(record2.id,workflowName,mode,deps,extKey);return lifecycle.ownerAttempt=proposed.owner_attempt??void 0,lifecycle.logger.info("workflow run started"),addSpanEvent("workflow.run.started",{workflowName,mode,runId:lifecycle.runId,dryRun:options.dryRun??!1}),lifecycle.events?.emit("workflow.run.started",{workflowName,mode,runId:lifecycle.runId,dryRun:options.dryRun??!1,externalKey:extKey,severity:"info"}),await lifecycle.execute(loop)},{attributes:{"workflow.name":workflowName,"workflow.mode":mode}})}static async resume(workflowName,mode,deps,runId,externalKey,loop,ownerAttempt){return await traceAsync("workflow.run",async()=>{let lifecycle=new RunLifecycle(runId,workflowName,mode,deps,externalKey);return lifecycle.ownerAttempt=ownerAttempt,lifecycle.logger.info("workflow run resumed"),await lifecycle.execute(loop)},{attributes:{"workflow.name":workflowName,"workflow.mode":mode}})}async finalizeAsOwner(status,completedAt,reason){if(this.ownerAttempt===void 0){await this.persistence.finalizeRun(this.runId,status,completedAt,void 0,reason);return}if(await this.persistence.finalizeRun(this.runId,status,completedAt,{ownerAttempt:this.ownerAttempt},reason)===!1)throw this.events?.emit("workflow.run.stale_owner",{runId:this.runId,ownerAttemptId:this.ownerAttempt,status,severity:"warning"}),new WorkflowResumeError(`stale owner "${this.ownerAttempt}" cannot finalize run "${this.runId}" as "${status}": ownership was lost`)}async execute(loop){try{return await loop(this)}catch(error51){try{await this.finalizeAsOwner("failed",new Date().toISOString(),"failed")}catch(finalizeError){throw AggregateError([error51,finalizeError],"Workflow execution and failure persistence failed")}throw error51}}async enter(stateOrNodeId,transitionsTaken,persist=!0,vars){if(persist){let data={transitionsTaken};if(vars!==void 0)data.effectiveVars=vars;await this.persistence.saveWorkflowState(this.runId,stateOrNodeId,data),await this.persistence.savePhase(this.runId,stateOrNodeId,"running")}addSpanEvent("workflow.node.enter",{runId:this.runId,node:stateOrNodeId,transitionsTaken}),this.events?.emit("workflow.node.enter",{runId:this.runId,node:stateOrNodeId,transitionsTaken,severity:"info"})}async commitHop(from,to,trigger,transitionsTaken,phase,vars){let data={transitionsTaken};if(vars!==void 0)data.effectiveVars=vars;await this.persistence.commitTransition(this.runId,from,to,trigger,to,data,phase),addSpanEvent("workflow.node.transition",{runId:this.runId,from,to,...trigger===null?{}:{trigger}}),this.events?.emit("workflow.node.transition",{runId:this.runId,from,to,trigger,externalKey:this.externalKey,severity:"info"})}async recordTransition(from,to,trigger){await this.persistence.saveTransition(this.runId,from,to,trigger),addSpanEvent("workflow.node.transition",{runId:this.runId,from,to,...trigger===null?{}:{trigger}}),this.events?.emit("workflow.node.transition",{runId:this.runId,from,to,trigger,externalKey:this.externalKey,severity:"info"})}async done(finalState,transitionsTaken,reason){return await this.persistence.savePhase(this.runId,finalState,"done"),await this.finalizeAsOwner("done",new Date().toISOString(),reason),this.logger.info("workflow run done",{finalState,transitionsTaken}),addSpanEvent("workflow.run.done",{runId:this.runId,finalState,transitionsTaken}),this.events?.emit("workflow.run.done",{runId:this.runId,finalState,transitionsTaken,externalKey:this.externalKey,severity:"info"}),this.result("done",finalState,transitionsTaken,reason)}async fail(finalState,transitionsTaken,reason="failed"){return await this.persistence.savePhase(this.runId,finalState,"failed"),await this.finalizeAsOwner("failed",new Date().toISOString(),reason),addSpanEvent("workflow.run.failed",{runId:this.runId,finalState,reason}),this.events?.emit("workflow.run.failed",{runId:this.runId,finalState,reason,externalKey:this.externalKey,severity:"error"}),this.logger.warn("workflow run failed",{finalState,transitionsTaken,reason}),this.result("failed",finalState,transitionsTaken,reason)}async pause(stateOrNodeId,transitionsTaken,vars,lastActionResult,reason){let data={transitionsTaken};if(vars!==void 0)data.effectiveVars=vars;if(lastActionResult!==void 0)data.lastActionResult={ok:lastActionResult.ok};return await this.persistence.saveWorkflowState(this.runId,stateOrNodeId,data),await this.persistence.savePhase(this.runId,stateOrNodeId,"paused"),await this.finalizeAsOwner("paused",new Date().toISOString(),reason),this.logger.info("workflow run paused",{stateOrNodeId,transitionsTaken}),addSpanEvent("workflow.run.paused",{runId:this.runId,node:stateOrNodeId,transitionsTaken}),this.events?.emit("workflow.run.paused",{runId:this.runId,node:stateOrNodeId,transitionsTaken,externalKey:this.externalKey,severity:"warning"}),this.result("paused",stateOrNodeId,transitionsTaken)}actionStart(stateOrNodeId,kind){addSpanEvent("workflow.action.start",{runId:this.runId,node:stateOrNodeId,kind}),this.events?.emit("workflow.action.start",{runId:this.runId,node:stateOrNodeId,kind,severity:"info"})}actionDone(stateOrNodeId,kind,durationMs,ok){addSpanEvent("workflow.action.done",{runId:this.runId,node:stateOrNodeId,kind,durationMs,ok}),this.events?.emit("workflow.action.done",{runId:this.runId,node:stateOrNodeId,kind,durationMs,ok,severity:ok?"info":"error"})}warnActionFailed(stateOrNodeId,transitionsTaken,error51){addSpanEvent("workflow.action.failed_continue",{runId:this.runId,node:stateOrNodeId,transitionsTaken,...error51===void 0?{}:{error:error51}}),this.events?.emit("workflow.action.failed_continue",{runId:this.runId,node:stateOrNodeId,transitionsTaken,...error51===void 0?{}:{error:error51},severity:"warning"}),this.logger.warn("action failed (continuing)",{node:stateOrNodeId,transitionsTaken,error:error51})}guardEvaluated(from,to,kind,passed){this.events?.emit("workflow.guard.evaluated",{runId:this.runId,from,to,kind,passed,externalKey:this.externalKey,severity:passed?"info":"warning"})}hitlAsk(node,kind,message){this.events?.emit("workflow.hitl.ask",{runId:this.runId,node,kind,message,severity:"info"})}hitlResponse(node,ok){this.events?.emit("workflow.hitl.response",{runId:this.runId,node,ok,severity:ok?"info":"warning"})}result(status,finalState,transitionsTaken,reason){return{runId:this.runId,workflowName:this.workflowName,mode:this.mode,status,finalState,transitionsTaken,...reason===void 0?{}:{reason}}}static runRecord(runId,workflowName,mode,startedAt,metadata,externalKey){return{id:runId,workflow_name:workflowName,mode,status:"running",started_at:startedAt,metadata_json:JSON.stringify(metadata??{}),completed_at:null,external_key:externalKey??null}}}function snapshotTransitions(data){let value=data?.transitionsTaken;return typeof value==="number"&&Number.isSafeInteger(value)&&value>=0?value:0}function snapshotActionResult(data){let value=data?.lastActionResult;return value!==null&&typeof value==="object"&&"ok"in value&&typeof value.ok==="boolean"?{ok:value.ok}:void 0}class CapabilityRegistry{kind;capabilities=new Map;constructor(kind){this.kind=kind}register(name,capability,origin2="extension"){this.capabilities.set(name,{capability,origin:origin2})}has(name){return this.capabilities.has(name)}get(name){let entry=this.capabilities.get(name);if(entry===void 0)throw Error(`Unknown ${this.kind}: ${name}`);return entry.capability}getEntry(name){return this.capabilities.get(name)}list(){return[...this.capabilities.keys()]}entries(){return[...this.capabilities.entries()]}}function assertRelativeExtensionPath(path8,options={}){let where=options.sourceName!==void 0?` declared by "${options.sourceName}"`:"";if(/^([/\\]|[A-Za-z]:[/\\])/.test(path8))throw Error(`extension path "${path8}"${where} must be relative (no absolute paths)`);if(path8.split(/[/\\]/).includes(".."))throw Error(`extension path "${path8}"${where} must not contain ".." traversal`)}init_zod();var RESERVED_VAR_NAMES=new Set(["task","state","node","iteration","run","runtime"]),IDENTIFIER=/^[A-Za-z_][A-Za-z0-9_]*$/,VarsSchema=exports_external.record(exports_external.string(),exports_external.string()).superRefine((vars,ctx)=>{for(let key of Object.keys(vars)){if(!IDENTIFIER.test(key))ctx.addIssue({code:"custom",message:`Invalid variable name "${key}" (must be a valid identifier)`});if(RESERVED_VAR_NAMES.has(key))ctx.addIssue({code:"custom",message:`Variable name "${key}" is reserved for runtime use`})}}),EnvSchema=exports_external.object({allow:exports_external.array(exports_external.string().regex(IDENTIFIER,"env.allow entries must be valid identifiers")).optional()}),relativeExtensionPath=exports_external.string().min(1).superRefine((value,ctx)=>{try{assertRelativeExtensionPath(value)}catch(error51){ctx.addIssue({code:"custom",message:error51 instanceof Error?error51.message:"invalid extension path"})}}),WorkflowExtensionsSchema=exports_external.object({actions:exports_external.array(relativeExtensionPath).optional(),guards:exports_external.array(relativeExtensionPath).optional()}).strict(),ActionDefSchema=exports_external.object({kind:exports_external.string().min(1),options:exports_external.record(exports_external.string(),exports_external.unknown()).optional(),onError:exports_external.enum(["fail","continue"]).optional()}),GuardDefSchema=exports_external.object({kind:exports_external.string().min(1),options:exports_external.record(exports_external.string(),exports_external.unknown()).optional()}),StateMachineWorkflowDefSchema=exports_external.object({$schema:exports_external.string().optional(),kind:exports_external.literal("state-machine").optional(),name:exports_external.string().min(1),version:exports_external.string().optional(),description:exports_external.string().optional(),initialState:exports_external.string().min(1),terminalStates:exports_external.array(exports_external.string().min(1)).optional(),failureStates:exports_external.array(exports_external.string().min(1)).optional(),iterationBound:exports_external.number().int().positive().optional(),defaultOnError:exports_external.enum(["fail","continue"]).optional(),vars:VarsSchema.optional(),env:EnvSchema.optional(),states:exports_external.array(exports_external.object({id:exports_external.string().min(1),description:exports_external.string().optional(),onEnter:exports_external.array(ActionDefSchema).optional(),onExit:exports_external.array(ActionDefSchema).optional(),pause:exports_external.boolean().optional(),resumeRerun:exports_external.boolean().optional()}).strict()),transitions:exports_external.array(exports_external.object({from:exports_external.string().min(1),to:exports_external.string().min(1),description:exports_external.string().optional(),trigger:exports_external.string().optional(),guard:GuardDefSchema.optional(),terminalReason:exports_external.string().optional()}).strict()),extensions:WorkflowExtensionsSchema.optional()}).strict(),TransitionFlowWorkflowDefSchema=exports_external.object({$schema:exports_external.string().optional(),kind:exports_external.literal("transition-flow"),name:exports_external.string().min(1),version:exports_external.string().optional(),description:exports_external.string().optional(),initialNode:exports_external.string().min(1),terminalNodes:exports_external.array(exports_external.string().min(1)).optional(),iterationBound:exports_external.number().int().positive().optional(),defaultOnError:exports_external.enum(["fail","continue"]).optional(),vars:VarsSchema.optional(),env:EnvSchema.optional(),nodes:exports_external.array(exports_external.object({id:exports_external.string().min(1),description:exports_external.string().optional(),type:exports_external.enum(["action","gate","parallel","decision"]).optional(),action:ActionDefSchema.optional(),pause:exports_external.boolean().optional(),resumeRerun:exports_external.boolean().optional()}).strict()),edges:exports_external.array(exports_external.object({from:exports_external.string().min(1),to:exports_external.string().min(1),description:exports_external.string().optional(),condition:GuardDefSchema.optional()}).strict()),extensions:WorkflowExtensionsSchema.optional()}).strict(),WorkflowDefSchema=exports_external.union([StateMachineWorkflowDefSchema,TransitionFlowWorkflowDefSchema]);async function loadWorkflowDef(path8,options={}){return parseWorkflowDef(await loadStructuredConfig(path8,options),path8)}function validateWorkflowDef(workflow){if(workflow.kind==="transition-flow")validateTransitionFlow(workflow);else validateStateMachine(workflow)}function validateStateMachine(workflow){let errors6=[],ids=workflow.states.map((state)=>state.id),states=new Set(ids),terminals=new Set(workflow.terminalStates??[]),failures=new Set(workflow.failureStates??[]);for(let id of duplicates(ids))errors6.push(`State "${id}" is declared more than once`);for(let failure of failures)if(!states.has(failure))errors6.push(`Failure state "${failure}" is not declared`);else if(!terminals.has(failure))errors6.push(`Failure state "${failure}" must also be declared as a terminal state`);if(!states.has(workflow.initialState))errors6.push(`Initial state "${workflow.initialState}" is not declared`);else if(terminals.has(workflow.initialState))errors6.push(`Initial state "${workflow.initialState}" must not be a terminal state`);for(let terminal of terminals)if(!states.has(terminal))errors6.push(`Terminal state "${terminal}" is not declared`);let outboundByState=new Map;for(let transition of workflow.transitions){if(!states.has(transition.from))errors6.push(`Transition source "${transition.from}" is not declared`);if(!states.has(transition.to))errors6.push(`Transition target "${transition.to}" is not declared`);let list=outboundByState.get(transition.from)??[];list.push(transition),outboundByState.set(transition.from,list)}for(let state of workflow.states){let outbound=outboundByState.get(state.id)??[];if(terminals.has(state.id)){if(outbound.length>0)errors6.push(`Terminal state "${state.id}" must not declare transitions`);continue}let ungatedIndex=outbound.findIndex((transition)=>transition.guard===void 0);if(ungatedIndex!==-1&&ungatedIndex<outbound.length-1)errors6.push(`State "${state.id}" has an unguarded transition that is not last; later transitions are unreachable`)}errors6.push(...checkVariableReferences(collectActionOptions(workflow),workflow.vars,workflow.env)),throwIfErrors(workflow,errors6)}function parseWorkflowDef(parsed,source){let result=selectWorkflowSchema(parsed).safeParse(parsed);if(!result.success)throw new WorkflowValidationError(`Workflow definition failed schema validation for ${source}: ${formatWorkflowIssues(result.error.issues)}`,result.error.issues);return validateWorkflowDef(result.data),result.data}function selectWorkflowSchema(parsed){if(parsed!==null&&typeof parsed==="object"){let value=parsed;if(value.kind==="transition-flow"||"nodes"in value||"edges"in value||"initialNode"in value)return TransitionFlowWorkflowDefSchema}return StateMachineWorkflowDefSchema}function formatWorkflowIssues(issues){return issues.map((issue2)=>{let path8=issue2.path.map(String).join(".");return path8.length>0?`${path8}: ${issue2.message}`:issue2.message}).join("; ")}function validateTransitionFlow(workflow){let errors6=[],ids=workflow.nodes.map((node)=>node.id),nodes=new Set(ids);for(let id of duplicates(ids))errors6.push(`Node "${id}" is declared more than once`);if(!nodes.has(workflow.initialNode))errors6.push(`Initial node "${workflow.initialNode}" is not declared`);let seenEdges=new Set;for(let edge of workflow.edges){if(!nodes.has(edge.from))errors6.push(`Edge source "${edge.from}" is not declared`);if(!nodes.has(edge.to))errors6.push(`Edge target "${edge.to}" is not declared`);let key=`${edge.from}→${edge.to}`;if(seenEdges.has(key))errors6.push(`Duplicate edge "${key}"`);seenEdges.add(key)}for(let terminal of workflow.terminalNodes??[]){if(!nodes.has(terminal))errors6.push(`Terminal node "${terminal}" is not declared`);if(workflow.edges.some((edge)=>edge.from===terminal))errors6.push(`Terminal node "${terminal}" must not declare edges`)}for(let node of workflow.nodes){let outbound=workflow.edges.filter((edge)=>edge.from===node.id),unconditional=outbound.findIndex((edge)=>edge.condition===void 0);if(unconditional!==-1&&unconditional<outbound.length-1)errors6.push(`Node "${node.id}" has an unconditional edge that is not last; later edges are unreachable`)}errors6.push(...checkVariableReferences(collectActionOptions(workflow),workflow.vars,workflow.env)),throwIfErrors(workflow,errors6)}function duplicates(ids){let seen=new Set,dupes=new Set;for(let id of ids){if(seen.has(id))dupes.add(id);seen.add(id)}return[...dupes]}function collectActionOptions(workflow){let optionSets=[],actions=workflow.kind==="transition-flow"?workflow.nodes.flatMap((node)=>node.action?[node.action]:[]):workflow.states.flatMap((state)=>[...state.onEnter??[],...state.onExit??[]]);for(let action of actions)if(action.options)optionSets.push(action.options);return optionSets}var RUNTIME_TEMPLATE_NAMESPACES=new Set(RUNTIME_BUILTIN_KEYS);function checkVariableReferences(optionSets,vars,env2){let declaredVars=new Set(Object.keys(vars??{})),allowedEnv2=new Set(env2?.allow??[]),errors6=[],reference=/\$\{([^}]+)\}/g;for(let options of optionSets)for(let value of Object.values(options)){if(typeof value!=="string")continue;for(let match of value.matchAll(reference)){let expr=(match[1]??"").trim(),[namespace,name]=expr.includes(".")?expr.split(".",2):[expr,void 0];if(namespace==="vars"){if(name!==void 0&&!declaredVars.has(name))errors6.push(`Unknown variable reference "\${${expr}}" (no var "${name}" declared)`)}else if(namespace==="env"){if(name!==void 0&&!allowedEnv2.has(name))errors6.push(`Env reference "\${${expr}}" is not in env.allow`)}else if(namespace!==void 0&&!RUNTIME_TEMPLATE_NAMESPACES.has(namespace))errors6.push(`Unknown template reference "\${${expr}}"`)}}return errors6}function throwIfErrors(workflow,errors6){if(errors6.length>0)throw new WorkflowValidationError(`Workflow "${workflow.name}" is invalid: ${errors6.join("; ")}`,errors6)}init_dist6();var TEMPLATE_REF=/\$\{([^}]+)\}/g;function mergeVars(workflowVars={},overrideVars={}){return{...workflowVars,...overrideVars}}function mergeSetVars(vars,setVars){if(setVars===void 0)return vars;let filtered={};for(let[key,value]of Object.entries(setVars))if(typeof value==="string")filtered[key]=value;return mergeVars(vars,filtered)}function resolveTemplates(value,context4){if(typeof value==="string")return resolveTemplateString(value,context4);if(Array.isArray(value))return value.map((entry)=>resolveTemplates(entry,context4));if(value!==null&&typeof value==="object")return Object.fromEntries(Object.entries(value).map(([key,entry])=>[key,resolveTemplates(entry,context4)]));return value}function resolveTemplateString(value,context4){return value.replace(TEMPLATE_REF,(_match,name)=>{return lookupRef(name,context4)})}function lookupRef(name,context4){if(name.startsWith("vars.")){let key=name.slice(5),resolved2=context4.vars[key];if(resolved2===void 0)throw new WorkflowValidationError(`Workflow variable "${key}" is not defined`);return resolved2}if(name.startsWith("env.")){let key=name.slice(4),resolved2=context4.env[key];if(resolved2===void 0)throw new WorkflowValidationError(`Environment variable "${key}" is not defined`);return resolved2}let resolved=context4.builtins?.[name];if(resolved===void 0)throw new WorkflowValidationError(`Workflow builtin "${name}" is not defined`);return String(resolved)}var SHELL_ENV_OPTION="__wfShellEnv",SHELL_BINDING=/^\$\{__WF_\d+\}$/,SHELL_BINDING_ANY=/\$\{__WF_\d+\}|\$__WF_\d+\b/;function resolveShellCommandTemplates(options,context4){let{command,args,...rest}=options;if(typeof command!=="string")return resolveTemplates(rest,context4);if(args!==void 0&&!Array.isArray(args))throw Error(`shell action "args" must be a string array when defined; got ${typeof args}`);if(Array.isArray(args)&&args.length>0)return{...resolveTemplates(rest,context4),command:resolveTemplateString(command,context4),args:resolveTemplates(args,context4)};let env2={},index2=0;if(!(SHELL_ENV_OPTION in options)&&SHELL_BINDING_ANY.test(command))throw Error("shell command must not contain the reserved $__WF_ placeholder namespace; it is minted by the template-binding pass");let existingBindings=options[SHELL_ENV_OPTION];if(existingBindings!==void 0&&typeof existingBindings==="object"&&existingBindings!==null){Object.assign(env2,existingBindings);while(`__WF_${index2}`in env2)index2++}let bound=command.replace(TEMPLATE_REF,(match,name)=>{if(SHELL_BINDING.test(match))return match;let key=`__WF_${index2++}`;return env2[key]=lookupRef(name,context4),`\${${key}}`});return{...resolveTemplates(rest,context4),command:bound,[SHELL_ENV_OPTION]:env2}}function resolveOnErrorPolicy(actionOnError,workflowDefault,runOptionOverride){return actionOnError??workflowDefault??runOptionOverride??"fail"}class WorkflowEngineHost{lifecycleBus;actions=new CapabilityRegistry("workflow action");guards=new CapabilityRegistry("workflow guard");constructor(lifecycleBus){this.lifecycleBus=lifecycleBus}registerAction(action,origin2="extension"){return this.actions.register(action.kind,action,origin2),this}registerGuard(guard,origin2="extension"){return this.guards.register(guard.kind,guard,origin2),this}hasAction(kind){return this.actions.has(kind)}hasGuard(kind){return this.guards.has(kind)}listActions(){return this.actions.list()}listGuards(){return this.guards.list()}actionOrigin(kind){return this.actions.getEntry(kind)?.origin}guardOrigin(kind){return this.guards.getEntry(kind)?.origin}async runAction(kind,options,context4){if(!this.actions.has(kind))throw new WorkflowValidationError(`Unknown workflow action "${kind}"`);return await this.actions.get(kind).execute(options,context4)}async evaluateGuard(kind,options,context4){return(await this.evaluateGuardResult(kind,options,context4)).passed}async evaluateGuardResult(kind,options,context4){if(!this.guards.has(kind))throw new WorkflowValidationError(`Unknown workflow guard "${kind}"`);let result=await this.guards.get(kind).evaluate(options,context4);return typeof result==="boolean"?{passed:result}:result}}function createDefaultWorkflowEngineHost(options={}){let host=new WorkflowEngineHost(options.lifecycleBus);return host.registerAction(new NoteActionRunner,"builtin"),host.registerAction(new ShellActionRunner(options.processExecutor??nodeBunFactory2.createProcessExecutor()),"builtin"),host.registerAction(new EventEmitActionRunner,"builtin"),host.registerGuard(new ShellGuardRunner(options.processExecutor??nodeBunFactory2.createProcessExecutor()),"builtin"),host.registerGuard({kind:"always",evaluate:async()=>!0},"builtin"),host.registerGuard({kind:"never",evaluate:async()=>!1},"builtin"),host.registerGuard({kind:"action-ok",evaluate:async(_options,context4)=>context4.lastActionResult?.ok===!0},"builtin"),host}class NoteActionRunner{kind="note";async execute(options,context4){let message=String(options.message??"");return context4?.events?.emit("workflow.hitl.note",{runId:context4.runId,node:context4.stateOrNodeId,message,severity:"info"}),{ok:!0,data:{message}}}}class EventEmitActionRunner{kind="event.emit";async execute(options,context4){let name=String(options.name??"");if(!name)return{ok:!1,error:'event.emit requires a non-empty "name" option'};let payload=options.payload??{};return context4?.events?.emit("workflow.custom",{name,payload,severity:"info"}),{ok:!0,data:{name,payload}}}}async function spawnShellCommand(processExecutor,options,workdir){let command=stringOption(options,"command"),explicitArgs=arrayOption(options,"args"),spawn2=explicitArgs.length===0?{command:"/bin/sh",args:["-c",command]}:{command,args:explicitArgs},timeout=optionalTimeoutOption(options),envOption=options[SHELL_ENV_OPTION],env2=envOption!==null&&typeof envOption==="object"?envOption:void 0,result=await processExecutor.run({command:spawn2.command,args:spawn2.args,cwd:optionalStringOption(options,"cwd",workdir),...env2!==void 0?{env:env2,envMode:"merge"}:{},...timeout!==void 0?{timeout}:{},rejectOnError:!1,forceBuffered:!0});return{stdout:result.stdout,stderr:result.stderr,exitCode:result.exitCode,timedOut:result.outcome==="timeout"}}class ShellActionRunner{processExecutor;kind="shell";constructor(processExecutor){this.processExecutor=processExecutor}async execute(options,context4){let spawn2=await spawnShellCommand(this.processExecutor,options,context4.workdir);if(spawn2.timedOut){let timeout=optionalTimeoutOption(options);return{ok:!1,data:{stdout:spawn2.stdout,stderr:spawn2.stderr,exitCode:spawn2.exitCode,timedOut:!0},error:`Shell action timed out after ${timeout}ms`}}let command=stringOption(options,"command");return{ok:spawn2.exitCode===0,data:{stdout:spawn2.stdout,stderr:spawn2.stderr,exitCode:spawn2.exitCode},...spawn2.exitCode===0?{}:{error:`Command "${command}" exited with ${spawn2.exitCode}`}}}}class ShellGuardRunner{processExecutor;kind="shell";constructor(processExecutor){this.processExecutor=processExecutor}async evaluate(options,context4){let spawn2=await spawnShellCommand(this.processExecutor,options,context4.workdir);return{passed:!spawn2.timedOut&&spawn2.exitCode===0,report:{stdout:spawn2.stdout,stderr:spawn2.stderr,exitCode:spawn2.exitCode,...spawn2.timedOut?{timedOut:!0}:{}}}}}function stringOption(options,key,fallback){let value=options[key];if(typeof value==="string")return value;if(fallback!==void 0)return fallback;throw new WorkflowValidationError(`Action option "${key}" must be a string`)}function optionalStringOption(options,key,fallback){let value=options[key];if(typeof value==="string")return value;if(value===void 0)return fallback;throw new WorkflowValidationError(`Action option "${key}" must be a string`)}function arrayOption(options,key){let value=options[key];if(value===void 0)return[];if(Array.isArray(value)&&value.every((entry)=>typeof entry==="string"))return value;throw new WorkflowValidationError(`Action option "${key}" must be a string array`)}function optionalTimeoutOption(options){let value=options.timeout;if(value===void 0)return;if(typeof value==="number"&&Number.isFinite(value)&&value>0)return value;throw new WorkflowValidationError('shell option "timeout" must be a positive number of milliseconds')}var WORKFLOW_ENGINE_SCHEMA_SQL=`
555
555
  CREATE TABLE IF NOT EXISTS runs (
556
556
  id TEXT PRIMARY KEY,
557
557
  workflow_name TEXT,
@@ -566,7 +566,8 @@ CREATE TABLE IF NOT EXISTS runs (
566
566
  updated_at INTEGER NOT NULL DEFAULT 0,
567
567
  owner_attempt TEXT,
568
568
  owner_pid INTEGER,
569
- interrupt_reason TEXT
569
+ interrupt_reason TEXT,
570
+ terminal_reason TEXT
570
571
  );
571
572
 
572
573
  CREATE UNIQUE INDEX IF NOT EXISTS idx_runs_external_key
@@ -625,15 +626,16 @@ CREATE TABLE IF NOT EXISTS action_runs (
625
626
  ALTER TABLE runs ADD COLUMN owner_attempt TEXT;
626
627
  ALTER TABLE runs ADD COLUMN owner_pid INTEGER;
627
628
  ALTER TABLE runs ADD COLUMN interrupt_reason TEXT;
629
+ ALTER TABLE runs ADD COLUMN terminal_reason TEXT;
628
630
  `.trim();async function applyWorkflowEngineSchema(db2){for(let statement of WORKFLOW_ENGINE_SCHEMA_SQL.split(";")){let sql4=statement.trim();if(sql4.length>0)await db2.exec(sql4)}for(let statement of WORKFLOW_ENGINE_MIGRATIONS_SQL.split(";")){let sql4=statement.trim();if(sql4.length===0)continue;try{await db2.exec(sql4)}catch(error51){if(!/duplicate column/i.test(String(error51)))throw error51}}}function isRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function defaultActionRedactor(kind,payload){if(kind!=="shell")return payload;let data=isRecord(payload.data)?{...payload.data}:payload.data;if(isRecord(data)){if("stdout"in data)data.stdout="[redacted]";if("stderr"in data)data.stderr="[redacted]"}return{...payload,data}}function applyRedactor(redactor,kind,result){let payload=isRecord(result)?result:{value:result};return redactor!==void 0?redactor(kind,payload):defaultActionRedactor(kind,payload)}class DbWorkflowPersistenceAdapter{db;schemaReady;constructor(db2){this.db=db2}ensureSchema(){return this.schemaReady??=applyWorkflowEngineSchema(this.db),this.schemaReady}async createRun(record2){if(await this.loadRun(record2.id)!==void 0)throw new RunCollisionError(record2.id);await this.ensureSchema(),await this.db.run(`INSERT INTO runs (id, workflow_name, mode, status, external_key, started_at, completed_at, metadata_json, owner_attempt, owner_pid, created_at, updated_at)
629
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,record2.id,record2.workflow_name,record2.mode,record2.status,record2.external_key??null,record2.started_at,record2.completed_at,record2.metadata_json,record2.owner_attempt??null,record2.owner_pid??null,Date.now(),Date.now())}async finalizeRun(runId,status,completedAt,fence){if(fence===void 0)return await this.db.run("UPDATE runs SET status = ?, completed_at = ?, updated_at = ? WHERE id = ?",status,completedAt,Date.now(),runId),!0;await this.db.run("UPDATE runs SET status = ?, completed_at = ?, updated_at = ? WHERE id = ? AND owner_attempt = ? AND status = 'running'",status,completedAt,Date.now(),runId,fence.ownerAttempt);let run=await this.loadRun(runId);return run!==void 0&&run.status===status&&run.owner_attempt===fence.ownerAttempt}async claimRunOwnership(runId,owner,expectedStatuses){await this.ensureSchema();let placeholders=expectedStatuses.map(()=>"?").join(", ");await this.db.run(`UPDATE runs SET status = 'running', completed_at = NULL, owner_attempt = ?, owner_pid = ?, updated_at = ?
630
- WHERE id = ? AND status IN (${placeholders})`,owner.attemptId,owner.pid??null,Date.now(),runId,...expectedStatuses);let run=await this.loadRun(runId);return run!==void 0&&run.status==="running"&&run.owner_attempt===owner.attemptId?run:void 0}async interruptRun(runId,reason){await this.ensureSchema(),await this.db.run("UPDATE runs SET status = 'interrupted', interrupt_reason = ?, completed_at = NULL, updated_at = ? WHERE id = ? AND status = 'running'",reason,Date.now(),runId);let run=await this.loadRun(runId);return run!==void 0&&run.status==="interrupted"?run:void 0}async savePhase(runId,phase,status){let op=this.phaseRow(runId,phase,status,Date.now());await this.db.run(op.sql,...op.params)}async saveTransition(runId,from,to,trigger){let op=this.transitionRow(runId,from,to,trigger,Date.now());await this.db.run(op.sql,...op.params)}async saveWorkflowState(runId,state,data){let op=this.stateRow(runId,state,data,Date.now());await this.db.run(op.sql,...op.params)}async commitTransition(runId,from,to,trigger,state,data,phase){await this.ensureSchema();let now=Date.now(),ops=[this.transitionRow(runId,from,to,trigger,now),this.stateRow(runId,state,data,now)];if(phase)ops.push(this.phaseRow(runId,phase.phase,phase.status,now));await this.db.batch(ops)}transitionRow(runId,from,to,trigger,now){return{sql:`INSERT INTO transition_runs (id, run_id, from_state, to_state, trigger, status, created_at, updated_at)
631
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,record2.id,record2.workflow_name,record2.mode,record2.status,record2.external_key??null,record2.started_at,record2.completed_at,record2.metadata_json,record2.owner_attempt??null,record2.owner_pid??null,Date.now(),Date.now())}async finalizeRun(runId,status,completedAt,fence,reason){if(fence===void 0)return await this.db.run("UPDATE runs SET status = ?, completed_at = ?, terminal_reason = ?, updated_at = ? WHERE id = ?",status,completedAt,reason??null,Date.now(),runId),!0;await this.db.run("UPDATE runs SET status = ?, completed_at = ?, terminal_reason = ?, updated_at = ? WHERE id = ? AND owner_attempt = ? AND status = 'running'",status,completedAt,reason??null,Date.now(),runId,fence.ownerAttempt);let run=await this.loadRun(runId);return run!==void 0&&run.status===status&&run.owner_attempt===fence.ownerAttempt}async claimRunOwnership(runId,owner,expectedStatuses){await this.ensureSchema();let placeholders=expectedStatuses.map(()=>"?").join(", ");await this.db.run(`UPDATE runs SET status = 'running', completed_at = NULL, terminal_reason = NULL, owner_attempt = ?, owner_pid = ?, updated_at = ?
632
+ WHERE id = ? AND status IN (${placeholders})`,owner.attemptId,owner.pid??null,Date.now(),runId,...expectedStatuses);let run=await this.loadRun(runId);return run!==void 0&&run.status==="running"&&run.owner_attempt===owner.attemptId?run:void 0}async interruptRun(runId,reason){await this.ensureSchema(),await this.db.run("UPDATE runs SET status = 'interrupted', interrupt_reason = ?, terminal_reason = ?, completed_at = NULL, updated_at = ? WHERE id = ? AND status = 'running'",reason,reason,Date.now(),runId);let run=await this.loadRun(runId);return run!==void 0&&run.status==="interrupted"?run:void 0}async savePhase(runId,phase,status){let op=this.phaseRow(runId,phase,status,Date.now());await this.db.run(op.sql,...op.params)}async saveTransition(runId,from,to,trigger){let op=this.transitionRow(runId,from,to,trigger,Date.now());await this.db.run(op.sql,...op.params)}async saveWorkflowState(runId,state,data){let op=this.stateRow(runId,state,data,Date.now());await this.db.run(op.sql,...op.params)}async commitTransition(runId,from,to,trigger,state,data,phase){await this.ensureSchema();let now=Date.now(),ops=[this.transitionRow(runId,from,to,trigger,now),this.stateRow(runId,state,data,now)];if(phase)ops.push(this.phaseRow(runId,phase.phase,phase.status,now));await this.db.batch(ops)}transitionRow(runId,from,to,trigger,now){return{sql:`INSERT INTO transition_runs (id, run_id, from_state, to_state, trigger, status, created_at, updated_at)
631
633
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,params:[`${runId}:transition:${from}:${to}:${crypto.randomUUID()}`,runId,from,to,trigger,"done",now,now]}}stateRow(runId,state,data,now){return{sql:`INSERT INTO workflow_states (id, run_id, state, data_json, created_at, updated_at)
632
634
  VALUES (?, ?, ?, ?, ?, ?)`,params:[`${runId}:state:${state}:${crypto.randomUUID()}`,runId,state,JSON.stringify(data),now,now]}}phaseRow(runId,phase,status,now){return{sql:`INSERT INTO phase_runs (id, run_id, phase, status, started_at, completed_at, created_at, updated_at)
633
635
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,params:[`${runId}:phase:${phase}:${crypto.randomUUID()}`,runId,phase,status,new Date(now).toISOString(),status==="running"?null:new Date(now).toISOString(),now,now]}}async saveActionStart(runId,node,kind,_options){let id=crypto.randomUUID(),now=Date.now();return await this.db.run(`INSERT INTO action_runs (id, run_id, node, kind, status, started_at, created_at, updated_at)
634
636
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,id,runId,node,kind,"running",new Date(now).toISOString(),now,now),id}async saveActionFinalize(actionId,status,durationMs,ok,kind,result,redactor){let now=Date.now();await this.db.run(`UPDATE action_runs
635
637
  SET status = ?, duration_ms = ?, ok = ?, result_json = ?, completed_at = ?, updated_at = ?
636
- WHERE id = ?`,status,durationMs,ok?1:0,result!==void 0?JSON.stringify(applyRedactor(redactor,kind,result)):null,new Date(now).toISOString(),now,actionId)}async loadRun(runId){return await this.ensureSchema(),await this.db.queryFirst("SELECT * FROM runs WHERE id = ?",runId)??void 0}async listRuns(){return await this.ensureSchema(),await this.db.queryAll("SELECT * FROM runs ORDER BY started_at DESC")}async findRunByKey(workflowName,externalKey){return await this.ensureSchema(),await this.db.queryFirst("SELECT * FROM runs WHERE workflow_name = ? AND external_key = ?",workflowName,externalKey)??void 0}async createOrAttachRun(record2){if(await this.ensureSchema(),record2.external_key!==void 0&&record2.external_key!==null){let existing=await this.findRunByKey(record2.workflow_name,record2.external_key);if(existing)return existing}try{await this.createRun(record2)}catch(error51){if(record2.external_key!==void 0&&record2.external_key!==null){let existing=await this.findRunByKey(record2.workflow_name,record2.external_key);if(existing)return existing}throw error51}return{...record2}}async reseedRun(runId,newState){await this.ensureSchema();let previous=await this.loadLatestStateSnapshot(runId),now=Date.now(),data={...previous?.data??{},reseeded:!0,reseededAt:new Date(now).toISOString()};return await this.commitTransition(runId,previous?.state??"",newState,"__reseed__",newState,data),{fromState:previous?.state??null,toState:newState}}async loadCurrentState(runId){return await this.ensureSchema(),(await this.db.queryFirst("SELECT state FROM workflow_states WHERE run_id = ? ORDER BY created_at DESC, rowid DESC LIMIT 1",runId))?.state}async loadLatestStateSnapshot(runId){await this.ensureSchema();let row=await this.db.queryFirst("SELECT state, data_json FROM workflow_states WHERE run_id = ? ORDER BY created_at DESC, rowid DESC LIMIT 1",runId);if(row==null)return;let data={};if(row.data_json!==null&&row.data_json.length>0)try{data=JSON.parse(row.data_json)}catch{data={}}return{state:row.state,data}}async listPausedRuns(options){await this.ensureSchema();let where=["status = 'paused'"],params=[];if(options?.workflowName!==void 0)where.push("workflow_name = ?"),params.push(options.workflowName);let limit=options?.limit??100,sql4=`SELECT * FROM runs WHERE ${where.join(" AND ")} ORDER BY updated_at DESC, rowid DESC LIMIT ?`;return params.push(limit),await this.db.queryAll(sql4,...params)}}init_dist7();async function runActionStep(action,vars,deps){let{host,persistence,lifecycle,stateOrNodeId,runId}=deps,templateContext={vars,env:deps.env,builtins:runtimeBuiltins(deps.workflowName,stateOrNodeId,runId,deps.transitionsTaken,deps.mode)},resolvedWithEnv=action.kind==="shell"?resolveShellCommandTemplates(action.options??{},templateContext):resolveTemplates(action.options??{},templateContext),{[SHELL_ENV_OPTION]:_shellEnv,...resolved}=resolvedWithEnv,actionId=await persistence.saveActionStart(runId,stateOrNodeId,action.kind,resolved),actionStartMs=Date.now();lifecycle.actionStart(stateOrNodeId,action.kind);let result;try{result=await host.runAction(action.kind,resolvedWithEnv,{runId,actionId,workdir:deps.options.workdir,stateOrNodeId,vars,env:deps.env,metadata:deps.options.metadata,events:deps.options.events})}catch(error51){result={ok:!1,error:error51 instanceof Error?error51.message:String(error51)}}finally{let durationMs=Date.now()-actionStartMs;lifecycle.actionDone(stateOrNodeId,action.kind,durationMs,result?.ok??!1),await persistence.saveActionFinalize(actionId,result?.ok===!0?"done":"failed",durationMs,result?.ok??!1,action.kind,result,deps.options.redactor??defaultActionRedactor)}if(result.terminal===!0)return{outcome:"terminal",result};if(!result.ok){if(resolveOnErrorPolicy(action.onError,deps.defaultOnError,deps.options.onError)==="fail")return{outcome:"fail",result};lifecycle.warnActionFailed(stateOrNodeId,deps.transitionsTaken,result.error)}return{outcome:"completed",result}}async function runActionSequence(actions,vars,deps){let last,acc;for(let action of actions){let step=await runActionStep(action,vars,deps);if(step.result!==void 0)last=step.result;if(step.result?.setVars)acc=mergeSetVars(acc??{},step.result.setVars),vars=mergeSetVars(vars,step.result.setVars);if(step.outcome==="terminal")return{outcome:"terminal",result:last,setVars:acc};if(step.outcome==="fail")return{outcome:"fail",result:last,setVars:acc}}return{outcome:"completed",result:last,setVars:acc}}class StateMachineDriver{options;constructor(options){this.options=options}async run(workflow,options={}){return await RunLifecycle.run(workflow.name,"state-machine",{persistence:this.options.persistence,events:options.events},options,(lifecycle)=>this.loop(workflow,options,lifecycle))}async resume(workflow,runId,resumeFromState,externalKey,options={}){return await RunLifecycle.resume(workflow.name,"state-machine",{persistence:this.options.persistence,events:options.events},runId,externalKey,(lifecycle)=>this.loop(workflow,options,lifecycle,resumeFromState),options.resumeOwner?.attemptId)}async loop(workflow,options,lifecycle,resumeFromState){let runId=lifecycle.runId,states=new Map(workflow.states.map((state)=>[state.id,state])),terminal=new Set(workflow.terminalStates??[]),failure=new Set(workflow.failureStates??[]),vars=mergeVars(workflow.vars,options.vars),env2=allowedEnv(workflow.env?.allow??[],options.env),current=resumeFromState!==void 0?states.get(resumeFromState):states.get(workflow.initialState),snapshot=resumeFromState===void 0?void 0:await this.options.persistence.loadLatestStateSnapshot(runId),transitionsTaken=snapshotTransitions(snapshot?.data),lastActionResult=snapshotActionResult(snapshot?.data),iterationBound=workflow.iterationBound??50,defaultOnError=workflow.defaultOnError,resumeMode=resumeFromState!==void 0?options.resumeMode??"skip-enter":void 0,persistedViaHop=!1;if(current===void 0){let label=resumeFromState??workflow.initialState;throw new FSMError(`State "${label}" is not declared`)}while(!0){if(resumeMode==="skip-enter")resumeMode=void 0,persistedViaHop=!0;else{if(resumeMode==="rerun-enter"){if(current.resumeRerun!==!0)throw new FSMError(`Cannot rerun-resume into state "${current.id}": not marked resumeRerun: true (mark its on-enter actions as safe to re-run, or resume with resumeMode: "skip-enter")`);resumeMode=void 0,persistedViaHop=!0}await lifecycle.enter(current.id,transitionsTaken,!persistedViaHop,vars);let enter=options.dryRun?EMPTY_OUTCOME:await runActionSequence(current.onEnter??[],vars,{host:this.options.host,persistence:this.options.persistence,lifecycle,workflowName:workflow.name,stateOrNodeId:current.id,runId,mode:"state-machine",transitionsTaken,env:env2,options,defaultOnError});if(enter.result!==void 0)lastActionResult=enter.result;if(enter.setVars)vars=mergeSetVars(vars,enter.setVars);if(enter.outcome==="terminal")return failure.has(current.id)?await lifecycle.fail(current.id,transitionsTaken,`terminal:${current.id}`):await lifecycle.done(current.id,transitionsTaken);if(enter.outcome==="fail")return await lifecycle.fail(current.id,transitionsTaken,lastActionResult?.error);if(current.pause===!0)return await lifecycle.pause(current.id,transitionsTaken,vars,lastActionResult)}let outbound=workflow.transitions.filter((transition)=>transition.from===current?.id);if(terminal.has(current.id)||outbound.length===0)return failure.has(current.id)?await lifecycle.fail(current.id,transitionsTaken,`terminal:${current.id}`):await lifecycle.done(current.id,transitionsTaken);let nextTransition=await firstPassingTransition(outbound,this.options.host,{runId,current:current.id,vars,env:env2,lastActionResult,workdir:options.workdir},lifecycle);if(nextTransition===void 0)return await lifecycle.fail(current.id,transitionsTaken,"no-passing-transition");let exit=options.dryRun?EMPTY_OUTCOME:await runActionSequence(current.onExit??[],vars,{host:this.options.host,persistence:this.options.persistence,lifecycle,workflowName:workflow.name,stateOrNodeId:current.id,runId,mode:"state-machine",transitionsTaken,env:env2,options,defaultOnError});if(exit.result!==void 0)lastActionResult=exit.result;if(exit.setVars)vars=mergeSetVars(vars,exit.setVars);if(exit.outcome==="terminal")return failure.has(current.id)?await lifecycle.fail(current.id,transitionsTaken,`terminal:${current.id}`):await lifecycle.done(current.id,transitionsTaken);if(exit.outcome==="fail")return await lifecycle.fail(current.id,transitionsTaken,exit.result?.error);if(transitionsTaken+=1,await lifecycle.commitHop(current.id,nextTransition.to,nextTransition.trigger??null,transitionsTaken,{phase:nextTransition.to,status:"running"},vars),transitionsTaken>iterationBound)return await lifecycle.fail(current.id,transitionsTaken,"iteration-bound-exceeded");let nextState=states.get(nextTransition.to);if(nextState===void 0)throw new FSMError(`Transition target "${nextTransition.to}" is not declared`);current=nextState,persistedViaHop=!0}}}var EMPTY_OUTCOME={outcome:"completed",result:void 0,setVars:void 0};async function firstPassingTransition(transitions,host,context4,lifecycle){for(let transition of transitions){if(transition.guard===void 0)return transition;let resolvedOptions=transition.guard.kind==="shell"?resolveShellCommandTemplates(transition.guard.options??{},{vars:context4.vars,env:context4.env??{}}):resolveTemplates(transition.guard.options??{},{vars:context4.vars,env:context4.env??{}}),passed=await host.evaluateGuard(transition.guard.kind,resolvedOptions,context4);if(lifecycle.guardEvaluated(context4.current,transition.to,transition.guard.kind,passed),passed)return transition}return}class TransitionFlowDriver{options;constructor(options){this.options=options}async run(workflow,options={}){return await RunLifecycle.run(workflow.name,"transition-flow",{persistence:this.options.persistence,events:options.events},options,(lifecycle)=>this.loop(workflow,options,lifecycle))}async resume(workflow,runId,resumeFromNode,externalKey,options={}){return await RunLifecycle.resume(workflow.name,"transition-flow",{persistence:this.options.persistence,events:options.events},runId,externalKey,(lifecycle)=>this.loop(workflow,options,lifecycle,resumeFromNode),options.resumeOwner?.attemptId)}async loop(workflow,options,lifecycle,resumeFromNode){let runId=lifecycle.runId,nodes=new Map(workflow.nodes.map((node)=>[node.id,node])),terminal=new Set(workflow.terminalNodes??[]),vars=mergeVars(workflow.vars,options.vars),env2=allowedEnv(workflow.env?.allow??[],options.env),current=resumeFromNode!==void 0?nodes.get(resumeFromNode):nodes.get(workflow.initialNode),snapshot=resumeFromNode===void 0?void 0:await this.options.persistence.loadLatestStateSnapshot(runId),transitionsTaken=snapshotTransitions(snapshot?.data),lastActionResult=snapshotActionResult(snapshot?.data),iterationBound=workflow.iterationBound??50,defaultOnError=workflow.defaultOnError,resumeMode=resumeFromNode!==void 0?options.resumeMode??"skip-enter":void 0,persistedViaHop=!1;if(current===void 0){let label=resumeFromNode??workflow.initialNode;throw new FSMError(`Node "${label}" is not declared`)}while(!0){if(resumeMode==="skip-enter")resumeMode=void 0,persistedViaHop=!0;else{if(resumeMode==="rerun-enter"){if(current.resumeRerun!==!0)throw new FSMError(`Cannot rerun-resume into node "${current.id}": not marked resumeRerun: true (mark its action as safe to re-run, or resume with resumeMode: "skip-enter")`);resumeMode=void 0,persistedViaHop=!0}if(await lifecycle.enter(current.id,transitionsTaken,!persistedViaHop,vars),options.dryRun){if(current.action!==void 0)lastActionResult=void 0}else if(current.action!==void 0){let step=await runActionStep(current.action,vars,{host:this.options.host,persistence:this.options.persistence,lifecycle,workflowName:workflow.name,stateOrNodeId:current.id,runId,mode:"transition-flow",transitionsTaken,env:env2,options,defaultOnError});if(lastActionResult=step.result,step.result?.setVars)vars=mergeSetVars(vars,step.result.setVars);if(step.outcome==="terminal")return await lifecycle.done(current.id,transitionsTaken);if(step.outcome==="fail")return await lifecycle.fail(current.id,transitionsTaken,step.result?.error)}if(current.pause===!0)return await lifecycle.pause(current.id,transitionsTaken,vars,lastActionResult)}let outbound=workflow.edges.filter((edge2)=>edge2.from===current?.id);if(terminal.has(current.id)||outbound.length===0)return await lifecycle.done(current.id,transitionsTaken);let edge=await firstPassingEdge(outbound,this.options.host,{runId,current:current.id,vars,env:env2,lastActionResult,workdir:options.workdir},lifecycle);if(edge===void 0)return await lifecycle.fail(current.id,transitionsTaken,"no-passing-edge");if(transitionsTaken+=1,await lifecycle.commitHop(current.id,edge.to,edge.condition?.kind??null,transitionsTaken,{phase:edge.to,status:"running"},vars),transitionsTaken>iterationBound)return await lifecycle.fail(current.id,transitionsTaken,"iteration-bound-exceeded");let nextNode=nodes.get(edge.to);if(nextNode===void 0)throw new FSMError(`Edge target "${edge.to}" is not declared`);current=nextNode,persistedViaHop=!0}}}async function firstPassingEdge(edges,host,context4,lifecycle){for(let edge of edges){if(edge.condition===void 0)return edge;let resolvedOptions=edge.condition.kind==="shell"?resolveShellCommandTemplates(edge.condition.options??{},{vars:context4.vars,env:context4.env??{}}):resolveTemplates(edge.condition.options??{},{vars:context4.vars,env:context4.env??{}}),passed=await host.evaluateGuard(edge.condition.kind,resolvedOptions,context4);if(lifecycle.guardEvaluated(context4.current,edge.to,edge.condition.kind,passed),passed)return edge}return}class WorkflowService{host;persistence;runLocks=new Map;lifecycleBus;constructor(host,persistence,lifecycleBus){this.host=host,this.persistence=persistence,this.lifecycleBus=lifecycleBus??host.lifecycleBus}resolveEvents(events){return events??(this.lifecycleBus?new EventBus({lifecycleBus:this.lifecycleBus}):void 0)}async load(path8){return await loadWorkflowDef(path8)}async run(workflow,options={}){let events=this.resolveEvents(options.events);if(workflow.kind==="transition-flow")return await new TransitionFlowDriver({host:this.host,persistence:this.persistence}).run(workflow,{...options,events});return await new StateMachineDriver({host:this.host,persistence:this.persistence}).run(workflow,{...options,events})}async runFile(path8,options={}){return await this.run(await this.load(path8),options)}async listRuns(){return await this.persistence.listRuns()}async findRunByKey(workflowName,externalKey){return await this.persistence.findRunByKey(workflowName,externalKey)}async createOrAttachRun(record2){return await this.persistence.createOrAttachRun(record2)}async reseedRun(workflowOrRunId,runIdOrNewState,newStateOrOptions,maybeOptions){let args=typeof workflowOrRunId==="string"?{workflow:void 0,runId:workflowOrRunId,newState:runIdOrNewState,options:newStateOrOptions}:{workflow:workflowOrRunId,runId:runIdOrNewState,newState:newStateOrOptions,options:maybeOptions};if(args.workflow!==void 0)this.assertReseedTargetDeclared(args.workflow,args.runId,args.newState);await this.commitReseed(args.runId,args.newState,args.options)}assertReseedTargetDeclared(workflow,runId,newState){if(workflow.kind==="transition-flow")throw new FSMError("reseedRun only supports state-machine workflows");if(!workflow.states.some((state)=>state.id===newState))throw new FSMError(`Cannot reseed run "${runId}" to undeclared state "${newState}"`)}async commitReseed(runId,newState,options){let extKey=(await this.persistence.loadRun(runId))?.external_key??void 0,result=await this.persistence.reseedRun(runId,newState);this.resolveEvents(options?.events)?.emit("workflow.run.reseeded",{runId,fromState:result.fromState??"",toState:result.toState,externalKey:extKey,severity:"warning"})}async resumeRun(workflow,runId,options){let run=await this.persistence.loadRun(runId);if(run===void 0)throw new WorkflowResumeError(`Run "${runId}" not found`);if(run.status!=="paused"&&run.status!=="interrupted")throw new WorkflowResumeError(`Run "${runId}" is not resumable (status: ${run.status})`);let currentState=await this.persistence.loadCurrentState(runId);if(currentState===void 0)throw new WorkflowResumeError(`Run "${runId}" has no persisted state to resume from`);let resumeMode=options?.resumeMode??(run.status==="interrupted"?"rerun-enter":"skip-enter");this.assertResumeRerunAllowed(workflow,currentState,resumeMode);let snapshot=await this.persistence.loadLatestStateSnapshot(runId),persistedVars=extractEffectiveVars(snapshot?.data),restoredVars=mergeVars(persistedVars,options?.vars),owner=options?.resumeOwner??{attemptId:crypto.randomUUID()},mergedOptions={...options,vars:restoredVars,resumeMode,resumeOwner:owner},claimed=await this.persistence.claimRunOwnership(runId,owner,["paused","interrupted"]);if(claimed===void 0){let current=await this.persistence.loadRun(runId);throw new WorkflowResumeError(`Run "${runId}" could not be claimed for resume (status: ${current?.status??"unknown"}, owner: ${current?.owner_attempt??"none"})`)}let extKey=claimed.external_key??void 0;if(this.resolveEvents(mergedOptions.events)?.emit("workflow.run.resumed",{runId,node:currentState,resumeMode,ownerAttemptId:owner.attemptId,externalKey:extKey,severity:"info"}),workflow.kind==="transition-flow")return await new TransitionFlowDriver({host:this.host,persistence:this.persistence}).resume(workflow,runId,currentState,extKey,mergedOptions);return await new StateMachineDriver({host:this.host,persistence:this.persistence}).resume(workflow,runId,currentState,extKey,mergedOptions)}async interruptRun(runId,reason){let interrupted=await this.persistence.interruptRun(runId,reason);if(interrupted!==void 0)this.resolveEvents(void 0)?.emit("workflow.run.interrupted",{runId,reason,externalKey:interrupted.external_key??void 0,severity:"warning"});return interrupted}assertResumeRerunAllowed(workflow,currentState,resumeMode){if(resumeMode!=="rerun-enter")return;let node=workflow.kind==="transition-flow"?workflow.nodes.find((candidate)=>candidate.id===currentState):workflow.states.find((candidate)=>candidate.id===currentState);if(node!==void 0&&node.resumeRerun!==!0)throw new FSMError(`Cannot rerun-resume into "${currentState}": not marked resumeRerun: true `+'(mark its actions as safe to re-run — idempotent or deduped by runId+state — or resume with resumeMode: "skip-enter")')}async listPausedRuns(options){return await this.persistence.listPausedRuns(options)}async requestTransition(workflow,runId,toState,options){let release,previous=this.runLocks.get(runId)??Promise.resolve(),next=previous.then(()=>new Promise((resolve)=>{release=resolve}));this.runLocks.set(runId,next),await previous;try{return await this.evaluateAndCommit(workflow,runId,toState,options)}finally{if(release(),this.runLocks.get(runId)===next)this.runLocks.delete(runId)}}async evaluateAndCommit(workflow,runId,toState,options){let currentState=await this.persistence.loadCurrentState(runId),extKey=(await this.persistence.loadRun(runId))?.external_key??void 0;if(currentState===void 0)return{allowed:!1,reason:"no-such-transition",detail:`No state recorded for run "${runId}"`};let events=this.resolveEvents(options?.events),lifecycle=RunLifecycle.forExternalTransition(workflow.name,runId,{persistence:this.persistence,events},extKey),transition=workflow.transitions.find((t)=>t.from===currentState&&t.to===toState);if(transition===void 0)return this.denyTransition(events,runId,currentState,toState,extKey,{reason:"no-such-transition",detail:`No transition from "${currentState}" to "${toState}"`});let snapshot=await this.persistence.loadLatestStateSnapshot(runId),vars=mergeVars(mergeVars(workflow.vars,extractEffectiveVars(snapshot?.data)),options?.vars),env2=allowedEnv(workflow.env?.allow??[],options?.env);if(transition.guard!==void 0){let resolvedGuardOptions=transition.guard.kind==="shell"?resolveShellCommandTemplates(transition.guard.options??{},{vars,env:env2}):resolveTemplates(transition.guard.options??{},{vars,env:env2}),guardResult=await this.host.evaluateGuardResult(transition.guard.kind,resolvedGuardOptions,{runId,current:currentState,lastActionResult:snapshotActionResult(snapshot?.data),vars,env:env2,workdir:options?.workdir});if(lifecycle.guardEvaluated(currentState,toState,transition.guard.kind,guardResult.passed),!guardResult.passed)return this.denyTransition(events,runId,currentState,toState,extKey,{reason:"guard-failed",detail:`Guard "${transition.guard.kind}" denied transition from "${currentState}" to "${toState}"`,guardKind:transition.guard.kind,...guardResult.report===void 0?{}:{guardReport:guardResult.report}})}let trigger=transition.trigger??null;return await lifecycle.commitHop(currentState,toState,trigger,snapshotTransitions(snapshot?.data)+1,void 0,vars),events?.emit("workflow.transition.requested",{runId,from:currentState,to:toState,trigger,externalKey:extKey,severity:"info"}),{allowed:!0,fromState:currentState,toState}}denyTransition(events,runId,from,to,externalKey,denial){return events?.emit("workflow.transition.denied",{runId,from,to,reason:denial.reason,externalKey,severity:"error"}),{allowed:!1,...denial}}}function extractEffectiveVars(data){if(data===void 0)return{};let raw=data.effectiveVars;if(raw===void 0||raw===null)return{};if(typeof raw!=="object")return{};let filtered={};for(let[key,value]of Object.entries(raw))if(typeof value==="string")filtered[key]=value;return filtered}var RULE_ENGINE_SCHEMA_SQL=`
638
+ WHERE id = ?`,status,durationMs,ok?1:0,result!==void 0?JSON.stringify(applyRedactor(redactor,kind,result)):null,new Date(now).toISOString(),now,actionId)}async loadRun(runId){return await this.ensureSchema(),await this.db.queryFirst("SELECT * FROM runs WHERE id = ?",runId)??void 0}async listRuns(){return await this.ensureSchema(),await this.db.queryAll("SELECT * FROM runs ORDER BY started_at DESC")}async findRunByKey(workflowName,externalKey){return await this.ensureSchema(),await this.db.queryFirst("SELECT * FROM runs WHERE workflow_name = ? AND external_key = ?",workflowName,externalKey)??void 0}async createOrAttachRun(record2){if(await this.ensureSchema(),record2.external_key!==void 0&&record2.external_key!==null){let existing=await this.findRunByKey(record2.workflow_name,record2.external_key);if(existing)return existing}try{await this.createRun(record2)}catch(error51){if(record2.external_key!==void 0&&record2.external_key!==null){let existing=await this.findRunByKey(record2.workflow_name,record2.external_key);if(existing)return existing}throw error51}return{...record2}}async reseedRun(runId,newState){await this.ensureSchema();let previous=await this.loadLatestStateSnapshot(runId),now=Date.now(),data={...previous?.data??{},reseeded:!0,reseededAt:new Date(now).toISOString()};return await this.commitTransition(runId,previous?.state??"",newState,"__reseed__",newState,data),{fromState:previous?.state??null,toState:newState}}async loadCurrentState(runId){return await this.ensureSchema(),(await this.db.queryFirst("SELECT state FROM workflow_states WHERE run_id = ? ORDER BY created_at DESC, rowid DESC LIMIT 1",runId))?.state}async loadLatestStateSnapshot(runId){await this.ensureSchema();let row=await this.db.queryFirst("SELECT state, data_json FROM workflow_states WHERE run_id = ? ORDER BY created_at DESC, rowid DESC LIMIT 1",runId);if(row==null)return;let data={};if(row.data_json!==null&&row.data_json.length>0)try{data=JSON.parse(row.data_json)}catch{data={}}return{state:row.state,data}}async listPausedRuns(options){await this.ensureSchema();let where=["status = 'paused'"],params=[];if(options?.workflowName!==void 0)where.push("workflow_name = ?"),params.push(options.workflowName);let limit=options?.limit??100,sql4=`SELECT * FROM runs WHERE ${where.join(" AND ")} ORDER BY updated_at DESC, rowid DESC LIMIT ?`;return params.push(limit),await this.db.queryAll(sql4,...params)}}init_dist7();async function runActionStep(action,vars,deps){let{host,persistence,lifecycle,stateOrNodeId,runId}=deps,templateContext={vars,env:deps.env,builtins:runtimeBuiltins(deps.workflowName,stateOrNodeId,runId,deps.transitionsTaken,deps.mode)},resolvedWithEnv=action.kind==="shell"?resolveShellCommandTemplates(action.options??{},templateContext):resolveTemplates(action.options??{},templateContext),{[SHELL_ENV_OPTION]:_shellEnv,...resolved}=resolvedWithEnv,actionId=await persistence.saveActionStart(runId,stateOrNodeId,action.kind,resolved),actionStartMs=Date.now();lifecycle.actionStart(stateOrNodeId,action.kind);let result;try{result=await host.runAction(action.kind,resolvedWithEnv,{runId,actionId,workdir:deps.options.workdir,stateOrNodeId,vars,env:deps.env,metadata:deps.options.metadata,events:deps.options.events})}catch(error51){result={ok:!1,error:error51 instanceof Error?error51.message:String(error51)}}finally{let durationMs=Date.now()-actionStartMs;lifecycle.actionDone(stateOrNodeId,action.kind,durationMs,result?.ok??!1),await persistence.saveActionFinalize(actionId,result?.ok===!0?"done":"failed",durationMs,result?.ok??!1,action.kind,result,deps.options.redactor??defaultActionRedactor)}if(result.terminal===!0)return{outcome:"terminal",result};if(!result.ok){if(resolveOnErrorPolicy(action.onError,deps.defaultOnError,deps.options.onError)==="fail")return{outcome:"fail",result};lifecycle.warnActionFailed(stateOrNodeId,deps.transitionsTaken,result.error)}return{outcome:"completed",result}}async function runActionSequence(actions,vars,deps){let last,acc;for(let action of actions){let step=await runActionStep(action,vars,deps);if(step.result!==void 0)last=step.result;if(step.result?.setVars)acc=mergeSetVars(acc??{},step.result.setVars),vars=mergeSetVars(vars,step.result.setVars);if(step.outcome==="terminal")return{outcome:"terminal",result:last,setVars:acc};if(step.outcome==="fail")return{outcome:"fail",result:last,setVars:acc}}return{outcome:"completed",result:last,setVars:acc}}class StateMachineDriver{options;constructor(options){this.options=options}async run(workflow,options={}){return await RunLifecycle.run(workflow.name,"state-machine",{persistence:this.options.persistence,events:options.events},options,(lifecycle)=>this.loop(workflow,options,lifecycle))}async resume(workflow,runId,resumeFromState,externalKey,options={}){return await RunLifecycle.resume(workflow.name,"state-machine",{persistence:this.options.persistence,events:options.events},runId,externalKey,(lifecycle)=>this.loop(workflow,options,lifecycle,resumeFromState),options.resumeOwner?.attemptId)}async loop(workflow,options,lifecycle,resumeFromState){let runId=lifecycle.runId,states=new Map(workflow.states.map((state)=>[state.id,state])),terminal=new Set(workflow.terminalStates??[]),failure=new Set(workflow.failureStates??[]),vars=mergeVars(workflow.vars,options.vars),env2=allowedEnv(workflow.env?.allow??[],options.env),current=resumeFromState!==void 0?states.get(resumeFromState):states.get(workflow.initialState),snapshot=resumeFromState===void 0?void 0:await this.options.persistence.loadLatestStateSnapshot(runId),transitionsTaken=snapshotTransitions(snapshot?.data),lastActionResult=snapshotActionResult(snapshot?.data),iterationBound=workflow.iterationBound??50,defaultOnError=workflow.defaultOnError,resumeMode=resumeFromState!==void 0?options.resumeMode??"skip-enter":void 0,persistedViaHop=!1,declaredTerminalReason;if(current===void 0){let label=resumeFromState??workflow.initialState;throw new FSMError(`State "${label}" is not declared`)}while(!0){if(resumeMode==="skip-enter")resumeMode=void 0,persistedViaHop=!0;else{if(resumeMode==="rerun-enter"){if(current.resumeRerun!==!0)throw new FSMError(`Cannot rerun-resume into state "${current.id}": not marked resumeRerun: true (mark its on-enter actions as safe to re-run, or resume with resumeMode: "skip-enter")`);resumeMode=void 0,persistedViaHop=!0}await lifecycle.enter(current.id,transitionsTaken,!persistedViaHop,vars);let enter=options.dryRun?EMPTY_OUTCOME:await runActionSequence(current.onEnter??[],vars,{host:this.options.host,persistence:this.options.persistence,lifecycle,workflowName:workflow.name,stateOrNodeId:current.id,runId,mode:"state-machine",transitionsTaken,env:env2,options,defaultOnError});if(enter.result!==void 0)lastActionResult=enter.result;if(enter.setVars)vars=mergeSetVars(vars,enter.setVars);if(enter.outcome==="terminal")return failure.has(current.id)?await lifecycle.fail(current.id,transitionsTaken,`terminal:${current.id}`):await lifecycle.done(current.id,transitionsTaken);if(enter.outcome==="fail")return await lifecycle.fail(current.id,transitionsTaken,lastActionResult?.error);if(current.pause===!0)return await lifecycle.pause(current.id,transitionsTaken,vars,lastActionResult)}let outbound=workflow.transitions.filter((transition)=>transition.from===current?.id);if(terminal.has(current.id)||outbound.length===0){let declared=declaredTerminalReason;return declaredTerminalReason=void 0,failure.has(current.id)?await lifecycle.fail(current.id,transitionsTaken,declared??`terminal:${current.id}`):await lifecycle.done(current.id,transitionsTaken,declared)}let nextTransition=await firstPassingTransition(outbound,this.options.host,{runId,current:current.id,vars,env:env2,lastActionResult,workdir:options.workdir},lifecycle);if(nextTransition===void 0)return await lifecycle.fail(current.id,transitionsTaken,"no-passing-transition");let exit=options.dryRun?EMPTY_OUTCOME:await runActionSequence(current.onExit??[],vars,{host:this.options.host,persistence:this.options.persistence,lifecycle,workflowName:workflow.name,stateOrNodeId:current.id,runId,mode:"state-machine",transitionsTaken,env:env2,options,defaultOnError});if(exit.result!==void 0)lastActionResult=exit.result;if(exit.setVars)vars=mergeSetVars(vars,exit.setVars);if(exit.outcome==="terminal")return failure.has(current.id)?await lifecycle.fail(current.id,transitionsTaken,`terminal:${current.id}`):await lifecycle.done(current.id,transitionsTaken);if(exit.outcome==="fail")return await lifecycle.fail(current.id,transitionsTaken,exit.result?.error);if(transitionsTaken+=1,await lifecycle.commitHop(current.id,nextTransition.to,nextTransition.trigger??null,transitionsTaken,{phase:nextTransition.to,status:"running"},vars),transitionsTaken>iterationBound)return await lifecycle.fail(current.id,transitionsTaken,"iteration-bound-exceeded");let nextState=states.get(nextTransition.to);if(nextState===void 0)throw new FSMError(`Transition target "${nextTransition.to}" is not declared`);current=nextState,declaredTerminalReason=nextTransition.terminalReason,persistedViaHop=!0}}}var EMPTY_OUTCOME={outcome:"completed",result:void 0,setVars:void 0};async function firstPassingTransition(transitions,host,context4,lifecycle){for(let transition of transitions){if(transition.guard===void 0)return transition;let resolvedOptions=transition.guard.kind==="shell"?resolveShellCommandTemplates(transition.guard.options??{},{vars:context4.vars,env:context4.env??{}}):resolveTemplates(transition.guard.options??{},{vars:context4.vars,env:context4.env??{}}),passed=await host.evaluateGuard(transition.guard.kind,resolvedOptions,context4);if(lifecycle.guardEvaluated(context4.current,transition.to,transition.guard.kind,passed),passed)return transition}return}class TransitionFlowDriver{options;constructor(options){this.options=options}async run(workflow,options={}){return await RunLifecycle.run(workflow.name,"transition-flow",{persistence:this.options.persistence,events:options.events},options,(lifecycle)=>this.loop(workflow,options,lifecycle))}async resume(workflow,runId,resumeFromNode,externalKey,options={}){return await RunLifecycle.resume(workflow.name,"transition-flow",{persistence:this.options.persistence,events:options.events},runId,externalKey,(lifecycle)=>this.loop(workflow,options,lifecycle,resumeFromNode),options.resumeOwner?.attemptId)}async loop(workflow,options,lifecycle,resumeFromNode){let runId=lifecycle.runId,nodes=new Map(workflow.nodes.map((node)=>[node.id,node])),terminal=new Set(workflow.terminalNodes??[]),vars=mergeVars(workflow.vars,options.vars),env2=allowedEnv(workflow.env?.allow??[],options.env),current=resumeFromNode!==void 0?nodes.get(resumeFromNode):nodes.get(workflow.initialNode),snapshot=resumeFromNode===void 0?void 0:await this.options.persistence.loadLatestStateSnapshot(runId),transitionsTaken=snapshotTransitions(snapshot?.data),lastActionResult=snapshotActionResult(snapshot?.data),iterationBound=workflow.iterationBound??50,defaultOnError=workflow.defaultOnError,resumeMode=resumeFromNode!==void 0?options.resumeMode??"skip-enter":void 0,persistedViaHop=!1;if(current===void 0){let label=resumeFromNode??workflow.initialNode;throw new FSMError(`Node "${label}" is not declared`)}while(!0){if(resumeMode==="skip-enter")resumeMode=void 0,persistedViaHop=!0;else{if(resumeMode==="rerun-enter"){if(current.resumeRerun!==!0)throw new FSMError(`Cannot rerun-resume into node "${current.id}": not marked resumeRerun: true (mark its action as safe to re-run, or resume with resumeMode: "skip-enter")`);resumeMode=void 0,persistedViaHop=!0}if(await lifecycle.enter(current.id,transitionsTaken,!persistedViaHop,vars),options.dryRun){if(current.action!==void 0)lastActionResult=void 0}else if(current.action!==void 0){let step=await runActionStep(current.action,vars,{host:this.options.host,persistence:this.options.persistence,lifecycle,workflowName:workflow.name,stateOrNodeId:current.id,runId,mode:"transition-flow",transitionsTaken,env:env2,options,defaultOnError});if(lastActionResult=step.result,step.result?.setVars)vars=mergeSetVars(vars,step.result.setVars);if(step.outcome==="terminal")return await lifecycle.done(current.id,transitionsTaken);if(step.outcome==="fail")return await lifecycle.fail(current.id,transitionsTaken,step.result?.error)}if(current.pause===!0)return await lifecycle.pause(current.id,transitionsTaken,vars,lastActionResult)}let outbound=workflow.edges.filter((edge2)=>edge2.from===current?.id);if(terminal.has(current.id)||outbound.length===0)return await lifecycle.done(current.id,transitionsTaken);let edge=await firstPassingEdge(outbound,this.options.host,{runId,current:current.id,vars,env:env2,lastActionResult,workdir:options.workdir},lifecycle);if(edge===void 0)return await lifecycle.fail(current.id,transitionsTaken,"no-passing-edge");if(transitionsTaken+=1,await lifecycle.commitHop(current.id,edge.to,edge.condition?.kind??null,transitionsTaken,{phase:edge.to,status:"running"},vars),transitionsTaken>iterationBound)return await lifecycle.fail(current.id,transitionsTaken,"iteration-bound-exceeded");let nextNode=nodes.get(edge.to);if(nextNode===void 0)throw new FSMError(`Edge target "${edge.to}" is not declared`);current=nextNode,persistedViaHop=!0}}}async function firstPassingEdge(edges,host,context4,lifecycle){for(let edge of edges){if(edge.condition===void 0)return edge;let resolvedOptions=edge.condition.kind==="shell"?resolveShellCommandTemplates(edge.condition.options??{},{vars:context4.vars,env:context4.env??{}}):resolveTemplates(edge.condition.options??{},{vars:context4.vars,env:context4.env??{}}),passed=await host.evaluateGuard(edge.condition.kind,resolvedOptions,context4);if(lifecycle.guardEvaluated(context4.current,edge.to,edge.condition.kind,passed),passed)return edge}return}class WorkflowService{host;persistence;runLocks=new Map;lifecycleBus;constructor(host,persistence,lifecycleBus){this.host=host,this.persistence=persistence,this.lifecycleBus=lifecycleBus??host.lifecycleBus}resolveEvents(events){return events??(this.lifecycleBus?new EventBus({lifecycleBus:this.lifecycleBus}):void 0)}async load(path8){return await loadWorkflowDef(path8)}async run(workflow,options={}){let events=this.resolveEvents(options.events);if(workflow.kind==="transition-flow")return await new TransitionFlowDriver({host:this.host,persistence:this.persistence}).run(workflow,{...options,events});return await new StateMachineDriver({host:this.host,persistence:this.persistence}).run(workflow,{...options,events})}async runFile(path8,options={}){return await this.run(await this.load(path8),options)}async listRuns(){return await this.persistence.listRuns()}async findRunByKey(workflowName,externalKey){return await this.persistence.findRunByKey(workflowName,externalKey)}async createOrAttachRun(record2){return await this.persistence.createOrAttachRun(record2)}async reseedRun(workflowOrRunId,runIdOrNewState,newStateOrOptions,maybeOptions){let args=typeof workflowOrRunId==="string"?{workflow:void 0,runId:workflowOrRunId,newState:runIdOrNewState,options:newStateOrOptions}:{workflow:workflowOrRunId,runId:runIdOrNewState,newState:newStateOrOptions,options:maybeOptions};if(args.workflow!==void 0)this.assertReseedTargetDeclared(args.workflow,args.runId,args.newState);await this.commitReseed(args.runId,args.newState,args.options)}assertReseedTargetDeclared(workflow,runId,newState){if(workflow.kind==="transition-flow")throw new FSMError("reseedRun only supports state-machine workflows");if(!workflow.states.some((state)=>state.id===newState))throw new FSMError(`Cannot reseed run "${runId}" to undeclared state "${newState}"`)}async commitReseed(runId,newState,options){let extKey=(await this.persistence.loadRun(runId))?.external_key??void 0,result=await this.persistence.reseedRun(runId,newState);this.resolveEvents(options?.events)?.emit("workflow.run.reseeded",{runId,fromState:result.fromState??"",toState:result.toState,externalKey:extKey,severity:"warning"})}async resumeRun(workflow,runId,options){let run=await this.persistence.loadRun(runId);if(run===void 0)throw new WorkflowResumeError(`Run "${runId}" not found`);if(run.status!=="paused"&&run.status!=="interrupted")throw new WorkflowResumeError(`Run "${runId}" is not resumable (status: ${run.status})`);let currentState=await this.persistence.loadCurrentState(runId);if(currentState===void 0)throw new WorkflowResumeError(`Run "${runId}" has no persisted state to resume from`);let resumeMode=options?.resumeMode??(run.status==="interrupted"?"rerun-enter":"skip-enter");this.assertResumeRerunAllowed(workflow,currentState,resumeMode);let snapshot=await this.persistence.loadLatestStateSnapshot(runId),persistedVars=extractEffectiveVars(snapshot?.data),restoredVars=mergeVars(persistedVars,options?.vars),owner=options?.resumeOwner??{attemptId:crypto.randomUUID()},mergedOptions={...options,vars:restoredVars,resumeMode,resumeOwner:owner},claimed=await this.persistence.claimRunOwnership(runId,owner,["paused","interrupted"]);if(claimed===void 0){let current=await this.persistence.loadRun(runId);throw new WorkflowResumeError(`Run "${runId}" could not be claimed for resume (status: ${current?.status??"unknown"}, owner: ${current?.owner_attempt??"none"})`)}let extKey=claimed.external_key??void 0;if(this.resolveEvents(mergedOptions.events)?.emit("workflow.run.resumed",{runId,node:currentState,resumeMode,ownerAttemptId:owner.attemptId,externalKey:extKey,severity:"info"}),workflow.kind==="transition-flow")return await new TransitionFlowDriver({host:this.host,persistence:this.persistence}).resume(workflow,runId,currentState,extKey,mergedOptions);return await new StateMachineDriver({host:this.host,persistence:this.persistence}).resume(workflow,runId,currentState,extKey,mergedOptions)}async interruptRun(runId,reason){let interrupted=await this.persistence.interruptRun(runId,reason);if(interrupted!==void 0)this.resolveEvents(void 0)?.emit("workflow.run.interrupted",{runId,reason,externalKey:interrupted.external_key??void 0,severity:"warning"});return interrupted}assertResumeRerunAllowed(workflow,currentState,resumeMode){if(resumeMode!=="rerun-enter")return;let node=workflow.kind==="transition-flow"?workflow.nodes.find((candidate)=>candidate.id===currentState):workflow.states.find((candidate)=>candidate.id===currentState);if(node!==void 0&&node.resumeRerun!==!0)throw new FSMError(`Cannot rerun-resume into "${currentState}": not marked resumeRerun: true `+'(mark its actions as safe to re-run — idempotent or deduped by runId+state — or resume with resumeMode: "skip-enter")')}async listPausedRuns(options){return await this.persistence.listPausedRuns(options)}async requestTransition(workflow,runId,toState,options){let release,previous=this.runLocks.get(runId)??Promise.resolve(),next=previous.then(()=>new Promise((resolve)=>{release=resolve}));this.runLocks.set(runId,next),await previous;try{return await this.evaluateAndCommit(workflow,runId,toState,options)}finally{if(release(),this.runLocks.get(runId)===next)this.runLocks.delete(runId)}}async evaluateAndCommit(workflow,runId,toState,options){let currentState=await this.persistence.loadCurrentState(runId),extKey=(await this.persistence.loadRun(runId))?.external_key??void 0;if(currentState===void 0)return{allowed:!1,reason:"no-such-transition",detail:`No state recorded for run "${runId}"`};let events=this.resolveEvents(options?.events),lifecycle=RunLifecycle.forExternalTransition(workflow.name,runId,{persistence:this.persistence,events},extKey),transition=workflow.transitions.find((t)=>t.from===currentState&&t.to===toState);if(transition===void 0)return this.denyTransition(events,runId,currentState,toState,extKey,{reason:"no-such-transition",detail:`No transition from "${currentState}" to "${toState}"`});let snapshot=await this.persistence.loadLatestStateSnapshot(runId),vars=mergeVars(mergeVars(workflow.vars,extractEffectiveVars(snapshot?.data)),options?.vars),env2=allowedEnv(workflow.env?.allow??[],options?.env);if(transition.guard!==void 0){let resolvedGuardOptions=transition.guard.kind==="shell"?resolveShellCommandTemplates(transition.guard.options??{},{vars,env:env2}):resolveTemplates(transition.guard.options??{},{vars,env:env2}),guardResult=await this.host.evaluateGuardResult(transition.guard.kind,resolvedGuardOptions,{runId,current:currentState,lastActionResult:snapshotActionResult(snapshot?.data),vars,env:env2,workdir:options?.workdir});if(lifecycle.guardEvaluated(currentState,toState,transition.guard.kind,guardResult.passed),!guardResult.passed)return this.denyTransition(events,runId,currentState,toState,extKey,{reason:"guard-failed",detail:`Guard "${transition.guard.kind}" denied transition from "${currentState}" to "${toState}"`,guardKind:transition.guard.kind,...guardResult.report===void 0?{}:{guardReport:guardResult.report}})}let trigger=transition.trigger??null;return await lifecycle.commitHop(currentState,toState,trigger,snapshotTransitions(snapshot?.data)+1,void 0,vars),events?.emit("workflow.transition.requested",{runId,from:currentState,to:toState,trigger,externalKey:extKey,severity:"info"}),{allowed:!0,fromState:currentState,toState}}denyTransition(events,runId,from,to,externalKey,denial){return events?.emit("workflow.transition.denied",{runId,from,to,reason:denial.reason,externalKey,severity:"error"}),{allowed:!1,...denial}}}function extractEffectiveVars(data){if(data===void 0)return{};let raw=data.effectiveVars;if(raw===void 0||raw===null)return{};if(typeof raw!=="object")return{};let filtered={};for(let[key,value]of Object.entries(raw))if(typeof value==="string")filtered[key]=value;return filtered}var RULE_ENGINE_SCHEMA_SQL=`
637
639
  CREATE TABLE IF NOT EXISTS rule_runs (
638
640
  id TEXT PRIMARY KEY,
639
641
  preset TEXT,
@@ -837,6 +839,8 @@ ALTER TABLE agent_executor_updates ADD COLUMN owner TEXT;
837
839
  ALTER TABLE agent_executor_updates ADD COLUMN layer TEXT;
838
840
  ALTER TABLE agent_executor_updates ADD COLUMN skipped_reason TEXT;
839
841
  UPDATE agent_executor_updates SET owner = 'quota', layer = 'project' WHERE owner IS NULL;
842
+ `,CLI_RUNS_TERMINAL_REASON_SCHEMA_SQL=`
843
+ ALTER TABLE runs ADD COLUMN terminal_reason TEXT;
840
844
  `,PROJECT_CLAIMS_SCHEMA_SQL=`
841
845
  CREATE TABLE IF NOT EXISTS project_claims (
842
846
  project_path TEXT NOT NULL,
@@ -1421,7 +1425,7 @@ ALTER TABLE queue_jobs ADD COLUMN timeout_ms INTEGER;
1421
1425
  ALTER TABLE queue_jobs ADD COLUMN timeout_unlimited INTEGER NOT NULL DEFAULT 0;
1422
1426
  ALTER TABLE queue_jobs ADD COLUMN attempt_token TEXT;
1423
1427
  ALTER TABLE queue_jobs ADD COLUMN lease_expires_at INTEGER;
1424
- `,CLI_MIGRATIONS=[{id:"0000_spur_cli_foundation",sql:CLI_SCHEMA_SQL},{id:"0001_spur_cli_team_inbox",sql:INBOX_MESSAGES_SCHEMA_SQL},{id:"0002_spur_cli_rule_history",sql:RULE_ENGINE_SCHEMA_SQL},{id:"0003_spur_cli_planning",sql:PLANNING_SCHEMA_SQL},{id:"0004_spur_cli_queue_jobs",sql:QUEUE_JOBS_SCHEMA_SQL},{id:"0005_spur_cli_run_pid",sql:RUN_PID_COLUMN_SCHEMA_SQL,addColumnIfMissing:{table:"runs",column:"pid"}},{id:"0006_spur_cli_system_events",sql:SYSTEM_EVENTS_SCHEMA_SQL},{id:"0007_spur_cli_runs_external_key",sql:RUNS_EXTERNAL_KEY_COLUMN_SCHEMA_SQL,addColumnIfMissing:{table:"runs",column:"external_key"}},{id:"0008_spur_cli_system_events_correlation",sql:SYSTEM_EVENTS_CORRELATION_COLUMNS_SCHEMA_SQL,addColumnIfMissing:{table:"system_events",column:"sequence"}},{id:"0009_spur_cli_history_message_run_idx",sql:HISTORY_MESSAGE_RUN_INDEX_SCHEMA_SQL},{id:"0010_spur_cli_coordination_runs",sql:COORDINATION_RUNS_SCHEMA_SQL},{id:"0011_spur_cli_system_events_sequence_idx",sql:SYSTEM_EVENTS_SEQUENCE_INDEX_SCHEMA_SQL},{id:"0012_spur_cli_history_tool_call_args_raw",sql:HISTORY_TOOL_CALL_ARGS_RAW_SCHEMA_SQL,addColumnIfMissing:{table:"history_tool_call",column:"args_raw"}},{id:"0013_spur_cli_history_run_session",sql:HISTORY_RUN_SESSION_SCHEMA_SQL},{id:"0014_spur_cli_system_events_name_occurred_idx",sql:SYSTEM_EVENTS_NAME_OCCURRED_INDEX_SCHEMA_SQL},{id:"0015_spur_cli_history_tool_call_call_id",sql:HISTORY_TOOL_CALL_CALL_ID_SCHEMA_SQL,addColumnIfMissing:{table:"history_tool_call",column:"call_id"}},{id:"0016_spur_cli_history_message_ts_nullable",sql:HISTORY_MESSAGE_TS_NULLABLE_SCHEMA_SQL},{id:"0017_spur_cli_runs_status_completed_to_done",sql:"UPDATE runs SET status = 'done' WHERE status = 'completed'"},{id:"0018_spur_cli_history_message_request_id",sql:HISTORY_MESSAGE_REQUEST_ID_SCHEMA_SQL,addColumnIfMissing:{table:"history_message",column:"request_id"}},{id:"0019_spur_cli_history_etl_tables_drop",sql:HISTORY_ETL_TABLES_DROP_SCHEMA_SQL},{id:"0020_spur_cli_history_board_query_indexes",sql:HISTORY_BOARD_QUERY_INDEXES_SCHEMA_SQL},{id:"0021_spur_cli_history_board_rollups",sql:HISTORY_BOARD_ROLLUPS_SCHEMA_SQL},{id:"0022_spur_cli_history_performance_indexes",sql:HISTORY_PERFORMANCE_INDEXES_SCHEMA_SQL},{id:"0023_spur_cli_history_message_request_id_idx",sql:HISTORY_MESSAGE_REQUEST_ID_INDEX_SCHEMA_SQL},{id:"0024_spur_cli_history_checkpoint_identity",sql:"ALTER TABLE history_import_checkpoint ADD COLUMN source_size INTEGER",addColumnIfMissing:{table:"history_import_checkpoint",column:"source_size"}},{id:"0025_spur_cli_history_checkpoint_identity_mtime",sql:"ALTER TABLE history_import_checkpoint ADD COLUMN source_mtime_ms REAL",addColumnIfMissing:{table:"history_import_checkpoint",column:"source_mtime_ms"}},{id:"0026_spur_cli_history_message_duration_source",sql:"ALTER TABLE history_message ADD COLUMN duration_source TEXT",addColumnIfMissing:{table:"history_message",column:"duration_source"}},{id:"0027_spur_cli_history_refresh_active_unique",sql:HISTORY_REFRESH_ACTIVE_UNIQUE_SCHEMA_SQL},{id:"0028_spur_cli_history_task_session",sql:HISTORY_TASK_SESSION_SCHEMA_SQL},{id:"0029_spur_cli_history_tool_call_indexes",sql:HISTORY_TOOL_CALL_INDEXES_SCHEMA_SQL},{id:"0030_spur_cli_history_board_covering_indexes",sql:HISTORY_BOARD_COVERING_INDEXES_SCHEMA_SQL},{id:"0031_spur_cli_history_board_tool_stats_columns",sql:HISTORY_BOARD_TOOL_STATS_COLUMNS_SCHEMA_SQL},{id:"0032_spur_cli_history_board_skill_5m",sql:HISTORY_BOARD_SKILL_5M_SCHEMA_SQL},{id:"0033_spur_cli_importer_schema_version",sql:`INSERT OR REPLACE INTO "__spur_cli_migrations" (id, applied_at) VALUES ('${IMPORTER_SCHEMA_LEDGER_PREFIX}${HISTORY_IMPORT_SCHEMA_VERSION}', strftime('%s', 'now') * 1000);`},{id:"0034_spur_cli_history_tool_identity",sql:HISTORY_TOOL_IDENTITY_SCHEMA_SQL},{id:"0035_spur_cli_history_measure_vector",sql:HISTORY_MEASURE_VECTOR_SCHEMA_SQL},{id:"0036_spur_cli_history_rollup_watermark",sql:HISTORY_ROLLUP_WATERMARK_SCHEMA_SQL},{id:"0037_spur_cli_history_dimension_marts",sql:HISTORY_DIMENSION_MARTS_SCHEMA_SQL},{id:"0038_spur_cli_retention_compaction_meta",sql:RETENTION_COMPACTION_META_SCHEMA_SQL},{id:"0039_spur_cli_bounded_rollup_derivations",sql:BOUNDED_ROLLUP_DERIVATIONS_SCHEMA_SQL,addColumnIfMissing:{table:"history_board_source_daily",column:"raw_messages"}},{id:"0040_spur_cli_agent_executor_updates",sql:AGENT_EXECUTOR_UPDATES_SCHEMA_SQL},{id:"0041_spur_cli_queue_jobs_deadline_lease_columns",sql:QUEUE_JOBS_DEADLINE_LEASE_COLUMNS_SCHEMA_SQL,addColumnIfMissing:{table:"queue_jobs",column:"timeout_ms"}},{id:"0042_spur_cli_history_model_fallback_index",sql:HISTORY_MESSAGE_MODEL_FALLBACK_INDEX_SCHEMA_SQL},{id:"0043_spur_cli_inbox_messages_request_key",sql:INBOX_MESSAGES_REQUEST_KEY_SCHEMA_SQL,addColumnIfMissing:{table:"inbox_messages",column:"request_key"}},{id:"0044_spur_cli_coordination_runs_receipt_columns",sql:COORDINATION_RUNS_RECEIPT_COLUMNS_SCHEMA_SQL,addColumnIfMissing:{table:"coordination_runs",column:"message_ids_json"}},{id:"0045_spur_cli_project_claims",sql:PROJECT_CLAIMS_SCHEMA_SQL},{id:"0046_spur_cli_project_strategy",sql:PROJECT_STRATEGY_SCHEMA_SQL},{id:"0047_spur_cli_scheduler_custom_active_unique",sql:SCHEDULER_CUSTOM_ACTIVE_UNIQUE_SCHEMA_SQL},{id:"0048_spur_cli_agent_executor_updates_owner_columns",sql:AGENT_EXECUTOR_UPDATES_OWNER_COLUMNS_SCHEMA_SQL,addColumnIfMissing:{table:"agent_executor_updates",column:"owner"}}];async function allMigrationsJournaled(adapter,migrations){if(migrations.length===0)return!0;if(!await tableExists(adapter,"__spur_cli_migrations"))return!1;let placeholders=migrations.map(()=>"?").join(", ");if(((await adapter.queryFirst(`SELECT COUNT(*) AS n FROM "__spur_cli_migrations" WHERE id IN (${placeholders})`,...migrations.map((m)=>m.id)))?.n??0)!==migrations.length)return!1;if(migrations.some((m)=>m.id==="0033_spur_cli_importer_schema_version")){if(!await adapter.queryFirst('SELECT id FROM "__spur_cli_migrations" WHERE id = ?',IMPORTER_SCHEMA_LEDGER_PREFIX+HISTORY_IMPORT_SCHEMA_VERSION))return!1}return!0}async function applyCliMigrations(adapter,migrations=CLI_MIGRATIONS){if(await allMigrationsJournaled(adapter,migrations))return 0;await adapter.exec('CREATE TABLE IF NOT EXISTS "__spur_cli_migrations" (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)');let applied=0;for(let migration of migrations){if(await adapter.queryFirst('SELECT id FROM "__spur_cli_migrations" WHERE id = ?',migration.id)!=null)continue;if(migration.id==="0009_spur_cli_history_message_run_idx"&&!await tableExists(adapter,"history_message")){for(let statement of splitSqlStatements(HISTORY_IMPORT_SCHEMA_SQL))await adapter.exec(statement);let versionLedgerId=IMPORTER_SCHEMA_LEDGER_PREFIX+HISTORY_IMPORT_SCHEMA_VERSION;await adapter.run('INSERT OR REPLACE INTO "__spur_cli_migrations" (id, applied_at) VALUES (?, ?)',[versionLedgerId,Date.now()])}if((migration.id==="0024_spur_cli_history_checkpoint_identity"||migration.id==="0025_spur_cli_history_checkpoint_identity_mtime")&&!await tableExists(adapter,"history_import_checkpoint")){await adapter.run('INSERT INTO "__spur_cli_migrations" (id, applied_at) VALUES (?, ?)',[migration.id,Date.now()]);continue}if(migration.id==="0034_spur_cli_history_tool_identity"&&await tableExists(adapter,"history_tool_call")){if(!await columnExists(adapter,"history_tool_call","effective_tool_name"))await adapter.exec("ALTER TABLE history_tool_call ADD COLUMN effective_tool_name TEXT NOT NULL DEFAULT 'unknown'");if(!await columnExists(adapter,"history_tool_call","tool_name_alias"))await adapter.exec("ALTER TABLE history_tool_call ADD COLUMN tool_name_alias TEXT NOT NULL DEFAULT 'unknown'")}let addColumnGuard=migration.addColumnIfMissing,shouldApplySql=addColumnGuard===void 0||!await columnExists(adapter,addColumnGuard.table,addColumnGuard.column),tsNullableSkip=migration.id==="0016_spur_cli_history_message_ts_nullable"&&(!await tableExists(adapter,"history_message")||!await columnNotNull(adapter,"history_message","ts")),sequenceIndexSkip=migration.id==="0011_spur_cli_system_events_sequence_idx"&&!await tableExists(adapter,"system_events"),argsRawSkip=migration.id==="0012_spur_cli_history_tool_call_args_raw"&&!await tableExists(adapter,"history_tool_call"),callIdSkip=migration.id==="0015_spur_cli_history_tool_call_call_id"&&!await tableExists(adapter,"history_tool_call"),nameOccurredIndexSkip=migration.id==="0014_spur_cli_system_events_name_occurred_idx"&&!await tableExists(adapter,"system_events"),historyBoardQueryIndexesSkip=migration.id==="0020_spur_cli_history_board_query_indexes"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","seq")||!await columnExists(adapter,"history_message","duration_ms")||!await columnExists(adapter,"history_message","role")||!await columnExists(adapter,"history_message","input_tokens")||!await columnExists(adapter,"history_message","cache_read_tokens")),historyPerformanceIndexesSkip=migration.id==="0022_spur_cli_history_performance_indexes"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","ts")||!await columnExists(adapter,"history_message","model")||!await tableExists(adapter,"history_tool_call")),historyToolCallIndexesSkip=migration.id==="0029_spur_cli_history_tool_call_indexes"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","ts")||!await tableExists(adapter,"history_tool_call")),historyBoardCoveringIndexesSkip=migration.id==="0030_spur_cli_history_board_covering_indexes"&&(!await tableExists(adapter,"history_daily_stats")||!await tableExists(adapter,"history_board_tool_5m")||!await tableExists(adapter,"history_board_message_5m")||!await tableExists(adapter,"history_board_session_stats")||!await tableExists(adapter,"history_board_source_daily")||!await tableExists(adapter,"history_tool_call")||!await tableExists(adapter,"history_task_session")),runsStatusDoneSkip=migration.id==="0017_spur_cli_runs_status_completed_to_done"&&(!await tableExists(adapter,"runs")||!await columnExists(adapter,"runs","status")),historyBoardToolStatsColumnsSkip=migration.id==="0031_spur_cli_history_board_tool_stats_columns"&&(!await tableExists(adapter,"history_board_tool_stats")||await columnExists(adapter,"history_board_tool_stats","fresh_input_tokens")),queueJobsActiveIndexSkip=migration.id==="0027_spur_cli_history_refresh_active_unique"&&!await tableExists(adapter,"queue_jobs"),schedulerCustomActiveIndexSkip=migration.id==="0047_spur_cli_scheduler_custom_active_unique"&&!await tableExists(adapter,"queue_jobs"),queueJobsDeadlineLeaseSkip=migration.id==="0041_spur_cli_queue_jobs_deadline_lease_columns"&&!await tableExists(adapter,"queue_jobs"),inboxRequestKeySkip=migration.id==="0043_spur_cli_inbox_messages_request_key"&&!await tableExists(adapter,"inbox_messages"),coordinationReceiptColumnsSkip=migration.id==="0044_spur_cli_coordination_runs_receipt_columns"&&!await tableExists(adapter,"coordination_runs"),historyToolIdentitySkip=migration.id==="0034_spur_cli_history_tool_identity"&&!await tableExists(adapter,"history_tool_call"),historyMeasureVectorSkip=migration.id==="0035_spur_cli_history_measure_vector"&&(!await tableExists(adapter,"history_board_message_5m")||await columnExists(adapter,"history_board_message_5m","cache_write_tokens")),historyRollupWatermarkSkip=migration.id==="0036_spur_cli_history_rollup_watermark"&&(await tableExists(adapter,"history_board_rollup_watermark")||!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","imported_at")),boundedRollupDerivationsSkip=migration.id==="0039_spur_cli_bounded_rollup_derivations"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","source_file")||!await tableExists(adapter,"history_board_source_daily")),historyModelFallbackIndexSkip=migration.id==="0042_spur_cli_history_model_fallback_index"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","model"));if(shouldApplySql&&!sequenceIndexSkip&&!argsRawSkip&&!runsStatusDoneSkip&&!nameOccurredIndexSkip&&!historyBoardQueryIndexesSkip&&!historyPerformanceIndexesSkip&&!historyToolCallIndexesSkip&&!historyBoardCoveringIndexesSkip&&!historyBoardToolStatsColumnsSkip&&!callIdSkip&&!tsNullableSkip&&!queueJobsActiveIndexSkip&&!schedulerCustomActiveIndexSkip&&!queueJobsDeadlineLeaseSkip&&!inboxRequestKeySkip&&!coordinationReceiptColumnsSkip&&!historyToolIdentitySkip&&!historyMeasureVectorSkip&&!historyRollupWatermarkSkip&&!boundedRollupDerivationsSkip&&!historyModelFallbackIndexSkip)for(let statement of splitSqlStatements(migration.sql))await adapter.exec(statement);if(historyToolIdentitySkip&&!await tableExists(adapter,"history_tool_alias_map"))await adapter.exec("CREATE TABLE IF NOT EXISTS history_tool_alias_map (source TEXT NOT NULL, effective_tool_name TEXT NOT NULL, alias TEXT NOT NULL, PRIMARY KEY (source, effective_tool_name));");await adapter.run('INSERT INTO "__spur_cli_migrations" (id, applied_at) VALUES (?, ?)',migration.id,Date.now()),applied+=1}if(migrations.some((m)=>m.id==="0033_spur_cli_importer_schema_version")){let currentVersionLedgerId=IMPORTER_SCHEMA_LEDGER_PREFIX+HISTORY_IMPORT_SCHEMA_VERSION;if(!await adapter.queryFirst('SELECT id FROM "__spur_cli_migrations" WHERE id = ?',currentVersionLedgerId)){for(let statement of splitSqlStatements(HISTORY_IMPORT_SCHEMA_SQL))if(statement.startsWith("CREATE TABLE"))await adapter.exec(statement);await adapter.run('INSERT OR REPLACE INTO "__spur_cli_migrations" (id, applied_at) VALUES (?, ?)',[currentVersionLedgerId,Date.now()]),applied+=1}}return applied}async function columnExists(adapter,table3,column2){return(await adapter.queryAll(`PRAGMA table_info("${table3}")`)).some((row)=>row.name===column2)}async function columnNotNull(adapter,table3,column2){return(await adapter.queryAll(`PRAGMA table_info("${table3}")`)).some((row)=>row.name===column2&&row.notnull===1)}async function tableExists(adapter,table3){return await adapter.queryFirst("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?",table3)!=null}function splitSqlStatements(sql4){return sql4.split(";").map((statement)=>statement.trim()).filter(Boolean)}var SQLITE_BUSY_TIMEOUT_MS=30000;async function createMigratedDb(options){let{createDbAdapter:createDbAdapter3}=await Promise.resolve().then(() => (init_dist4(),exports_dist)),adapter=await createDbAdapter3({driver:"bun-sqlite",url:options.url});return await adapter.exec(`PRAGMA busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS}`),await applyCliMigrations(adapter),adapter}init_zod();init_zod();var STAGE_REGISTRY_SCHEMA_VERSION={major:1,minor:3},stageSchemaVersionSchema=exports_external.object({major:exports_external.number().int().nonnegative(),minor:exports_external.number().int().nonnegative()}).strict();var MUTATION_CLASSES=["none","corpus","code","tests","verdict","learnings","driver","irreversible"];var inlineExecutionSchema=exports_external.object({kind:exports_external.literal("inline"),current_agent_allowed:exports_external.literal(!0),may_reuse_captured_layers:exports_external.boolean().optional()}).strict(),subprocessExecutionSchema=exports_external.object({kind:exports_external.literal("subprocess"),current_agent_allowed:exports_external.literal(!1),via:exports_external.literal("spur-agent-run")}).strict(),deterministicExecutionSchema=exports_external.object({kind:exports_external.literal("deterministic"),current_agent_allowed:exports_external.literal(!1),executor:exports_external.enum(["cli","script"])}).strict(),hitlExecutionSchema=exports_external.object({kind:exports_external.literal("hitl"),current_agent_allowed:exports_external.literal(!0),gate_timing:exports_external.enum(["pre","post","both"])}).strict(),irreversibleExecutionSchema=exports_external.object({kind:exports_external.literal("irreversible"),requires_operator_intent:exports_external.literal(!0),current_agent_allowed:exports_external.boolean(),rollback_disclaimer:exports_external.string().min(1)}).strict(),executionKindSchema=exports_external.discriminatedUnion("kind",[inlineExecutionSchema,subprocessExecutionSchema,deterministicExecutionSchema,hitlExecutionSchema,irreversibleExecutionSchema]),ARTIFACT_DIRECTIONS=["input","output"],stageArtifactSchema=exports_external.object({kind:exports_external.string().min(1),direction:exports_external.enum(ARTIFACT_DIRECTIONS),identity:exports_external.string().optional(),description:exports_external.string().optional(),required:exports_external.boolean().optional().default(!0)}).strict(),stageGateSchema=exports_external.object({name:exports_external.string().min(1),timing:exports_external.enum(["pre","post","transition"]),min_verdict:exports_external.enum(["pass","partial","fail"]).optional(),description:exports_external.string().optional()}).strict(),stageRetryPolicySchema=exports_external.object({max_attempts:exports_external.number().int().min(1),terminal_stop:exports_external.enum(["block","escalate","fail"]),timeout_seconds:exports_external.number().int().positive().optional()}).strict(),CAPABILITY_TIERS=["cheap","standard","capable-1","capable-2","capable-3"],LEGACY_CAPABLE_ALIAS="capable";function normalizeCapabilityTier(value){return value===LEGACY_CAPABLE_ALIAS?"capable-1":value}var capabilityTierSchema=exports_external.preprocess(normalizeCapabilityTier,exports_external.enum(CAPABILITY_TIERS)),objectiveEscalationTriggerSchema=exports_external.enum(["gate-fail","timeout","insufficient-evidence","retry-exhausted","resource-exhaustion","auth"]),stageModelPolicySchema=exports_external.object({min_tier:capabilityTierSchema,fallback:exports_external.array(exports_external.object({tier:capabilityTierSchema,trigger:objectiveEscalationTriggerSchema}).strict()),override_key:exports_external.string().optional()}).strict();var CONTEXT_LAYER_NAMES=["harness-policy","project-authority","stage-contract","task-state","indexed-evidence","run-state","tool-observations"],stageContextLayerSchema=exports_external.object({layer:exports_external.enum(CONTEXT_LAYER_NAMES),required:exports_external.literal(!0)}).strict(),stageEventSchema=exports_external.object({name:exports_external.string().min(1),description:exports_external.string().optional()}).strict(),STAGE_ID_PATTERN=/^[a-z][a-z0-9-]*$/,stageRecordSchema=exports_external.object({schema_version:stageSchemaVersionSchema,id:exports_external.string().regex(STAGE_ID_PATTERN,{message:"stage id must be lowercase kebab-case"}),aliases:exports_external.array(exports_external.string().min(1)).optional().default([]),description:exports_external.string().min(1),artifacts:exports_external.array(stageArtifactSchema).min(1),reasoning_skill:exports_external.string().min(1),required_references:exports_external.array(exports_external.string().min(1)).optional().default([]),gates:exports_external.array(stageGateSchema).optional().default([]),mutation_class:exports_external.enum(MUTATION_CLASSES),retry:stageRetryPolicySchema,model_policy:stageModelPolicySchema,context_layers:exports_external.array(stageContextLayerSchema).optional().default([]),observability:exports_external.array(stageEventSchema).optional().default([]),execution:executionKindSchema}).strict();var REGISTERED_CANONICAL_STAGES=[{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"refine",aliases:["dev-refine"],description:"dev-refine: Q&A refinement, section filling, AC tightening",artifacts:[{kind:"task-section",direction:"input",required:!0,description:"Background/Requirements sections"},{kind:"task-section",direction:"output",required:!0,description:"Q&A/Design/Plan/AC sections"}],reasoning_skill:"sp:spur-dev",required_references:[],gates:[],mutation_class:"corpus",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[{tier:"capable-2",trigger:"gate-fail"},{tier:"capable-2",trigger:"auth"},{tier:"capable-2",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"plan",aliases:["dev-plan"],description:"dev-plan: feature intake -> AC generation -> decomposition",artifacts:[{kind:"feature-frontmatter",direction:"input",required:!0},{kind:"task-batch",direction:"output",required:!0}],reasoning_skill:"sp:spur-dev",required_references:[],gates:[{name:"feature-check",timing:"post",min_verdict:"pass"},{name:"batch-create",timing:"post",min_verdict:"pass"}],mutation_class:"corpus",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{min_tier:"capable-2",fallback:[{tier:"capable-3",trigger:"gate-fail"},{tier:"capable-3",trigger:"auth"},{tier:"capable-3",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"implement",aliases:["dev-run"],description:"dev-run --mode implement: code edits in worktree",artifacts:[{kind:"worktree-diff",direction:"output",required:!0},{kind:"task-section",direction:"output",required:!0,identity:"Solution"}],reasoning_skill:"sp:code-implementation",required_references:[],gates:[],mutation_class:"code",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[{tier:"capable-1",trigger:"gate-fail"},{tier:"capable-1",trigger:"timeout"},{tier:"capable-1",trigger:"auth"},{tier:"capable-1",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"test",aliases:["dev-unit","dev-fixall"],description:"dev-unit: generate/extend tests to coverage target",artifacts:[{kind:"test-file",direction:"output",required:!0},{kind:"coverage-report",direction:"output",required:!1}],reasoning_skill:"sp:code-testing",required_references:[],gates:[],mutation_class:"tests",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{fallback:[{tier:"capable-1",trigger:"gate-fail"},{tier:"capable-1",trigger:"auth"},{tier:"capable-1",trigger:"resource-exhaustion"}],min_tier:"standard"},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"verify",aliases:["dev-verify"],description:"dev-verify: SECUA review + requirements traceability",artifacts:[{kind:"worktree-diff",direction:"input",required:!0},{kind:"verdict-artifact",direction:"output",required:!0,identity:"<wbs>-verdict.json"}],reasoning_skill:"sp:code-verification",required_references:[],gates:[{name:"verdict-artifact",timing:"post",min_verdict:"pass"},{name:"strict-core",timing:"post",min_verdict:"pass"}],mutation_class:"verdict",retry:{max_attempts:2,terminal_stop:"escalate"},model_policy:{min_tier:"capable-1",fallback:[{tier:"capable-2",trigger:"auth"},{tier:"capable-2",trigger:"resource-exhaustion"},{tier:"capable-2",trigger:"gate-fail"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"wrap",aliases:["dev-wrap"],description:"dev-wrap: learnings/doc-sync/feature transition",artifacts:[{kind:"learning-entry",direction:"output",required:!0}],reasoning_skill:"sp:spur-dev",required_references:[],gates:[{name:"task-check",timing:"pre",min_verdict:"pass"}],mutation_class:"learnings",retry:{max_attempts:2,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[{tier:"capable-1",trigger:"gate-fail"},{tier:"capable-1",trigger:"auth"},{tier:"capable-1",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"hitl",current_agent_allowed:!0,gate_timing:"both"}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"review",aliases:["dev-review"],description:"dev-review: multi-dimensional code review (coordinator writes the combined Review)",artifacts:[{kind:"review-findings",direction:"output",required:!0,identity:"Review"}],reasoning_skill:"sp:code-verification",required_references:[],gates:[],mutation_class:"verdict",retry:{max_attempts:2,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[{tier:"capable-1",trigger:"gate-fail"},{tier:"capable-1",trigger:"auth"},{tier:"capable-1",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"record",aliases:["dev-record"],description:"record: deterministic Testing write-back from the verdict artifact; bare-Review fallback only",artifacts:[{kind:"verdict-artifact",direction:"input",required:!0,identity:"<wbs>-verdict.json"},{kind:"task-section",direction:"output",required:!0,identity:"Testing"},{kind:"task-section",direction:"output",required:!1,identity:"Review",description:"fallback-only: backfills Review only when the section is bare; never overwrites authored Review"}],reasoning_skill:"inline",required_references:[],gates:[],mutation_class:"corpus",retry:{max_attempts:1,terminal_stop:"block"},model_policy:{min_tier:"cheap",fallback:[]},context_layers:[],observability:[],execution:{kind:"deterministic",current_agent_allowed:!1,executor:"cli"}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"dogfood",aliases:["dev-dogfood"],description:"dev-dogfood: end-to-end driver test",artifacts:[{kind:"dogfood-report",direction:"output",required:!0},{kind:"monitor-ledger",direction:"output",required:!1}],reasoning_skill:"sp:dogfood-testing",required_references:[],gates:[],mutation_class:"driver",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{min_tier:"capable-1",fallback:[{tier:"capable-2",trigger:"auth"},{tier:"capable-2",trigger:"resource-exhaustion"},{tier:"capable-2",trigger:"gate-fail"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"brainstorm",aliases:["dev-brainstorm"],description:"dev-brainstorm: structured ideation",artifacts:[{kind:"brainstorm-outline",direction:"output",required:!0}],reasoning_skill:"sp:brainstorm",required_references:[],gates:[],mutation_class:"corpus",retry:{max_attempts:2,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"changelog",aliases:["dev-changelog"],description:"dev-changelog: generate changelog from git commits",artifacts:[{kind:"changelog-entry",direction:"output",required:!0}],reasoning_skill:"inline",required_references:[],gates:[],mutation_class:"none",retry:{max_attempts:1,terminal_stop:"block"},model_policy:{min_tier:"cheap",fallback:[]},context_layers:[],observability:[],execution:{kind:"deterministic",current_agent_allowed:!1,executor:"cli"}}],CANONICAL_STAGE_BY_KEY=new Map;for(let s2 of REGISTERED_CANONICAL_STAGES){CANONICAL_STAGE_BY_KEY.set(s2.id,s2);for(let a2 of s2.aliases??[])CANONICAL_STAGE_BY_KEY.set(a2,s2)}var CACHEABILITY_CLASSES=["stable-prefix-eligible","volatile"],SENSITIVITY_CLASSES=["public","internal","confidential"],envelopeProvenanceSchema=exports_external.object({owner:exports_external.string().min(1),schema_version:exports_external.string().min(1),source_revision:exports_external.string().nullable().optional(),generated_at:exports_external.string().datetime()}).strict(),envelopeSizeBudgetSchema=exports_external.object({max_bytes:exports_external.number().int().positive()}).strict(),envelopeLayerSchema=exports_external.object({layer:exports_external.enum(CONTEXT_LAYER_NAMES),content:exports_external.string(),size_bytes:exports_external.number().int().nonnegative(),content_hash:exports_external.string().length(64),provenance:envelopeProvenanceSchema,cacheability:exports_external.enum(CACHEABILITY_CLASSES),sensitivity:exports_external.enum(SENSITIVITY_CLASSES).default("internal"),size_budget:envelopeSizeBudgetSchema.optional(),disclosure_handle:exports_external.string().optional()}).strict(),STABLE_LAYER_NAMES=["harness-policy","project-authority","stage-contract","task-state","indexed-evidence"],VOLATILE_LAYER_NAMES=["run-state","tool-observations"];var envelopeSchema=exports_external.object({schema_version:exports_external.string().default("1.0"),layers:exports_external.array(envelopeLayerSchema).min(1),stage_id:exports_external.string().optional(),run_id:exports_external.string().optional(),assembled_at:exports_external.string().datetime(),total_size_bytes:exports_external.number().int().nonnegative()}).strict(),projectSnapshotSchema=exports_external.object({name:exports_external.string(),version:exports_external.string(),task_counts:exports_external.object({backlog:exports_external.number().int().nonnegative(),todo:exports_external.number().int().nonnegative(),wip:exports_external.number().int().nonnegative(),testing:exports_external.number().int().nonnegative(),done:exports_external.number().int().nonnegative(),blocked:exports_external.number().int().nonnegative(),cancelled:exports_external.number().int().nonnegative()}).strict(),feature_counts:exports_external.object({backlog:exports_external.number().int().nonnegative(),active:exports_external.number().int().nonnegative(),verifying:exports_external.number().int().nonnegative(),done:exports_external.number().int().nonnegative(),blocked:exports_external.number().int().nonnegative(),cancelled:exports_external.number().int().nonnegative()}).strict(),active_features:exports_external.array(exports_external.string()),content_hash:exports_external.string().length(64).optional()}).strict(),taskSnapshotSchema=exports_external.object({wbs:exports_external.string().regex(/^\d{4}$/),name:exports_external.string(),status:exports_external.string(),priority:exports_external.string().optional(),feature_id:exports_external.string().optional(),acceptance_criteria:exports_external.string().optional(),locked_qa:exports_external.array(exports_external.string()).optional(),solution:exports_external.string().optional(),content_hash:exports_external.string().length(64).optional()}).strict(),featureSnapshotSchema=exports_external.object({id:exports_external.string(),name:exports_external.string(),status:exports_external.string(),priority:exports_external.string().optional(),scenarios:exports_external.array(exports_external.string()).optional(),content_hash:exports_external.string().length(64).optional()}).strict();var ALL_LAYER_NAMES=[...STABLE_LAYER_NAMES,...VOLATILE_LAYER_NAMES],LAYER_ORDER={};ALL_LAYER_NAMES.forEach((name,idx)=>{LAYER_ORDER[name]=idx});init_dist2();var TASK_CANONICAL_SECTIONS=["Background","Requirements","Acceptance Criteria","Q&A","Design","Plan","Root Cause","Solution","Testing","Review","References","History"],FEATURE_CANONICAL_SECTIONS=["Goal","Scope","Acceptance Criteria","Tasks","Notes","History"],UNIVERSAL_SECTIONS=["History","References","Notes"],HEADING_LEVELS={task:3,feature:2},START_MARKER="<!-- AUTO-GENERATED by spur feature refresh -->",END_MARKER="<!-- END AUTO-GENERATED -->",MARKER_START_RE=/<!--[ \t]*AUTO-GENERATED.*?-->/,MARKER_END_RE=/<!--[ \t]*END[ \t]*AUTO-GENERATED.*?-->/;function findHeadings(body,hashes){let hits=[],prefix=`${hashes} `,inCodeBlock=!1,lineStart=0;for(let i2=0;i2<=body.length;i2++){if(i2!==body.length&&body[i2]!==`
1428
+ `,CLI_MIGRATIONS=[{id:"0000_spur_cli_foundation",sql:CLI_SCHEMA_SQL},{id:"0001_spur_cli_team_inbox",sql:INBOX_MESSAGES_SCHEMA_SQL},{id:"0002_spur_cli_rule_history",sql:RULE_ENGINE_SCHEMA_SQL},{id:"0003_spur_cli_planning",sql:PLANNING_SCHEMA_SQL},{id:"0004_spur_cli_queue_jobs",sql:QUEUE_JOBS_SCHEMA_SQL},{id:"0005_spur_cli_run_pid",sql:RUN_PID_COLUMN_SCHEMA_SQL,addColumnIfMissing:{table:"runs",column:"pid"}},{id:"0006_spur_cli_system_events",sql:SYSTEM_EVENTS_SCHEMA_SQL},{id:"0007_spur_cli_runs_external_key",sql:RUNS_EXTERNAL_KEY_COLUMN_SCHEMA_SQL,addColumnIfMissing:{table:"runs",column:"external_key"}},{id:"0008_spur_cli_system_events_correlation",sql:SYSTEM_EVENTS_CORRELATION_COLUMNS_SCHEMA_SQL,addColumnIfMissing:{table:"system_events",column:"sequence"}},{id:"0009_spur_cli_history_message_run_idx",sql:HISTORY_MESSAGE_RUN_INDEX_SCHEMA_SQL},{id:"0010_spur_cli_coordination_runs",sql:COORDINATION_RUNS_SCHEMA_SQL},{id:"0011_spur_cli_system_events_sequence_idx",sql:SYSTEM_EVENTS_SEQUENCE_INDEX_SCHEMA_SQL},{id:"0012_spur_cli_history_tool_call_args_raw",sql:HISTORY_TOOL_CALL_ARGS_RAW_SCHEMA_SQL,addColumnIfMissing:{table:"history_tool_call",column:"args_raw"}},{id:"0013_spur_cli_history_run_session",sql:HISTORY_RUN_SESSION_SCHEMA_SQL},{id:"0014_spur_cli_system_events_name_occurred_idx",sql:SYSTEM_EVENTS_NAME_OCCURRED_INDEX_SCHEMA_SQL},{id:"0015_spur_cli_history_tool_call_call_id",sql:HISTORY_TOOL_CALL_CALL_ID_SCHEMA_SQL,addColumnIfMissing:{table:"history_tool_call",column:"call_id"}},{id:"0016_spur_cli_history_message_ts_nullable",sql:HISTORY_MESSAGE_TS_NULLABLE_SCHEMA_SQL},{id:"0017_spur_cli_runs_status_completed_to_done",sql:"UPDATE runs SET status = 'done' WHERE status = 'completed'"},{id:"0018_spur_cli_history_message_request_id",sql:HISTORY_MESSAGE_REQUEST_ID_SCHEMA_SQL,addColumnIfMissing:{table:"history_message",column:"request_id"}},{id:"0019_spur_cli_history_etl_tables_drop",sql:HISTORY_ETL_TABLES_DROP_SCHEMA_SQL},{id:"0020_spur_cli_history_board_query_indexes",sql:HISTORY_BOARD_QUERY_INDEXES_SCHEMA_SQL},{id:"0021_spur_cli_history_board_rollups",sql:HISTORY_BOARD_ROLLUPS_SCHEMA_SQL},{id:"0022_spur_cli_history_performance_indexes",sql:HISTORY_PERFORMANCE_INDEXES_SCHEMA_SQL},{id:"0023_spur_cli_history_message_request_id_idx",sql:HISTORY_MESSAGE_REQUEST_ID_INDEX_SCHEMA_SQL},{id:"0024_spur_cli_history_checkpoint_identity",sql:"ALTER TABLE history_import_checkpoint ADD COLUMN source_size INTEGER",addColumnIfMissing:{table:"history_import_checkpoint",column:"source_size"}},{id:"0025_spur_cli_history_checkpoint_identity_mtime",sql:"ALTER TABLE history_import_checkpoint ADD COLUMN source_mtime_ms REAL",addColumnIfMissing:{table:"history_import_checkpoint",column:"source_mtime_ms"}},{id:"0026_spur_cli_history_message_duration_source",sql:"ALTER TABLE history_message ADD COLUMN duration_source TEXT",addColumnIfMissing:{table:"history_message",column:"duration_source"}},{id:"0027_spur_cli_history_refresh_active_unique",sql:HISTORY_REFRESH_ACTIVE_UNIQUE_SCHEMA_SQL},{id:"0028_spur_cli_history_task_session",sql:HISTORY_TASK_SESSION_SCHEMA_SQL},{id:"0029_spur_cli_history_tool_call_indexes",sql:HISTORY_TOOL_CALL_INDEXES_SCHEMA_SQL},{id:"0030_spur_cli_history_board_covering_indexes",sql:HISTORY_BOARD_COVERING_INDEXES_SCHEMA_SQL},{id:"0031_spur_cli_history_board_tool_stats_columns",sql:HISTORY_BOARD_TOOL_STATS_COLUMNS_SCHEMA_SQL},{id:"0032_spur_cli_history_board_skill_5m",sql:HISTORY_BOARD_SKILL_5M_SCHEMA_SQL},{id:"0033_spur_cli_importer_schema_version",sql:`INSERT OR REPLACE INTO "__spur_cli_migrations" (id, applied_at) VALUES ('${IMPORTER_SCHEMA_LEDGER_PREFIX}${HISTORY_IMPORT_SCHEMA_VERSION}', strftime('%s', 'now') * 1000);`},{id:"0034_spur_cli_history_tool_identity",sql:HISTORY_TOOL_IDENTITY_SCHEMA_SQL},{id:"0035_spur_cli_history_measure_vector",sql:HISTORY_MEASURE_VECTOR_SCHEMA_SQL},{id:"0036_spur_cli_history_rollup_watermark",sql:HISTORY_ROLLUP_WATERMARK_SCHEMA_SQL},{id:"0037_spur_cli_history_dimension_marts",sql:HISTORY_DIMENSION_MARTS_SCHEMA_SQL},{id:"0038_spur_cli_retention_compaction_meta",sql:RETENTION_COMPACTION_META_SCHEMA_SQL},{id:"0039_spur_cli_bounded_rollup_derivations",sql:BOUNDED_ROLLUP_DERIVATIONS_SCHEMA_SQL,addColumnIfMissing:{table:"history_board_source_daily",column:"raw_messages"}},{id:"0040_spur_cli_agent_executor_updates",sql:AGENT_EXECUTOR_UPDATES_SCHEMA_SQL},{id:"0041_spur_cli_queue_jobs_deadline_lease_columns",sql:QUEUE_JOBS_DEADLINE_LEASE_COLUMNS_SCHEMA_SQL,addColumnIfMissing:{table:"queue_jobs",column:"timeout_ms"}},{id:"0042_spur_cli_history_model_fallback_index",sql:HISTORY_MESSAGE_MODEL_FALLBACK_INDEX_SCHEMA_SQL},{id:"0043_spur_cli_inbox_messages_request_key",sql:INBOX_MESSAGES_REQUEST_KEY_SCHEMA_SQL,addColumnIfMissing:{table:"inbox_messages",column:"request_key"}},{id:"0044_spur_cli_coordination_runs_receipt_columns",sql:COORDINATION_RUNS_RECEIPT_COLUMNS_SCHEMA_SQL,addColumnIfMissing:{table:"coordination_runs",column:"message_ids_json"}},{id:"0045_spur_cli_project_claims",sql:PROJECT_CLAIMS_SCHEMA_SQL},{id:"0046_spur_cli_project_strategy",sql:PROJECT_STRATEGY_SCHEMA_SQL},{id:"0047_spur_cli_scheduler_custom_active_unique",sql:SCHEDULER_CUSTOM_ACTIVE_UNIQUE_SCHEMA_SQL},{id:"0048_spur_cli_agent_executor_updates_owner_columns",sql:AGENT_EXECUTOR_UPDATES_OWNER_COLUMNS_SCHEMA_SQL,addColumnIfMissing:{table:"agent_executor_updates",column:"owner"}},{id:"0049_spur_cli_runs_terminal_reason",sql:CLI_RUNS_TERMINAL_REASON_SCHEMA_SQL,addColumnIfMissing:{table:"runs",column:"terminal_reason"}}];async function allMigrationsJournaled(adapter,migrations){if(migrations.length===0)return!0;if(!await tableExists(adapter,"__spur_cli_migrations"))return!1;let placeholders=migrations.map(()=>"?").join(", ");if(((await adapter.queryFirst(`SELECT COUNT(*) AS n FROM "__spur_cli_migrations" WHERE id IN (${placeholders})`,...migrations.map((m)=>m.id)))?.n??0)!==migrations.length)return!1;if(migrations.some((m)=>m.id==="0033_spur_cli_importer_schema_version")){if(!await adapter.queryFirst('SELECT id FROM "__spur_cli_migrations" WHERE id = ?',IMPORTER_SCHEMA_LEDGER_PREFIX+HISTORY_IMPORT_SCHEMA_VERSION))return!1}return!0}async function applyCliMigrations(adapter,migrations=CLI_MIGRATIONS){if(await allMigrationsJournaled(adapter,migrations))return 0;await adapter.exec('CREATE TABLE IF NOT EXISTS "__spur_cli_migrations" (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)');let applied=0;for(let migration of migrations){if(await adapter.queryFirst('SELECT id FROM "__spur_cli_migrations" WHERE id = ?',migration.id)!=null)continue;if(migration.id==="0009_spur_cli_history_message_run_idx"&&!await tableExists(adapter,"history_message")){for(let statement of splitSqlStatements(HISTORY_IMPORT_SCHEMA_SQL))await adapter.exec(statement);let versionLedgerId=IMPORTER_SCHEMA_LEDGER_PREFIX+HISTORY_IMPORT_SCHEMA_VERSION;await adapter.run('INSERT OR REPLACE INTO "__spur_cli_migrations" (id, applied_at) VALUES (?, ?)',[versionLedgerId,Date.now()])}if((migration.id==="0024_spur_cli_history_checkpoint_identity"||migration.id==="0025_spur_cli_history_checkpoint_identity_mtime")&&!await tableExists(adapter,"history_import_checkpoint")){await adapter.run('INSERT INTO "__spur_cli_migrations" (id, applied_at) VALUES (?, ?)',[migration.id,Date.now()]);continue}if(migration.id==="0034_spur_cli_history_tool_identity"&&await tableExists(adapter,"history_tool_call")){if(!await columnExists(adapter,"history_tool_call","effective_tool_name"))await adapter.exec("ALTER TABLE history_tool_call ADD COLUMN effective_tool_name TEXT NOT NULL DEFAULT 'unknown'");if(!await columnExists(adapter,"history_tool_call","tool_name_alias"))await adapter.exec("ALTER TABLE history_tool_call ADD COLUMN tool_name_alias TEXT NOT NULL DEFAULT 'unknown'")}let addColumnGuard=migration.addColumnIfMissing,shouldApplySql=addColumnGuard===void 0||!await columnExists(adapter,addColumnGuard.table,addColumnGuard.column),tsNullableSkip=migration.id==="0016_spur_cli_history_message_ts_nullable"&&(!await tableExists(adapter,"history_message")||!await columnNotNull(adapter,"history_message","ts")),sequenceIndexSkip=migration.id==="0011_spur_cli_system_events_sequence_idx"&&!await tableExists(adapter,"system_events"),argsRawSkip=migration.id==="0012_spur_cli_history_tool_call_args_raw"&&!await tableExists(adapter,"history_tool_call"),callIdSkip=migration.id==="0015_spur_cli_history_tool_call_call_id"&&!await tableExists(adapter,"history_tool_call"),nameOccurredIndexSkip=migration.id==="0014_spur_cli_system_events_name_occurred_idx"&&!await tableExists(adapter,"system_events"),historyBoardQueryIndexesSkip=migration.id==="0020_spur_cli_history_board_query_indexes"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","seq")||!await columnExists(adapter,"history_message","duration_ms")||!await columnExists(adapter,"history_message","role")||!await columnExists(adapter,"history_message","input_tokens")||!await columnExists(adapter,"history_message","cache_read_tokens")),historyPerformanceIndexesSkip=migration.id==="0022_spur_cli_history_performance_indexes"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","ts")||!await columnExists(adapter,"history_message","model")||!await tableExists(adapter,"history_tool_call")),historyToolCallIndexesSkip=migration.id==="0029_spur_cli_history_tool_call_indexes"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","ts")||!await tableExists(adapter,"history_tool_call")),historyBoardCoveringIndexesSkip=migration.id==="0030_spur_cli_history_board_covering_indexes"&&(!await tableExists(adapter,"history_daily_stats")||!await tableExists(adapter,"history_board_tool_5m")||!await tableExists(adapter,"history_board_message_5m")||!await tableExists(adapter,"history_board_session_stats")||!await tableExists(adapter,"history_board_source_daily")||!await tableExists(adapter,"history_tool_call")||!await tableExists(adapter,"history_task_session")),runsStatusDoneSkip=migration.id==="0017_spur_cli_runs_status_completed_to_done"&&(!await tableExists(adapter,"runs")||!await columnExists(adapter,"runs","status")),historyBoardToolStatsColumnsSkip=migration.id==="0031_spur_cli_history_board_tool_stats_columns"&&(!await tableExists(adapter,"history_board_tool_stats")||await columnExists(adapter,"history_board_tool_stats","fresh_input_tokens")),queueJobsActiveIndexSkip=migration.id==="0027_spur_cli_history_refresh_active_unique"&&!await tableExists(adapter,"queue_jobs"),schedulerCustomActiveIndexSkip=migration.id==="0047_spur_cli_scheduler_custom_active_unique"&&!await tableExists(adapter,"queue_jobs"),queueJobsDeadlineLeaseSkip=migration.id==="0041_spur_cli_queue_jobs_deadline_lease_columns"&&!await tableExists(adapter,"queue_jobs"),runsTerminalReasonSkip=migration.id==="0049_spur_cli_runs_terminal_reason"&&!await tableExists(adapter,"runs"),inboxRequestKeySkip=migration.id==="0043_spur_cli_inbox_messages_request_key"&&!await tableExists(adapter,"inbox_messages"),coordinationReceiptColumnsSkip=migration.id==="0044_spur_cli_coordination_runs_receipt_columns"&&!await tableExists(adapter,"coordination_runs"),historyToolIdentitySkip=migration.id==="0034_spur_cli_history_tool_identity"&&!await tableExists(adapter,"history_tool_call"),historyMeasureVectorSkip=migration.id==="0035_spur_cli_history_measure_vector"&&(!await tableExists(adapter,"history_board_message_5m")||await columnExists(adapter,"history_board_message_5m","cache_write_tokens")),historyRollupWatermarkSkip=migration.id==="0036_spur_cli_history_rollup_watermark"&&(await tableExists(adapter,"history_board_rollup_watermark")||!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","imported_at")),boundedRollupDerivationsSkip=migration.id==="0039_spur_cli_bounded_rollup_derivations"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","source_file")||!await tableExists(adapter,"history_board_source_daily")),historyModelFallbackIndexSkip=migration.id==="0042_spur_cli_history_model_fallback_index"&&(!await tableExists(adapter,"history_message")||!await columnExists(adapter,"history_message","model"));if(shouldApplySql&&!sequenceIndexSkip&&!argsRawSkip&&!runsStatusDoneSkip&&!nameOccurredIndexSkip&&!historyBoardQueryIndexesSkip&&!historyPerformanceIndexesSkip&&!historyToolCallIndexesSkip&&!historyBoardCoveringIndexesSkip&&!historyBoardToolStatsColumnsSkip&&!callIdSkip&&!tsNullableSkip&&!queueJobsActiveIndexSkip&&!schedulerCustomActiveIndexSkip&&!queueJobsDeadlineLeaseSkip&&!runsTerminalReasonSkip&&!inboxRequestKeySkip&&!coordinationReceiptColumnsSkip&&!historyToolIdentitySkip&&!historyMeasureVectorSkip&&!historyRollupWatermarkSkip&&!boundedRollupDerivationsSkip&&!historyModelFallbackIndexSkip)for(let statement of splitSqlStatements(migration.sql))await adapter.exec(statement);if(historyToolIdentitySkip&&!await tableExists(adapter,"history_tool_alias_map"))await adapter.exec("CREATE TABLE IF NOT EXISTS history_tool_alias_map (source TEXT NOT NULL, effective_tool_name TEXT NOT NULL, alias TEXT NOT NULL, PRIMARY KEY (source, effective_tool_name));");await adapter.run('INSERT INTO "__spur_cli_migrations" (id, applied_at) VALUES (?, ?)',migration.id,Date.now()),applied+=1}if(migrations.some((m)=>m.id==="0033_spur_cli_importer_schema_version")){let currentVersionLedgerId=IMPORTER_SCHEMA_LEDGER_PREFIX+HISTORY_IMPORT_SCHEMA_VERSION;if(!await adapter.queryFirst('SELECT id FROM "__spur_cli_migrations" WHERE id = ?',currentVersionLedgerId)){for(let statement of splitSqlStatements(HISTORY_IMPORT_SCHEMA_SQL))if(statement.startsWith("CREATE TABLE"))await adapter.exec(statement);await adapter.run('INSERT OR REPLACE INTO "__spur_cli_migrations" (id, applied_at) VALUES (?, ?)',[currentVersionLedgerId,Date.now()]),applied+=1}}return applied}async function columnExists(adapter,table3,column2){return(await adapter.queryAll(`PRAGMA table_info("${table3}")`)).some((row)=>row.name===column2)}async function columnNotNull(adapter,table3,column2){return(await adapter.queryAll(`PRAGMA table_info("${table3}")`)).some((row)=>row.name===column2&&row.notnull===1)}async function tableExists(adapter,table3){return await adapter.queryFirst("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?",table3)!=null}function splitSqlStatements(sql4){return sql4.split(";").map((statement)=>statement.trim()).filter(Boolean)}var SQLITE_BUSY_TIMEOUT_MS=30000;async function createMigratedDb(options){let{createDbAdapter:createDbAdapter3}=await Promise.resolve().then(() => (init_dist4(),exports_dist)),adapter=await createDbAdapter3({driver:"bun-sqlite",url:options.url});return await adapter.exec(`PRAGMA busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS}`),await applyCliMigrations(adapter),adapter}init_zod();init_zod();var STAGE_REGISTRY_SCHEMA_VERSION={major:1,minor:3},stageSchemaVersionSchema=exports_external.object({major:exports_external.number().int().nonnegative(),minor:exports_external.number().int().nonnegative()}).strict();var MUTATION_CLASSES=["none","corpus","code","tests","verdict","learnings","driver","irreversible"];var inlineExecutionSchema=exports_external.object({kind:exports_external.literal("inline"),current_agent_allowed:exports_external.literal(!0),may_reuse_captured_layers:exports_external.boolean().optional()}).strict(),subprocessExecutionSchema=exports_external.object({kind:exports_external.literal("subprocess"),current_agent_allowed:exports_external.literal(!1),via:exports_external.literal("spur-agent-run")}).strict(),deterministicExecutionSchema=exports_external.object({kind:exports_external.literal("deterministic"),current_agent_allowed:exports_external.literal(!1),executor:exports_external.enum(["cli","script"])}).strict(),hitlExecutionSchema=exports_external.object({kind:exports_external.literal("hitl"),current_agent_allowed:exports_external.literal(!0),gate_timing:exports_external.enum(["pre","post","both"])}).strict(),irreversibleExecutionSchema=exports_external.object({kind:exports_external.literal("irreversible"),requires_operator_intent:exports_external.literal(!0),current_agent_allowed:exports_external.boolean(),rollback_disclaimer:exports_external.string().min(1)}).strict(),executionKindSchema=exports_external.discriminatedUnion("kind",[inlineExecutionSchema,subprocessExecutionSchema,deterministicExecutionSchema,hitlExecutionSchema,irreversibleExecutionSchema]),ARTIFACT_DIRECTIONS=["input","output"],stageArtifactSchema=exports_external.object({kind:exports_external.string().min(1),direction:exports_external.enum(ARTIFACT_DIRECTIONS),identity:exports_external.string().optional(),description:exports_external.string().optional(),required:exports_external.boolean().optional().default(!0)}).strict(),stageGateSchema=exports_external.object({name:exports_external.string().min(1),timing:exports_external.enum(["pre","post","transition"]),min_verdict:exports_external.enum(["pass","partial","fail"]).optional(),description:exports_external.string().optional()}).strict(),stageRetryPolicySchema=exports_external.object({max_attempts:exports_external.number().int().min(1),terminal_stop:exports_external.enum(["block","escalate","fail"]),timeout_seconds:exports_external.number().int().positive().optional()}).strict(),CAPABILITY_TIERS=["cheap","standard","capable-1","capable-2","capable-3"],LEGACY_CAPABLE_ALIAS="capable";function normalizeCapabilityTier(value){return value===LEGACY_CAPABLE_ALIAS?"capable-1":value}var capabilityTierSchema=exports_external.preprocess(normalizeCapabilityTier,exports_external.enum(CAPABILITY_TIERS)),objectiveEscalationTriggerSchema=exports_external.enum(["gate-fail","timeout","insufficient-evidence","retry-exhausted","resource-exhaustion","auth"]),stageModelPolicySchema=exports_external.object({min_tier:capabilityTierSchema,fallback:exports_external.array(exports_external.object({tier:capabilityTierSchema,trigger:objectiveEscalationTriggerSchema}).strict()),override_key:exports_external.string().optional()}).strict();var CONTEXT_LAYER_NAMES=["harness-policy","project-authority","stage-contract","task-state","indexed-evidence","run-state","tool-observations"],stageContextLayerSchema=exports_external.object({layer:exports_external.enum(CONTEXT_LAYER_NAMES),required:exports_external.literal(!0)}).strict(),stageEventSchema=exports_external.object({name:exports_external.string().min(1),description:exports_external.string().optional()}).strict(),STAGE_ID_PATTERN=/^[a-z][a-z0-9-]*$/,stageRecordSchema=exports_external.object({schema_version:stageSchemaVersionSchema,id:exports_external.string().regex(STAGE_ID_PATTERN,{message:"stage id must be lowercase kebab-case"}),aliases:exports_external.array(exports_external.string().min(1)).optional().default([]),description:exports_external.string().min(1),artifacts:exports_external.array(stageArtifactSchema).min(1),reasoning_skill:exports_external.string().min(1),required_references:exports_external.array(exports_external.string().min(1)).optional().default([]),gates:exports_external.array(stageGateSchema).optional().default([]),mutation_class:exports_external.enum(MUTATION_CLASSES),retry:stageRetryPolicySchema,model_policy:stageModelPolicySchema,context_layers:exports_external.array(stageContextLayerSchema).optional().default([]),observability:exports_external.array(stageEventSchema).optional().default([]),execution:executionKindSchema}).strict();var REGISTERED_CANONICAL_STAGES=[{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"refine",aliases:["dev-refine"],description:"dev-refine: Q&A refinement, section filling, AC tightening",artifacts:[{kind:"task-section",direction:"input",required:!0,description:"Background/Requirements sections"},{kind:"task-section",direction:"output",required:!0,description:"Q&A/Design/Plan/AC sections"}],reasoning_skill:"sp:spur-dev",required_references:[],gates:[],mutation_class:"corpus",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[{tier:"capable-2",trigger:"gate-fail"},{tier:"capable-2",trigger:"auth"},{tier:"capable-2",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"plan",aliases:["dev-plan"],description:"dev-plan: feature intake -> AC generation -> decomposition",artifacts:[{kind:"feature-frontmatter",direction:"input",required:!0},{kind:"task-batch",direction:"output",required:!0}],reasoning_skill:"sp:spur-dev",required_references:[],gates:[{name:"feature-check",timing:"post",min_verdict:"pass"},{name:"batch-create",timing:"post",min_verdict:"pass"}],mutation_class:"corpus",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{min_tier:"capable-2",fallback:[{tier:"capable-3",trigger:"gate-fail"},{tier:"capable-3",trigger:"auth"},{tier:"capable-3",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"implement",aliases:["dev-run"],description:"dev-run --mode implement: code edits in worktree",artifacts:[{kind:"worktree-diff",direction:"output",required:!0},{kind:"task-section",direction:"output",required:!0,identity:"Solution"}],reasoning_skill:"sp:code-implementation",required_references:[],gates:[],mutation_class:"code",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[{tier:"capable-1",trigger:"gate-fail"},{tier:"capable-1",trigger:"timeout"},{tier:"capable-1",trigger:"auth"},{tier:"capable-1",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"test",aliases:["dev-unit","dev-fixall"],description:"dev-unit: generate/extend tests to coverage target",artifacts:[{kind:"test-file",direction:"output",required:!0},{kind:"coverage-report",direction:"output",required:!1}],reasoning_skill:"sp:code-testing",required_references:[],gates:[],mutation_class:"tests",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{fallback:[{tier:"capable-1",trigger:"gate-fail"},{tier:"capable-1",trigger:"auth"},{tier:"capable-1",trigger:"resource-exhaustion"}],min_tier:"standard"},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"verify",aliases:["dev-verify"],description:"dev-verify: SECUA review + requirements traceability",artifacts:[{kind:"worktree-diff",direction:"input",required:!0},{kind:"verdict-artifact",direction:"output",required:!0,identity:"<wbs>-verdict.json"}],reasoning_skill:"sp:code-verification",required_references:[],gates:[{name:"verdict-artifact",timing:"post",min_verdict:"pass"},{name:"strict-core",timing:"post",min_verdict:"pass"}],mutation_class:"verdict",retry:{max_attempts:2,terminal_stop:"escalate"},model_policy:{min_tier:"capable-1",fallback:[{tier:"capable-2",trigger:"auth"},{tier:"capable-2",trigger:"resource-exhaustion"},{tier:"capable-2",trigger:"gate-fail"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"wrap",aliases:["dev-wrap"],description:"dev-wrap: learnings/doc-sync/feature transition",artifacts:[{kind:"learning-entry",direction:"output",required:!0}],reasoning_skill:"sp:spur-dev",required_references:[],gates:[{name:"task-check",timing:"pre",min_verdict:"pass"}],mutation_class:"learnings",retry:{max_attempts:2,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[{tier:"capable-1",trigger:"gate-fail"},{tier:"capable-1",trigger:"auth"},{tier:"capable-1",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"hitl",current_agent_allowed:!0,gate_timing:"both"}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"review",aliases:["dev-review"],description:"dev-review: multi-dimensional code review (coordinator writes the combined Review)",artifacts:[{kind:"review-findings",direction:"output",required:!0,identity:"Review"}],reasoning_skill:"sp:code-verification",required_references:[],gates:[],mutation_class:"verdict",retry:{max_attempts:2,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[{tier:"capable-1",trigger:"gate-fail"},{tier:"capable-1",trigger:"auth"},{tier:"capable-1",trigger:"resource-exhaustion"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"record",aliases:["dev-record"],description:"record: deterministic Testing write-back from the verdict artifact; bare-Review fallback only",artifacts:[{kind:"verdict-artifact",direction:"input",required:!0,identity:"<wbs>-verdict.json"},{kind:"task-section",direction:"output",required:!0,identity:"Testing"},{kind:"task-section",direction:"output",required:!1,identity:"Review",description:"fallback-only: backfills Review only when the section is bare; never overwrites authored Review"}],reasoning_skill:"inline",required_references:[],gates:[],mutation_class:"corpus",retry:{max_attempts:1,terminal_stop:"block"},model_policy:{min_tier:"cheap",fallback:[]},context_layers:[],observability:[],execution:{kind:"deterministic",current_agent_allowed:!1,executor:"cli"}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"dogfood",aliases:["dev-dogfood"],description:"dev-dogfood: end-to-end driver test",artifacts:[{kind:"dogfood-report",direction:"output",required:!0},{kind:"monitor-ledger",direction:"output",required:!1}],reasoning_skill:"sp:dogfood-testing",required_references:[],gates:[],mutation_class:"driver",retry:{max_attempts:3,terminal_stop:"block"},model_policy:{min_tier:"capable-1",fallback:[{tier:"capable-2",trigger:"auth"},{tier:"capable-2",trigger:"resource-exhaustion"},{tier:"capable-2",trigger:"gate-fail"}]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"brainstorm",aliases:["dev-brainstorm"],description:"dev-brainstorm: structured ideation",artifacts:[{kind:"brainstorm-outline",direction:"output",required:!0}],reasoning_skill:"sp:brainstorm",required_references:[],gates:[],mutation_class:"corpus",retry:{max_attempts:2,terminal_stop:"block"},model_policy:{min_tier:"standard",fallback:[]},context_layers:[],observability:[],execution:{kind:"inline",current_agent_allowed:!0}},{schema_version:STAGE_REGISTRY_SCHEMA_VERSION,id:"changelog",aliases:["dev-changelog"],description:"dev-changelog: generate changelog from git commits",artifacts:[{kind:"changelog-entry",direction:"output",required:!0}],reasoning_skill:"inline",required_references:[],gates:[],mutation_class:"none",retry:{max_attempts:1,terminal_stop:"block"},model_policy:{min_tier:"cheap",fallback:[]},context_layers:[],observability:[],execution:{kind:"deterministic",current_agent_allowed:!1,executor:"cli"}}],CANONICAL_STAGE_BY_KEY=new Map;for(let s2 of REGISTERED_CANONICAL_STAGES){CANONICAL_STAGE_BY_KEY.set(s2.id,s2);for(let a2 of s2.aliases??[])CANONICAL_STAGE_BY_KEY.set(a2,s2)}var CACHEABILITY_CLASSES=["stable-prefix-eligible","volatile"],SENSITIVITY_CLASSES=["public","internal","confidential"],envelopeProvenanceSchema=exports_external.object({owner:exports_external.string().min(1),schema_version:exports_external.string().min(1),source_revision:exports_external.string().nullable().optional(),generated_at:exports_external.string().datetime()}).strict(),envelopeSizeBudgetSchema=exports_external.object({max_bytes:exports_external.number().int().positive()}).strict(),envelopeLayerSchema=exports_external.object({layer:exports_external.enum(CONTEXT_LAYER_NAMES),content:exports_external.string(),size_bytes:exports_external.number().int().nonnegative(),content_hash:exports_external.string().length(64),provenance:envelopeProvenanceSchema,cacheability:exports_external.enum(CACHEABILITY_CLASSES),sensitivity:exports_external.enum(SENSITIVITY_CLASSES).default("internal"),size_budget:envelopeSizeBudgetSchema.optional(),disclosure_handle:exports_external.string().optional()}).strict(),STABLE_LAYER_NAMES=["harness-policy","project-authority","stage-contract","task-state","indexed-evidence"],VOLATILE_LAYER_NAMES=["run-state","tool-observations"];var envelopeSchema=exports_external.object({schema_version:exports_external.string().default("1.0"),layers:exports_external.array(envelopeLayerSchema).min(1),stage_id:exports_external.string().optional(),run_id:exports_external.string().optional(),assembled_at:exports_external.string().datetime(),total_size_bytes:exports_external.number().int().nonnegative()}).strict(),projectSnapshotSchema=exports_external.object({name:exports_external.string(),version:exports_external.string(),task_counts:exports_external.object({backlog:exports_external.number().int().nonnegative(),todo:exports_external.number().int().nonnegative(),wip:exports_external.number().int().nonnegative(),testing:exports_external.number().int().nonnegative(),done:exports_external.number().int().nonnegative(),blocked:exports_external.number().int().nonnegative(),cancelled:exports_external.number().int().nonnegative()}).strict(),feature_counts:exports_external.object({backlog:exports_external.number().int().nonnegative(),active:exports_external.number().int().nonnegative(),verifying:exports_external.number().int().nonnegative(),done:exports_external.number().int().nonnegative(),blocked:exports_external.number().int().nonnegative(),cancelled:exports_external.number().int().nonnegative()}).strict(),active_features:exports_external.array(exports_external.string()),content_hash:exports_external.string().length(64).optional()}).strict(),taskSnapshotSchema=exports_external.object({wbs:exports_external.string().regex(/^\d{4}$/),name:exports_external.string(),status:exports_external.string(),priority:exports_external.string().optional(),feature_id:exports_external.string().optional(),acceptance_criteria:exports_external.string().optional(),locked_qa:exports_external.array(exports_external.string()).optional(),solution:exports_external.string().optional(),content_hash:exports_external.string().length(64).optional()}).strict(),featureSnapshotSchema=exports_external.object({id:exports_external.string(),name:exports_external.string(),status:exports_external.string(),priority:exports_external.string().optional(),scenarios:exports_external.array(exports_external.string()).optional(),content_hash:exports_external.string().length(64).optional()}).strict();var ALL_LAYER_NAMES=[...STABLE_LAYER_NAMES,...VOLATILE_LAYER_NAMES],LAYER_ORDER={};ALL_LAYER_NAMES.forEach((name,idx)=>{LAYER_ORDER[name]=idx});init_dist2();var TASK_CANONICAL_SECTIONS=["Background","Requirements","Acceptance Criteria","Q&A","Design","Plan","Root Cause","Solution","Testing","Review","References","History"],FEATURE_CANONICAL_SECTIONS=["Goal","Scope","Acceptance Criteria","Tasks","Notes","History"],UNIVERSAL_SECTIONS=["History","References","Notes"],HEADING_LEVELS={task:3,feature:2},START_MARKER="<!-- AUTO-GENERATED by spur feature refresh -->",END_MARKER="<!-- END AUTO-GENERATED -->",MARKER_START_RE=/<!--[ \t]*AUTO-GENERATED.*?-->/,MARKER_END_RE=/<!--[ \t]*END[ \t]*AUTO-GENERATED.*?-->/;function findHeadings(body,hashes){let hits=[],prefix=`${hashes} `,inCodeBlock=!1,lineStart=0;for(let i2=0;i2<=body.length;i2++){if(i2!==body.length&&body[i2]!==`
1425
1429
  `)continue;let line=body.slice(lineStart,i2);if(line.startsWith("```"))inCodeBlock=!inCodeBlock;else if(!inCodeBlock&&line.startsWith(prefix)){let name=line.slice(prefix.length).trim();hits.push({index:lineStart,headingLine:line,name})}lineStart=i2+1}return hits}function normalizeYamlScalars(data){let out={};for(let[key,value]of Object.entries(data))if(value instanceof Date)out[key]=value.toISOString();else if(value!==null&&typeof value==="object"&&!Array.isArray(value))out[key]=normalizeYamlScalars(value);else out[key]=value;return out}class MarkdownDocument{_domain;_frontmatterBlock;_frontmatter;_preamble;_sections;_demotedHeadings=[];_duplicateSectionNames=[];constructor(domain2,frontmatterBlock,frontmatter,preamble,sections){this._domain=domain2,this._frontmatterBlock=frontmatterBlock,this._frontmatter=frontmatter,this._preamble=preamble,this._sections=sections}static parse(content,domain2){let level=HEADING_LEVELS[domain2],hashes="#".repeat(level),frontmatterBlock="",frontmatter=null,body=content,fmMatch=/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(content);if(fmMatch&&fmMatch.index===0){let raw=fmMatch[1]??"",data={};try{let parsed=$parse(raw);if(parsed!==null&&typeof parsed==="object"&&!Array.isArray(parsed))data=normalizeYamlScalars(parsed)}catch{}frontmatter={raw,data},frontmatterBlock=fmMatch[0],body=content.slice(fmMatch[0].length)}let hits=findHeadings(body,hashes),first=hits[0],preamble=first!==void 0?body.slice(0,first.index):body,allSections=hits.map((hit,idx)=>{let next=hits[idx+1],end=next!==void 0?next.index:body.length;return{name:hit.name,headingLine:hit.headingLine,originalText:body.slice(hit.index,end),modifiedText:null}}),seen=new Set,sections=[],duplicateNames=[];for(let s2 of allSections)if(seen.has(s2.name))duplicateNames.push(s2.name);else seen.add(s2.name),sections.push(s2);let doc2=new MarkdownDocument(domain2,frontmatterBlock,frontmatter,preamble,sections);return doc2._duplicateSectionNames.push(...duplicateNames),doc2}get domain(){return this._domain}replacePreamble(newBody){this._preamble=newBody}get frontmatter(){return this._frontmatter}get frontmatterRaw(){return this._frontmatter?.raw??null}get frontmatterData(){return this._frontmatter?.data??null}get bodyWithoutFrontmatter(){let result=this._preamble;for(let section of this._sections)result+=section.modifiedText??section.originalText;return result}get sectionNames(){return this._sections.map((s2)=>s2.name)}get demotedHeadings(){return this._demotedHeadings}get duplicateSectionNames(){return this._duplicateSectionNames}get canonicalSections(){let base2=this._domain==="task"?TASK_CANONICAL_SECTIONS:FEATURE_CANONICAL_SECTIONS,extra=UNIVERSAL_SECTIONS.filter((s2)=>!base2.includes(s2));return[...base2,...extra]}validateSectionName(name){if(!this.canonicalSections.includes(name))throw Error(`Unknown section "${name}" for domain "${this._domain}". Canonical sections: ${this.canonicalSections.join(", ")}.`)}findSection(name){return this._sections.find((s2)=>s2.name===name)}hasSection(name){return this.findSection(name)!==void 0}getSection(name){this.validateSectionName(name);let section=this.findSection(name);if(section===void 0)return null;let text3=section.modifiedText??section.originalText,newlineIdx=text3.indexOf(`
1426
1430
  `);return newlineIdx===-1?"":text3.slice(newlineIdx+1)}replaceSection(name,body){this.validateSectionName(name);let cleaned=this.stripSameLevelHeadings(body),section=this.findSection(name);if(section!==void 0){let trimmed=cleaned.trim();section.modifiedText=trimmed.length>0?`${section.headingLine}
1427
1431
 
@@ -1455,6 +1459,10 @@ ${fieldLine}
1455
1459
  `);this._frontmatter={raw,data:{...this._frontmatter.data,[key]:values}};let rawStart=this._frontmatterBlock.indexOf(oldRaw);this._frontmatterBlock=rawStart===-1?`---
1456
1460
  ${raw}
1457
1461
  ---
1458
- `:this._frontmatterBlock.slice(0,rawStart)+raw+this._frontmatterBlock.slice(rawStart+oldRaw.length)}serialize(){let result=this._frontmatterBlock;result+=this._preamble;for(let section of this._sections)result+=section.modifiedText??section.originalText;return result}}function escapeYamlArrayElement(value){return`"${value.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function escapeYamlValue(value){if(value.startsWith('"')&&value.endsWith('"'))return value;if(/[:{}[\],&*?|>!%@`#"'\\\n\r]/.test(value))return`"${value.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`;if(/^(null|true|false|yes|no|on|off)$/i.test(value))return`"${value}"`;if(/^\d/.test(value)&&!/^\d{4}-\d{2}-\d{2}/.test(value))return`"${value}"`;return value}init_zod();var TASK_STATUSES=["backlog","todo","wip","testing","blocked","done","cancelled"],FEATURE_STATUSES=["backlog","active","verifying","blocked","done","cancelled"];var PRIORITIES=["P0","P1","P2","P3"],PROFILES=["simple","standard","complex","research","refine","plan","unit","review","docs"],TASK_TYPES=["task","issue","review","meta","brainstorm"],TASK_VARIANTS=["standard","feature-impl","issue","review","meta","brainstorm"];var FEATURE_ID_PATTERN=/^[A-Z][1-9]*$/;var TASK_STATUS_ALIASES={completed:"done",complete:"done","in-progress":"wip","in progress":"wip",in_progress:"wip",dropped:"cancelled",cancel:"cancelled",canceled:"cancelled",new:"backlog",pending:"backlog",blocked:"blocked",wip:"wip",testing:"testing",done:"done",cancelled:"cancelled",backlog:"backlog",todo:"todo"};function normalizeTaskStatus(raw){let key=raw.trim().toLowerCase(),resolved=TASK_STATUS_ALIASES[key];if(resolved===void 0)throw Error(`Unknown task status: ${JSON.stringify(raw)} (allowed: ${TASK_STATUSES.join(", ")})`);return resolved}var isoDateString=exports_external.string().min(1).refine((value)=>!Number.isNaN(Date.parse(value)),{message:"must be an ISO 8601 timestamp"}),featureId=exports_external.string().regex(FEATURE_ID_PATTERN,{message:"feature id must match ^[A-Z][1-9]*$ (DD-14)"}).nullable().optional(),wbsString=exports_external.string().regex(/^\d{4}$/,{message:"parent_wbs must be a 4-digit WBS string"}).nullable().optional(),taskFrontmatterSchema=exports_external.object({schema_version:exports_external.literal(1),name:exports_external.string().min(1),description:exports_external.string().optional(),status:exports_external.preprocess((val)=>{if(typeof val==="string")try{return normalizeTaskStatus(val)}catch{}return val},exports_external.enum(TASK_STATUSES)),type:exports_external.enum(TASK_TYPES).optional().default("task"),template:exports_external.enum(TASK_VARIANTS).optional(),profile:exports_external.enum(PROFILES).optional(),feature_id:featureId,parent_wbs:wbsString,priority:exports_external.enum(PRIORITIES).optional(),tags:exports_external.array(exports_external.string()).optional(),dependencies:exports_external.array(exports_external.string()).optional(),ac_numbering:exports_external.literal("task-local").optional(),ac_altitude:exports_external.enum(["graduating","task-local"]).optional(),done_forced:exports_external.preprocess((v)=>typeof v==="string"?v==="true":v,exports_external.boolean().optional()),done_reason:exports_external.string().optional(),feature_link_declined:exports_external.preprocess((v)=>typeof v==="string"?v==="true":v,exports_external.boolean().optional()),estimate_hours:exports_external.preprocess((v)=>typeof v==="string"&&v.trim()!==""?Number(v):v,exports_external.number().positive().optional()),created_at:isoDateString,updated_at:isoDateString}),featureFrontmatterSchema=exports_external.object({schema_version:exports_external.literal(1),id:exports_external.string().regex(FEATURE_ID_PATTERN,{message:"feature id must match ^[A-Z][1-9]*$ (DD-14)"}),name:exports_external.string().min(1),status:exports_external.enum(FEATURE_STATUSES),priority:exports_external.enum(PRIORITIES).optional(),tags:exports_external.array(exports_external.string()).optional(),created_at:isoDateString,updated_at:isoDateString});var taskBatchItemSchema=exports_external.object({name:exports_external.string().min(1,"name is required"),background:exports_external.string().optional(),requirements:exports_external.string().optional(),design:exports_external.string().optional(),plan:exports_external.string().optional(),acceptance_criteria:exports_external.string().optional(),feature_id:featureId,parent_wbs:wbsString,priority:exports_external.enum(PRIORITIES).optional(),tags:exports_external.array(exports_external.string()).optional(),template:exports_external.enum(TASK_VARIANTS).optional(),estimate_hours:exports_external.number().positive().optional()}).strict(),taskBatchSchema=exports_external.array(taskBatchItemSchema).min(1,"batch must contain at least one task");init_dist2();init_zod();var sectionNameSchema=exports_external.enum(TASK_CANONICAL_SECTIONS),matrixEntrySchema=exports_external.object({required:exports_external.array(sectionNameSchema).optional(),optional:exports_external.array(sectionNameSchema).optional(),forbidden:exports_external.array(sectionNameSchema).optional(),gate:exports_external.boolean().optional()}).strict(),matrixStatusSchema=exports_external.enum(["backlog","todo","wip","testing","blocked","done","cancelled"]),sectionMatrixSchema=exports_external.object({variants:exports_external.record(exports_external.string(),exports_external.partialRecord(matrixStatusSchema,matrixEntrySchema))}).strict();var CANONICAL_INDEX=new Map(TASK_CANONICAL_SECTIONS.map((s2,i2)=>[s2,i2]));function parseWorkflowInventory(json2){if(typeof json2!=="object"||json2===null)return{ok:!1,error:"workflow inventory: projection is not an object"};let obj=json2,name=typeof obj.name==="string"?obj.name:"",kind=typeof obj.kind==="string"?obj.kind:"",format2=typeof obj.format==="string"?obj.format:"",version3=typeof obj.version==="string"||typeof obj.version==="number"?String(obj.version):"",definitionDigest=typeof obj.definitionDigest==="string"?obj.definitionDigest:"",source;if(obj.source!==void 0){if(typeof obj.source!=="object"||obj.source===null)return{ok:!1,error:"workflow inventory: invalid definition source"};let value=obj.source;if(typeof value.path!=="string"||value.path===""||typeof value.layer!=="string"||!["project","registered","shared"].includes(value.layer))return{ok:!1,error:"workflow inventory: invalid definition source path/layer"};source={path:value.path,layer:value.layer}}if(name==="")return{ok:!1,error:"workflow inventory: missing name"};if(kind==="")return{ok:!1,error:"workflow inventory: missing kind"};if(definitionDigest==="")return{ok:!1,error:"workflow inventory: missing definitionDigest"};if(!Array.isArray(obj.steps)||obj.steps.length===0)return{ok:!1,error:"workflow inventory: no declared steps"};let steps=[];for(let raw of obj.steps){if(typeof raw!=="object"||raw===null)return{ok:!1,error:"workflow inventory: a step is not an object"};let s2=raw;if(typeof s2.id!=="string"||s2.id==="")return{ok:!1,error:"workflow inventory: a step is missing its id"};steps.push({id:s2.id,initial:s2.initial===!0,terminal:s2.terminal===!0,failure:s2.failure===!0,pause:s2.pause===!0,loopBack:s2.loopBack===!0,conditional:s2.conditional===!0,...typeof s2.nodeType==="string"?{nodeType:s2.nodeType}:{},...typeof s2.description==="string"?{description:s2.description}:{}})}return{ok:!0,inventory:{name,kind,format:format2,version:version3,definitionDigest,steps,...source?{source}:{}}}}function assertInventoryIdentity(inventory,expectedDigest){if(expectedDigest==="")return{ok:!1,error:"workflow inventory: no expected definition digest to bind against"};if(inventory.definitionDigest!==expectedDigest)return{ok:!1,error:`workflow inventory: identity drift — projected ${inventory.definitionDigest} ≠ execution ${expectedDigest}`};return{ok:!0}}import{basename,isAbsolute,join as join3,resolve as resolve2}from"node:path";import{homedir}from"node:os";import{dirname as dirname3,join as join2,resolve}from"node:path";import{fileURLToPath as fileURLToPath3}from"node:url";init_dist2();init_zod();var RFC3339_PATTERN=/^\d{4}-\d{2}-\d{2}[Tt]\d{2}:\d{2}:\d{2}(\.\d+)?([Zz]|[+-]\d{2}:\d{2})$/;function isRfc3339Timestamp(value){return RFC3339_PATTERN.test(value)&&Number.isFinite(Date.parse(value))}var ALL_FINDING_CODES=["L1.markdown-parse","L1.schema-validation","L2.missing-required-section","L2.forbidden-section","L2.disallowed-section","L2.heading-level","L2.section-order","L3.requirements-format","L3.requirements-checkbox","L3.requirements-empty","L3.ac-empty","L3.ac-requirement-coverage","L3.solution-file-line","L3.review-priority-table","L3.required-section-placeholder","L3.plan-format","L3.unchecked-checklist","L3.ac-checklist-text","L3.ac-bdd-error","L3.ac-bdd-warning","L3.ac-bdd-invalid","L3.scope-delineation","L3.one-active-goal","L3.children-limit","L3.review-testing-contradiction","L4.design-placeholder","L4.feature-not-found","L4.feature-terminal","L4.missing-feature-id","L4.parent-not-found","L4.dependency-not-found","L4.rollup-subtasks-open","L4.rollup-parent-open","L4.rollup-missing-roster","L4.rollup-roster-not-declared-dependency","L4.readiness-blocked","L4.prose-prerequisite-unlisted","L4.prerequisite-cycle","L4.prerequisite-not-done","L4.gate-language","L4.linked-task-parse-failed","L4.orphan-scenarios","L4.uncovered-task-scenario","L4.uncovered-feature-scenario","L4.verdict-rows-match-no-scenario","L4.verifying-incomplete-tasks","L4.dogfood-missing","L4.stale-line-anchor","L4.anchor-subject-mismatch","L4.malformed-verdict-artifact","L4.scenario-unverified","L4.testing-verdict-stub","L4.evidence-not-recoverable","L4.feature-receipt-missing","L4.feature-receipt-malformed","L4.feature-receipt-cross-feature","L4.feature-receipt-divergent","L4.feature-receipt-failed","L4.feature-receipt-run","L4.feature-receipt-stale","L4.feature-receipt-contract"];function isFindingCode(code){return ALL_FINDING_CODES.includes(code)}init_dist();init_zod();var projectEntrySchema=exports_external.object({name:exports_external.string().min(1),path:exports_external.string().min(1),port:exports_external.number().int().nonnegative().default(0)}),projectsFileSchema=exports_external.object({schema_version:exports_external.literal(1).default(1),projects:exports_external.array(projectEntrySchema).default([])});init_zod();var slashCommandCategorySchema=exports_external.enum(["git","dev","sys","harness"]),slashCommandItemSchema=exports_external.object({name:exports_external.string().min(1),description:exports_external.string().min(1),category:slashCommandCategorySchema.default("dev"),argumentHint:exports_external.string().optional(),tags:exports_external.array(exports_external.string()).default([]),role:exports_external.string().optional(),source:exports_external.string().optional()}),slashCommandsFileSchema=exports_external.object({version:exports_external.number().int().default(1),updatedAt:exports_external.string().optional(),commands:exports_external.array(slashCommandItemSchema).default([])});var SPUR_LOG_LEVELS=["debug","info","warn","error"],DEFAULT_TASKS_DIR="docs/tasks",DEFAULT_FEATURES_DIR="docs/features",DEFAULT_DATABASE_URL=".spur/spur.db";var folderConfigSchema=exports_external.object({baseCounter:exports_external.number().int().nonnegative().default(0),label:exports_external.string().optional()});function folderPathWithDefault(defaultPath){return exports_external.preprocess((v)=>v==null?void 0:v,exports_external.string().default(defaultPath))}var tasksConfigSchema=exports_external.object({folders:exports_external.record(exports_external.string(),folderConfigSchema).default({}),active:folderPathWithDefault(DEFAULT_TASKS_DIR),severity:exports_external.record(exports_external.string(),exports_external.enum(["error","warning","off"])).optional()}).superRefine((data,ctx)=>{if(data.severity){for(let code of Object.keys(data.severity))if(!isFindingCode(code))ctx.addIssue({code:exports_external.ZodIssueCode.custom,path:["severity",code],message:`Unknown finding code "${code}" in severity overrides map`})}}),featuresConfigSchema=exports_external.object({dir:folderPathWithDefault(DEFAULT_FEATURES_DIR)}),EXECUTOR_CAPABILITY_TIERS=["cheap","standard","capable-1","capable-2","capable-3"];function normalizeExecutorTier(value){return value==="capable"?"capable-1":value}var executorCapabilityTierSchema=exports_external.preprocess((value)=>{if(value===void 0||value===null)return;return typeof value==="string"?normalizeExecutorTier(value):value},exports_external.enum(EXECUTOR_CAPABILITY_TIERS).optional()),AGENT_ROLE_NAMES=["scribe","coder","reviewer","planner"];var EXECUTION_CAPABILITY_AXES=["fsRead","fsWrite","networkEgress","processSpawn","externalMutationApproval"],SESSION_CAPABILITY_AXES=["resumeById","sessionDir","persistentStdin","structuredOutput"],AGENT_RUN_CAPABILITY_AXES=[...EXECUTION_CAPABILITY_AXES,...SESSION_CAPABILITY_AXES],EXECUTION_CAPABILITY_STATES=["enforced","available","unavailable","unknown"],EXECUTION_CAPABILITY_PROVENANCES=["native-known","operator-configured","unattested"],ExecutionCapabilityAttestationSchema=exports_external.object({state:exports_external.enum(EXECUTION_CAPABILITY_STATES),provenance:exports_external.enum(EXECUTION_CAPABILITY_PROVENANCES)}),ExecutionCapabilitiesSchema=exports_external.object({version:exports_external.literal(1),axes:exports_external.partialRecord(exports_external.enum(EXECUTION_CAPABILITY_AXES),ExecutionCapabilityAttestationSchema)}),EXECUTION_CAPABILITY_REQUIREMENTS=["available","enforced"],RequiresCapabilitiesSchema=exports_external.partialRecord(exports_external.enum(AGENT_RUN_CAPABILITY_AXES),exports_external.enum(EXECUTION_CAPABILITY_REQUIREMENTS)),executorAvailabilityOwnerSchema=exports_external.enum(["operator","quota","probe"]),executorDisabledObjectSchema=exports_external.object({owner:executorAvailabilityOwnerSchema,since:exports_external.string().refine(isRfc3339Timestamp,{message:"since must be an RFC 3339 timestamp"}),reason:exports_external.string().min(1)}),AgentExecutorConfigSchema=exports_external.object({name:exports_external.string().min(1),agent:exports_external.string().min(1),model:exports_external.string().min(1).optional(),tier:executorCapabilityTierSchema.optional(),executionCapabilities:ExecutionCapabilitiesSchema.optional(),disabled:exports_external.union([exports_external.boolean(),executorDisabledObjectSchema]).default(!1)});var AgentRoleConfigSchema=exports_external.object({tier:exports_external.enum(EXECUTOR_CAPABILITY_TIERS).optional(),stages:exports_external.array(exports_external.string().min(1)).min(1).optional()});var FleetMemberSchema=exports_external.object({id:exports_external.string().min(1).optional(),role:exports_external.enum(AGENT_ROLE_NAMES,{error:(issue2)=>Error(`Unknown role "${issue2.input}" — expected one of: ${AGENT_ROLE_NAMES.join(", ")}`)}).optional(),executor:exports_external.string().min(1).optional(),purpose:exports_external.string().optional(),enabled:exports_external.boolean().optional()}),FLEET_STRATEGIES=["rest","gtd"],FleetMemberEntrySchema=FleetMemberSchema.superRefine((member,ctx)=>{if(member.role===void 0&&member.executor===void 0)ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:"must declare a role or an executor — at least one is required"})}),AgentFleetSchema=exports_external.object({enabled:exports_external.boolean().default(!1),strategy:exports_external.enum(FLEET_STRATEGIES).default("rest"),orchestrator:exports_external.string().min(1).optional(),members:exports_external.array(FleetMemberEntrySchema).default([])});var AgentOutputConfigSchema=exports_external.object({"max-bytes":exports_external.number().int().positive().optional(),"max-lines":exports_external.number().int().positive().optional()}),AgentConfigSchema=exports_external.object({default:exports_external.string().optional(),executors:exports_external.array(AgentExecutorConfigSchema).optional(),roles:exports_external.record(exports_external.string(),AgentRoleConfigSchema).optional(),output:AgentOutputConfigSchema.optional(),sessionAffinity:exports_external.boolean().optional(),fleet:AgentFleetSchema.optional()}).superRefine((value,ctx)=>{for(let key of Object.keys(value.roles??{}))if(!AGENT_ROLE_NAMES.includes(key))ctx.addIssue({code:exports_external.ZodIssueCode.custom,path:["roles",key],message:`Unknown role "${key}" — expected one of: ${AGENT_ROLE_NAMES.join(", ")}`});let executors=value.executors,executorNames=new Set;if(executors!==void 0){let seen=new Set;for(let[index2,executor]of executors.entries()){if(seen.has(executor.name))ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:`Duplicate executor name: ${executor.name}`,path:["executors",index2,"name"]});if(executor.name==="inline"||executor.name==="auto")ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:`Executor name "${executor.name}" is reserved (the --agent selector value '${executor.name}' has fixed semantics); rename executor at index ${index2}.`,path:["executors",index2,"name"]});if(AGENT_ROLE_NAMES.includes(executor.name))ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:`Executor name "${executor.name}" collides with the role selector namespace ("${executor.name}"); rename executor at index ${index2}.`,path:["executors",index2,"name"]});seen.add(executor.name),executorNames.add(executor.name)}}}),RulesConfigSchema=exports_external.object({paths:exports_external.array(exports_external.string()).optional()}),WorkflowsConfigSchema=exports_external.object({paths:exports_external.array(exports_external.string()).optional()}),WorkflowConfigSchema=exports_external.object({hitlDecisionMaker:exports_external.boolean().optional(),logRetentionDays:exports_external.number().int().positive().default(30)}),RedactionConfigSchema=exports_external.object({enabled:exports_external.boolean().optional()}),HistoryRefreshConfigSchema=exports_external.object({on_completion:exports_external.boolean().default(!1),debounce_ms:exports_external.number().int().min(1000).default(600000)}),HistoryConfigSchema=exports_external.object({refresh:HistoryRefreshConfigSchema.optional()}),VersionCarrierEntrySchema=exports_external.looseObject({type:exports_external.string().min(1)}),BuilderBumpVerConfigSchema=exports_external.object({tagVersionSeparator:exports_external.string().min(1).default("-v"),aggregatePackage:exports_external.string().min(1).optional(),publishWorkflow:exports_external.string().min(1).default("publish.yml"),releaseCommitType:exports_external.string().min(1).default("chore"),releaseCommitScope:exports_external.string().min(1).default("release"),ghRunListLimit:exports_external.number().int().positive().default(5),versionCarriers:exports_external.array(VersionCarrierEntrySchema).default([])}),BuilderConfigSchema=exports_external.object({"bump-ver":BuilderBumpVerConfigSchema.optional()});var bootstrapOptionsSchema=exports_external.object({options:exports_external.record(exports_external.string(),exports_external.unknown()).optional()}),spurConfigSchema=exports_external.object({version:exports_external.string().optional(),name:exports_external.string().optional(),bootstrap:bootstrapOptionsSchema.optional(),agent:AgentConfigSchema.optional(),rules:RulesConfigSchema.optional(),workflows:WorkflowsConfigSchema.optional(),workflow:WorkflowConfigSchema.optional(),redaction:RedactionConfigSchema.optional(),history:HistoryConfigSchema.optional(),builder:BuilderConfigSchema.optional(),tasks:tasksConfigSchema.optional(),features:featuresConfigSchema.optional()});var configSchema3=exports_external.object({database:exports_external.object({url:exports_external.string().default(DEFAULT_DATABASE_URL)}).default({url:DEFAULT_DATABASE_URL}),server:exports_external.object({port:exports_external.coerce.number().int().positive().default(3000),host:exports_external.string().default("localhost"),openBrowser:exports_external.boolean().default(!0),webDistPath:exports_external.string().nullable().default(null)}).default({port:3000,host:"localhost",openBrowser:!0,webDistPath:null}),telemetry:exports_external.object({enabled:exports_external.boolean().default(!1),endpoint:exports_external.string().optional()}).default({enabled:!1}),logging:exports_external.object({level:exports_external.enum(SPUR_LOG_LEVELS).default("info")}).default({level:"info"})});import{existsSync as existsSync2,readdirSync as readdirSync2,statSync as statSync3}from"node:fs";import{dirname as dirname2,join}from"node:path";var BUNDLED_CONFIG_DIRS=["config","spur-cli/config"],cachedRoot;function bundledConfigRoot(){if(cachedRoot!==void 0)return cachedRoot;let dir=import.meta.dirname;while(!0){for(let name of BUNDLED_CONFIG_DIRS){let candidate=join(dir,name);if(isBundledConfigDir(candidate))return cachedRoot=candidate,cachedRoot}let parent=dirname2(dir);if(parent===dir)break;dir=parent}return cachedRoot=null,cachedRoot}function isBundledConfigDir(candidate){return existsSync2(candidate)&&statSync3(candidate).isDirectory()&&existsSync2(join(candidate,"rules"))&&existsSync2(join(candidate,"workflows"))}init_dist2();var GLOBAL_CONFIG_FILE=join2(homedir(),".config","spur","config.yaml"),LOADER_DIR=dirname3(fileURLToPath3(import.meta.url));init_dist6();init_dist2();import crypto3 from"node:crypto";function canonicalJsonStringify(obj){if(obj===null||typeof obj!=="object")return JSON.stringify(obj);if(Array.isArray(obj))return`[${obj.map(canonicalJsonStringify).join(",")}]`;return`{${Object.keys(obj).sort().map((key)=>`${JSON.stringify(key)}:${canonicalJsonStringify(obj[key])}`).join(",")}}`}function computeDefinitionDigest(workflow){let canonical=canonicalJsonStringify(workflow);return`sha256:${crypto3.createHash("sha256").update(canonical,"utf8").digest("hex")}`}var EMBEDDED_SCHEMA_PREFIX="\x00embedded-spur",SPUR_SCHEMA_MANIFEST="@gobing-ai/spur/package.json";function normalizeLayerPath(cwd,path8){return resolve2(cwd,path8)}function workflowLayers(opts){let sharedRoot=opts.sharedRoot!==void 0?opts.sharedRoot:bundledConfigRoot(),sharedPath=sharedRoot!==null?normalizeLayerPath(opts.cwd,join3(sharedRoot,"workflows")):null,layers=[],seen=new Set,add=(id,path8)=>{if(seen.has(path8))return;seen.add(path8),layers.push({id,path:path8})};add("project",normalizeLayerPath(opts.cwd,join3(opts.cwd,".spur","workflows")));for(let entry of opts.registered){if(sharedPath!==null&&normalizeLayerPath(opts.cwd,entry)===sharedPath)continue;add("registered",normalizeLayerPath(opts.cwd,entry))}if(sharedPath!==null)add("shared",sharedPath);return layers}function createEmbeddedSchemaOptions(embedded){if(embedded===void 0||embedded.size===0)return;let nodeFs=createNodeFileSystem2();return{resolve:(specifier)=>specifier===SPUR_SCHEMA_MANIFEST?`${EMBEDDED_SCHEMA_PREFIX}/package.json`:specifier,fileSystem:{readFile:async(path8)=>{if(!path8.startsWith(EMBEDDED_SCHEMA_PREFIX))return nodeFs.readFile(path8);let subpath=path8.slice(EMBEDDED_SCHEMA_PREFIX.length+1),text3=embedded.get(subpath);if(text3===void 0)throw Error(`No embedded schema registered for "${subpath}".`);return text3}}}}async function readWorkflowNameFast(fs2,filePath){try{let text3=await fs2.readFile(filePath),parsed=$parse(text3);return typeof parsed?.name==="string"?parsed.name:null}catch{return null}}async function scanWorkflowByName(cwd,name,registered){let fs2=createNodeFileSystem2();for(let layer of workflowLayers({cwd,registered}))try{let files=(await fs2.readDir(layer.path)).filter((f)=>f.endsWith(".yaml")||f.endsWith(".yml"));for(let f of files){let abs=join3(layer.path,f);if(await readWorkflowNameFast(fs2,abs)===name)return{path:abs,source:layer.id}}}catch{}return null}function resolveWorkflowFile(cwd,file2){let fs2=createNodeFileSystem2(),projectPath=resolve2(cwd,file2);if(fs2.exists(projectPath))return{path:projectPath,source:"project"};let isYaml=file2.endsWith(".yaml")||file2.endsWith(".yml"),base2=basename(file2);if(!isAbsolute(file2)){let withYaml=isYaml?file2:`${file2}.yaml`,projectSpur=resolve2(cwd,".spur","workflows",withYaml);if(fs2.exists(projectSpur))return{path:projectSpur,source:"project"};if(!isYaml){let projectDirect=resolve2(cwd,`${file2}.yaml`);if(fs2.exists(projectDirect))return{path:projectDirect,source:"project"};let projectSpurPipeline=resolve2(cwd,".spur","workflows",`${file2}-pipeline.yaml`);if(fs2.exists(projectSpurPipeline))return{path:projectSpurPipeline,source:"project"};let projectDirectPipeline=resolve2(cwd,`${file2}-pipeline.yaml`);if(fs2.exists(projectDirectPipeline))return{path:projectDirectPipeline,source:"project"}}}let bundledRoot=bundledConfigRoot();if(bundledRoot!==null){let sharedName=isYaml?base2:`${base2}.yaml`,sharedPath=join3(bundledRoot,"workflows",sharedName);if(fs2.exists(sharedPath))return{path:sharedPath,source:"shared"};if(!isYaml){let sharedPipeline=join3(bundledRoot,"workflows",`${base2}-pipeline.yaml`);if(fs2.exists(sharedPipeline))return{path:sharedPipeline,source:"shared"};let sharedLiteral=join3(bundledRoot,"workflows",base2);if(fs2.exists(sharedLiteral))return{path:sharedLiteral,source:"shared"}}return{path:null,probed:[projectPath,sharedPath]}}return{path:null,probed:[projectPath,null]}}async function resolveWorkflowDefinition(cwd,fileOrName,options={}){let registered=options.registered??[],resolved=(basename(fileOrName)===fileOrName&&!/\.ya?ml$/.test(fileOrName)&&!createNodeFileSystem2().exists(resolve2(cwd,fileOrName))?await scanWorkflowByName(cwd,fileOrName,registered):null)??resolveWorkflowFile(cwd,fileOrName);if(resolved.path===null){let scanned=await scanWorkflowByName(cwd,fileOrName,registered);if(scanned!==null)resolved=scanned;else{let[probedProject,probedShared]=resolved.probed;throw Error(`Workflow not found: ${probedProject}${probedShared!==null?` (shared: ${probedShared})`:""}`)}}let embedded=createEmbeddedSchemaOptions(options.embeddedSchemas),workflow=await loadWorkflowDef(resolved.path,{validateSchema:options.validateSchema!==!1,...embedded!==void 0?embedded:{}});if(workflow.version==="")throw Error(`Invalid workflow definition ${resolved.path}: root "version" is an empty string. Omit the field for an unversioned definition, or give it a non-empty literal.`);let digest=computeDefinitionDigest(workflow);return{path:resolved.path,workflow,digest,layer:resolved.source}}var UNPERSISTED_PREFIX="trace-unpersisted:";class RunRowNotFoundError extends Error{runId;constructor(runId){super(`run row not found: ${runId}`);this.name="RunRowNotFoundError",this.runId=runId}}class WorkflowActionTraceWriter{inner;recordFailure;db;boundaries=new Map;constructor(inner,recordFailure,db2){this.inner=inner;this.recordFailure=recordFailure;this.db=db2}async saveActionStart(runId,node,kind,options){let outcome=await this.guard("action.start",{runId,node,kind},()=>this.inner.saveActionStart(runId,node,kind,options));if(!outcome.ok){let syntheticId=`${UNPERSISTED_PREFIX}${crypto.randomUUID()}`;return this.boundaries.set(syntheticId,{runId,node,kind}),this.lastStart={runId,node,kind},syntheticId}return this.boundaries.set(outcome.value,{runId,node,kind}),this.lastStart={runId,node,kind},outcome.value}lastStart;async saveActionFinalize(actionId,status,durationMs,ok,kind,result,redactor){let origin2=this.boundaries.get(actionId)??this.lastStart;await this.guard("action.finish",{runId:origin2?.runId??"",node:origin2?.node,kind},()=>this.inner.saveActionFinalize(actionId,status,durationMs,ok,kind,result,redactor)),this.boundaries.delete(actionId)}async finalizeRun(runId,status,completedAt){await this.inner.finalizeRun(runId,status,completedAt)}async claimRunOwnership(runId,owner,expectedStatuses){return this.inner.claimRunOwnership(runId,owner,expectedStatuses)}async interruptRun(runId,reason){return this.inner.interruptRun(runId,reason)}async recordAction(boundary2){let start=await this.guard("action.start",{runId:boundary2.runId,node:boundary2.node,kind:boundary2.kind},()=>this.inner.saveActionStart(boundary2.runId,boundary2.node,boundary2.kind));if(!start.ok)return start;let finish=await this.guard("action.finish",{runId:boundary2.runId,node:boundary2.node,kind:boundary2.kind},()=>this.inner.saveActionFinalize(start.value,boundary2.status,boundary2.durationMs,boundary2.ok,boundary2.kind,boundary2.result,boundary2.redactor));if(!finish.ok)return finish;return await this.backdateStart(start.value,boundary2),{ok:!0,actionId:start.value}}async backdateStart(actionId,boundary2){let db2=this.db;if(db2===void 0||boundary2.durationMs<=0)return;await this.guard("action.backdate",{runId:boundary2.runId,node:boundary2.node,kind:boundary2.kind},async()=>{let dao2=new ActionRunDao(db2),completedAt=await dao2.completedAtById(actionId);if(completedAt===null)return;let startedAt=new Date(new Date(completedAt).getTime()-boundary2.durationMs).toISOString();await dao2.setStartedAt(actionId,startedAt)})}async closeRun(runId,status,completedAt){if(await this.inner.loadRun(runId)===void 0)throw new RunRowNotFoundError(runId);return await this.inner.finalizeRun(runId,status,completedAt??new Date().toISOString()),{ok:!0}}async guard(operation,context4,emit){try{return{ok:!0,value:await emit()}}catch(error51){let failure={operation,runId:context4.runId,...context4.node!==void 0?{node:context4.node}:{},...context4.kind!==void 0?{kind:context4.kind}:{},error:error51 instanceof Error?error51.message:String(error51),at:new Date().toISOString()};try{this.recordFailure?.(failure)}catch{}return{ok:!1,failure}}}createRun(record2){return this.inner.createRun(record2)}savePhase(runId,phase,status){return this.inner.savePhase(runId,phase,status)}saveTransition(runId,from,to,trigger){return this.inner.saveTransition(runId,from,to,trigger)}saveWorkflowState(runId,state,data){return this.inner.saveWorkflowState(runId,state,data)}commitTransition(runId,from,to,trigger,state,data,phase){return this.inner.commitTransition(runId,from,to,trigger,state,data,phase)}loadRun(runId){return this.inner.loadRun(runId)}listRuns(){return this.inner.listRuns()}findRunByKey(workflowName,externalKey){return this.inner.findRunByKey(workflowName,externalKey)}createOrAttachRun(record2){return this.inner.createOrAttachRun(record2)}reseedRun(runId,newState){return this.inner.reseedRun(runId,newState)}loadCurrentState(runId){return this.inner.loadCurrentState(runId)}loadLatestStateSnapshot(runId){return this.inner.loadLatestStateSnapshot(runId)}listPausedRuns(options){return this.inner.listPausedRuns(options)}}function createWorkflowActionTraceWriter(db2,recordFailure){return new WorkflowActionTraceWriter(new DbWorkflowPersistenceAdapter(db2),recordFailure,db2)}var TRIPWIRE_CATALOG=Object.freeze({"retry-exhausted":{id:"retry-exhausted",version:1,response:"fail",nextDecision:"Retries are exhausted; an operator must decide to escalate, extend the retry policy, or fail the stage. No further automatic retry is permitted."},"hard-budget":{id:"hard-budget",version:1,response:"fail",nextDecision:"An operator must raise the declared budget or trim the stage scope, then re-run the action; the run stays failed until then."},"capability-denied":{id:"capability-denied",version:1,response:"fail",nextDecision:"An operator must attest the executor capabilities in agent config or lower the stage requiresCapabilities, then re-run the action."},"proof-invalidated":{id:"proof-invalidated",version:1,response:"fail",nextDecision:"An operator must restore the proof inputs or re-establish the verdict (re-verify) before record; recording against a changed tree is blocked."},"output-drop":{id:"output-drop",version:1,response:"continue",nextDecision:"The dispatch completed but its captured evidence is incomplete (bounded relay dropped chunks). Inspect the session/trace for full output if the result is contested."}});var SHELL_METACHARACTERS=/[;&|<>$`(){}[\]!*?~#\n\r"']/;function splitLaunchCommand(value,label){if(SHELL_METACHARACTERS.test(value))return{error:`${label} must not contain shell metacharacters (got ${value})`};let tokens=value.trim().split(/\s+/).filter((t)=>t.length>0),command=tokens[0];if(command===void 0)return{error:`Action option ${label.slice(label.indexOf('"'))} must be a non-empty string`};return{command,leadingArgs:tokens.slice(1)}}import crypto4 from"node:crypto";import{tmpdir}from"node:os";import{dirname as dirname4,join as join4,resolve as resolve3,sep}from"node:path";init_dist6();class ProofCaptureError extends Error{stderr;constructor(message,stderr){super(message);this.stderr=stderr;this.name="ProofCaptureError"}}var TASK_SPEC_SECTIONS=["Background","Requirements","Acceptance Criteria","Design","Plan"],CANONICAL_TASK_HEADING_RE=/^##[ \t]+(\d+)\.[ \t]+(\S.*)$/m;function taskDocumentShapeError(content){let doc2=MarkdownDocument.parse(content,"task"),heading=CANONICAL_TASK_HEADING_RE.exec(doc2.bodyWithoutFrontmatter);if(heading===null)return"no canonical task heading (`## <WBS>. <title>`) was found";if((heading[2]??"").trim()==="")return`the canonical task heading for WBS ${heading[1]} has an empty title`;if(TASK_SPEC_SECTIONS.filter((section)=>doc2.hasSection(section)).length===0)return`no task specification section (${TASK_SPEC_SECTIONS.join(", ")}) was found`;return null}async function readProofInputContents(fileSystem=createNodeFileSystem2(),workdir,options){for(let name of["taskFile","featureFile"]){let value=options[name];if(value!==void 0&&typeof value!=="string")return{ok:!1,error:`${name} must be a string when supplied (got ${typeof value})`}}let readOne=async(name)=>{let raw=name==="taskFile"?options.taskFile:options.featureFile;if(raw===void 0||raw==="")return{};let workdirAbs=resolve3(workdir),resolved=resolve3(workdirAbs,raw);if(!(resolved===workdirAbs||resolved.startsWith(`${workdirAbs}${sep}`)))return{error:`${name} must resolve under the workflow workdir (${workdirAbs}): ${raw}`};let stat;try{stat=await fileSystem.stat(resolved)}catch(error51){return{error:`${name} could not be inspected: ${error51.message}`}}if(stat===null)return{error:`${name} does not exist: ${raw} (resolved ${resolved}) — an explicitly supplied spec must be readable, not silently omitted`};if(!stat.isFile())return{error:`${name} is not a regular file: ${resolved}`};let content;try{content=await fileSystem.readFile(resolved)}catch(error51){return{error:`${name} is not readable: ${error51.message}`}}if(name==="taskFile"){let shapeError=taskDocumentShapeError(content);if(shapeError!==null)return{error:`taskFile is not a task document: ${raw} (resolved ${resolved}) — ${shapeError}. Supply the task specification markdown itself: a \`## <WBS>. <title>\` heading plus at least one of ${TASK_SPEC_SECTIONS.join(", ")}. A file containing only a path is not dereferenced.`}}return{content}},task=await readOne("taskFile");if(task.error!==void 0)return{ok:!1,error:task.error};let feature=await readOne("featureFile");if(feature.error!==void 0)return{ok:!1,error:feature.error};return{ok:!0,...task.content!==void 0?{taskContent:task.content}:{},...feature.content!==void 0?{featureContent:feature.content}:{}}}var DEFAULT_EXCLUDE_GLOBS=["docs/tasks*","docs/features*"];async function createGitAlternateTree(cwd,excludeGlobs=DEFAULT_EXCLUDE_GLOBS,executor=new NodeProcessExecutor2,fs2=createNodeFileSystem2()){let indexFile=join4(tmpdir(),`spur-proof-fingerprint-${crypto4.randomUUID()}.index`);try{await fs2.ensureDir(dirname4(indexFile));let env2=Object.fromEntries(Object.entries(getEnvVars()).filter((entry)=>entry[1]!==void 0));env2.GIT_INDEX_FILE=indexFile;let common4={cwd,env:env2,forceBuffered:!0,rejectOnError:!1},read=await executor.run({command:"git",args:["read-tree","HEAD"],...common4});if(read.exitCode!==0)throw new ProofCaptureError(`git read-tree HEAD failed with exit code ${read.exitCode}`,read.stderr);let excludes=excludeGlobs.map((glob)=>`:(exclude)${glob}`),add=await executor.run({command:"git",args:["add","-A","--",".",...excludes],...common4});if(add.exitCode!==0)throw new ProofCaptureError(`git add -A failed with exit code ${add.exitCode}`,add.stderr);let tree=await executor.run({command:"git",args:["write-tree"],...common4});if(tree.exitCode!==0)throw new ProofCaptureError(`git write-tree failed with exit code ${tree.exitCode}`,tree.stderr);return tree.stdout.trim()}catch(error51){if(error51 instanceof ProofCaptureError)throw error51;throw new ProofCaptureError(`git alternate-tree capture threw: ${error51.message}`)}finally{if(await fs2.exists(indexFile))try{await fs2.deleteFile(indexFile)}catch{}}}function extractTaskProofData(content){let doc2=MarkdownDocument.parse(content,"task"),fm=doc2.frontmatterData??{},wbs=typeof fm.wbs==="string"?fm.wbs:void 0,name=typeof fm.name==="string"?fm.name:void 0,feature_id=typeof fm.feature_id==="string"?fm.feature_id:void 0,depends_on;if(Array.isArray(fm.depends_on))depends_on=fm.depends_on.filter((d)=>typeof d==="string");else if(Array.isArray(fm.dependencies))depends_on=fm.dependencies.filter((d)=>typeof d==="string");let sections={},taskSections=["Background","Requirements","Acceptance Criteria","Design","Plan"];for(let sec of taskSections)if(doc2.hasSection(sec)){let body=doc2.getSection(sec);if(body!==null)sections[sec]=body.trim()}return{...wbs!==void 0?{wbs}:{},...name!==void 0?{name}:{},...feature_id!==void 0?{feature_id}:{},...depends_on!==void 0?{depends_on}:{},sections}}function extractFeatureProofData(content){let doc2=MarkdownDocument.parse(content,"feature"),fm=doc2.frontmatterData??{},id=typeof fm.id==="string"?fm.id:void 0,name=typeof fm.name==="string"?fm.name:void 0,sections={},featureSections=["Goal","Scope","Acceptance Criteria"];for(let sec of featureSections)if(doc2.hasSection(sec)){let body=doc2.getSection(sec);if(body!==null)sections[sec]=body.trim()}return{...id!==void 0?{id}:{},...name!==void 0?{name}:{},sections}}async function computeProofInputFingerprint(options={}){let cwd=options.cwd??process.cwd(),gitTree=await createGitAlternateTree(cwd,options.excludeGlobs??DEFAULT_EXCLUDE_GLOBS,options.processExecutor,options.fileSystem),task;if(options.taskContent!==void 0)task=extractTaskProofData(options.taskContent);let feature;if(options.featureContent!==void 0)feature=extractFeatureProofData(options.featureContent);let canonical=canonicalJsonStringify({gitTree,...task!==void 0?{task}:{},...feature!==void 0?{feature}:{},...options.learningsContent!==void 0?{learnings:options.learningsContent}:{}});return`sha256:${crypto4.createHash("sha256").update(canonical,"utf8").digest("hex")}`}var ProofInputFingerprint={compute:computeProofInputFingerprint};init_zod();var VERDICT_AGGREGATES=["PASS","PARTIAL","FAIL","UNKNOWN"],ROW_STATUSES=["MET","PARTIAL","UNMET","N/A"],CHECK_SEVERITIES=["blocker","major","minor","advisory"],verdictSchema=exports_external.string().transform((v,ctx)=>{let up=v.toUpperCase();if(!VERDICT_AGGREGATES.includes(up))return ctx.addIssue({code:"custom",message:`invalid verdict "${v}" (expected PASS|PARTIAL|FAIL|UNKNOWN)`}),"UNKNOWN";return up}),coverageRowSchema=exports_external.object({id:exports_external.string().optional(),scenario:exports_external.string().optional(),status:exports_external.string(),evidenceType:exports_external.string().optional(),evidence:exports_external.string().optional()}).superRefine((r,ctx)=>{if(r.id!==void 0&&r.scenario!==void 0&&r.id!==r.scenario)ctx.addIssue({code:"custom",message:`id/scenario conflict ("${r.id}" vs "${r.scenario}")`,path:["scenario"]});if(!ROW_STATUSES.includes(r.status.toUpperCase()))ctx.addIssue({code:"custom",message:`invalid row status "${r.status}"`,path:["status"]})}).transform((r)=>({id:r.id??r.scenario??"",status:r.status.toUpperCase(),evidenceType:r.evidenceType??"",evidence:r.evidence??""})),checkSchema=exports_external.object({name:exports_external.string().optional(),check:exports_external.string().optional(),id:exports_external.string().optional(),status:exports_external.string(),evidence:exports_external.string().optional().default(""),severity:exports_external.enum(CHECK_SEVERITIES).optional()}).superRefine((c3,ctx)=>{if(c3.name===void 0&&c3.check===void 0&&c3.id===void 0)ctx.addIssue({code:"custom",message:"check row needs one of name/check/id",path:["name"]})}).transform((c3)=>({name:c3.name??c3.check??c3.id??"",status:c3.status,evidence:c3.evidence,severity:c3.severity})),verifyVerdictSchema=exports_external.object({wbs:exports_external.string().optional().default(""),verdict:verdictSchema,requirements:exports_external.array(coverageRowSchema).optional().default([]),acceptanceCriteria:exports_external.array(coverageRowSchema).optional().default([]),checks:exports_external.array(checkSchema).optional().default([]),source:exports_external.string().optional(),pipelineRunId:exports_external.string().optional(),recordedAt:exports_external.string().optional()});var field=(path8,label)=>({path:path8,label}),SOURCE_PROFILES={planning:{producerPackage:"spur",subsystem:"planning",remediationKind:"prefix-filter"},queue:{producerPackage:"@gobing-ai/ts-infra",subsystem:"job-queue",remediationKind:"prefix-filter"},scheduler:{producerPackage:"@gobing-ai/ts-infra",subsystem:"scheduler",remediationKind:"prefix-filter"},message:{producerPackage:"spur",subsystem:"coordination-messaging",remediationKind:"prefix-filter"},process:{producerPackage:"@gobing-ai/ts-runtime",subsystem:"process-executor",remediationKind:"prefix-filter"},workflow:{producerPackage:"@gobing-ai/ts-dual-workflow-engine",subsystem:"workflow",remediationKind:"workflow-trace"},rule:{producerPackage:"@gobing-ai/ts-rule-engine",subsystem:"rule-engine",remediationKind:"rule-trace"},agent:{producerPackage:"@gobing-ai/ts-ai-runner",subsystem:"agent-runner",remediationKind:"prefix-filter"},history:{producerPackage:"spur",subsystem:"history",remediationKind:"prefix-filter"},bus:{producerPackage:"@gobing-ai/ts-infra",subsystem:"event-bus",remediationKind:"prefix-filter"},api:{producerPackage:"spur",subsystem:"http-api",remediationKind:"prefix-filter"}};function at(data,path8){if(data===null)return;let current=data;for(let segment of path8.split(".")){if(current===null||typeof current!=="object"||Array.isArray(current))return;current=current[segment]}return current}function s2(data,...paths){for(let path8 of paths){let value=at(data,path8);if(typeof value==="string"&&value.length>0)return value}return}function n2(data,...paths){for(let path8 of paths){let value=at(data,path8);if(typeof value==="number"&&Number.isFinite(value))return String(value);if(typeof value==="boolean")return String(value)}return}function entityId(input){return s2(input.data,"entity.id")??input.correlation.entityId??""}function looksLikeOpaqueId(value){if(typeof value!=="string")return!1;let v=value.trim();if(v==="")return!1;if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v))return!0;if(/^live[-_][a-z0-9._-]+$/i.test(v))return!0;if(/^(?:eventId|rowId|runId|executionId|actionId)$/i.test(v))return!0;return!1}function humanWorkflowTitle(input){let raw=s2(input.data,"workflowName")??s2(input.data,"workflow");if(raw!==void 0&&!looksLikeOpaqueId(raw))return(raw.split("/").pop()?.replace(/\.(?:ya?ml|json)$/i,"")??raw).replace(/[._-]+$/,"");return""}function humanStepLabel(data){let label=s2(data,"nodeLabel")??s2(data,"stepName")??s2(data,"step");if(label!==void 0&&!looksLikeOpaqueId(label))return label;let node=s2(data,"node");if(node!==void 0&&!looksLikeOpaqueId(node))return node;return}function derivedFrom(...paths){return{support:"derived",derive:({data})=>s2(data,...paths)}}function derivedFromValue(...paths){return{support:"derived",derive:({data})=>n2(data,...paths)??s2(data,...paths)}}var unsupported={support:"unsupported"};function baseEvent(name,source,renderer,payloadPolicy="metadata-only",tier="default",producer){return{name,source,tier,payloadPolicy,renderer,...producer!==void 0?{producer}:{}}}var BASE_CATALOG=[baseEvent("task.created","planning","planning"),baseEvent("task.updated","planning","planning"),baseEvent("task.transitioned","planning","planning"),baseEvent("feature.created","planning","planning"),baseEvent("feature.updated","planning","planning"),baseEvent("feature.transitioned","planning","planning"),baseEvent("queue.consumer.started","queue","queue"),baseEvent("queue.consumer.stopped","queue","queue"),baseEvent("queue.job.enqueued","queue","queue"),baseEvent("queue.job.started","queue","queue"),baseEvent("queue.job.completed","queue","queue"),baseEvent("queue.job.failed","queue","queue"),baseEvent("queue.job.retrying","queue","queue"),baseEvent("queue.stats","queue","queue"),baseEvent("scheduler.job.executed","scheduler","scheduler"),baseEvent("message.sent","message","message"),baseEvent("message.replied","message","message"),baseEvent("process.spawned","process","process"),baseEvent("process.exited","process","process"),baseEvent("process.stopped","process","process"),baseEvent("process.started","process","process"),baseEvent("agent.invoke.start","agent","agent"),baseEvent("agent.invoke.exit","agent","agent"),baseEvent("agent.invoke.escalated","agent","agent","metadata-only","default",{package:"spur",subsystem:"agent-runner"}),baseEvent("agent.invoke.exhausted","agent","agent","metadata-only","default",{package:"spur",subsystem:"agent-runner"}),baseEvent("agent.started","agent","agent"),baseEvent("agent.stopped","agent","agent"),baseEvent("agent.message.sent","agent","agent"),baseEvent("strategy.changed","agent","agent","metadata-only","default",{package:"spur",subsystem:"fleet-strategy"}),baseEvent("fleet.capacity.changed","agent","agent","metadata-only","default",{package:"spur",subsystem:"write-slot"}),baseEvent("task.assigned","planning","planning"),baseEvent("history.import.completed","history","history-import"),baseEvent("history.analyze.completed","history","history-analyze"),baseEvent("history.daily.failed","history","history-daily"),baseEvent("history.refresh.enqueued","history","history-refresh"),baseEvent("rule.run.start","rule","rule"),baseEvent("rule.eval.start","rule","rule"),baseEvent("rule.eval.done","rule","rule"),baseEvent("rule.eval.error","rule","rule"),baseEvent("rule.run.done","rule","rule"),baseEvent("workflow.run.started","workflow","workflow-run"),baseEvent("workflow.run.done","workflow","workflow-run"),baseEvent("workflow.run.failed","workflow","workflow-run"),baseEvent("workflow.run.finalized","workflow","workflow-run"),baseEvent("workflow.escalation.created","workflow","workflow-run","redacted"),baseEvent("workflow.escalation.projection_failed","workflow","workflow-run","metadata-only"),baseEvent("workflow.run.paused","workflow","workflow-run"),baseEvent("workflow.run.resumed","workflow","workflow-run"),baseEvent("workflow.run.reseeded","workflow","workflow-run"),baseEvent("workflow.node.enter","workflow","workflow-phase"),baseEvent("workflow.phase","workflow","workflow-phase"),baseEvent("workflow.node.transition","workflow","workflow-transition"),baseEvent("workflow.transition","workflow","workflow-transition"),baseEvent("workflow.transition.requested","workflow","workflow-transition","metadata-only","diagnostic"),baseEvent("workflow.transition.denied","workflow","workflow-transition","metadata-only","diagnostic"),baseEvent("workflow.action.started","workflow","workflow-action"),baseEvent("workflow.action.finished","workflow","workflow-action"),baseEvent("workflow.action.failed_continue","workflow","workflow-action"),baseEvent("workflow.guard.evaluated","workflow","workflow-guard","metadata-only","diagnostic"),baseEvent("workflow.hitl.ask","workflow","workflow-hitl","redacted"),baseEvent("workflow.hitl.response","workflow","workflow-hitl","redacted"),baseEvent("workflow.hitl.note","workflow","workflow-hitl","redacted"),baseEvent("workflow.custom","workflow","workflow-custom"),baseEvent("workflow.agent","workflow","workflow-agent","redacted","diagnostic"),baseEvent("workflow.steering","workflow","workflow-steering","redacted"),baseEvent("api.request.error","api","api"),baseEvent("bus.emit.done","bus","bus","metadata-only","diagnostic"),baseEvent("bus.emit.noop","bus","bus","metadata-only","diagnostic"),baseEvent("bus.handler.error","bus","bus","metadata-only","diagnostic"),baseEvent("bus.handler.async.enqueued","bus","bus","metadata-only","diagnostic")],SYSTEM_EVENT_PRESENTERS={"task.created":{description:"A task file was created with a new WBS id.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity")],summary:({data,correlation})=>`[task] ${entityId({data,correlation})} created`,outcome:unsupported},"task.updated":{description:"An existing task file was updated in place, naming the section that changed.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity"),field("field","Field"),field("data.mutation.name","Section"),field("data.after","After"),field("data.diff","Diff")],summary:({data,correlation})=>{let section=s2(data,"data.mutation.name"),id=entityId({data,correlation});return section!==void 0?`[task] ${section}`:`[task] ${id||"updated"}`},outcome:unsupported},"task.transitioned":{description:"A task moved between lifecycle states, naming both the previous and new status.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity"),field("from","From"),field("to","To")],summary:({data,correlation})=>{let id=entityId({data,correlation}),from=s2(data,"from"),to=s2(data,"to");return from!==void 0&&to!==void 0?`[task] ${id} : ${from} -> ${to}`:`[task] ${id} transitioned`},outcome:{support:"derived",derive:({data})=>s2(data,"to")}},"feature.created":{description:"A feature file was created with a new feature id.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity")],summary:({data,correlation})=>`[feature] ${entityId({data,correlation})} created`,outcome:unsupported},"feature.updated":{description:"An existing feature file was updated in place, naming the section that changed.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity"),field("field","Field"),field("data.mutation.name","Section"),field("data.after","After"),field("data.diff","Diff")],summary:({data,correlation})=>{let section=s2(data,"data.mutation.name"),id=entityId({data,correlation});return section!==void 0?`[feature] ${section}`:`[feature] ${id||"updated"}`},outcome:unsupported},"feature.transitioned":{description:"A feature moved between lifecycle states, naming both the previous and new status.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity"),field("from","From"),field("to","To")],summary:({data,correlation})=>{let id=entityId({data,correlation}),from=s2(data,"from"),to=s2(data,"to");return from!==void 0&&to!==void 0?`[feature] ${id} : ${from} -> ${to}`:`[feature] ${id} transitioned`},outcome:{support:"derived",derive:({data})=>s2(data,"to")}},"queue.consumer.started":{description:"The configured queue consumer began polling its named queue.",fields:[field("queueName","Queue"),field("startedAt","Started"),field("pollInterval","Poll interval"),field("batchSize","Batch size"),field("maxConcurrency","Max concurrency"),field("visibilityTimeout","Visibility timeout")],summary:({data})=>{let name=s2(data,"queueName");return name!==void 0?`[queue] ${name} : consumer started`:"[queue] consumer started"},outcome:{support:"derived",derive:({data})=>at(data,"startedAt")!==void 0?"running":void 0}},"queue.consumer.stopped":{description:"The queue consumer stopped, reporting whether it drained in-flight work.",fields:[field("queueName","Queue"),field("stoppedAt","Stopped"),field("drainTimeoutMs","Drain timeout"),field("inFlightAtStop","In flight"),field("drained","Drained")],summary:({data})=>{let name=s2(data,"queueName");return name!==void 0?`[queue] ${name} : consumer stopped`:"[queue] consumer stopped"},outcome:{support:"derived",derive:({data})=>{let drained=at(data,"drained");if(drained===!0)return"drained";if(drained===!1)return"timeout";return}}},"queue.job.enqueued":{description:"A job was enqueued onto the job queue for later processing.",fields:[field("jobId","Job"),field("type","Type"),field("nextRetryAt","Next retry")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} enqueued`:"[queue] job enqueued"},outcome:unsupported},"queue.job.started":{description:"A queued job handler began executing (job identity and phase anchor).",fields:[field("jobId","Job"),field("type","Type"),field("name","Name")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} started`:"[queue] job started"},outcome:unsupported},"queue.job.completed":{description:"A queued job finished successfully with its attempt and duration.",fields:[field("jobId","Job"),field("type","Type"),field("attempt","Attempt"),field("durationMs","Duration (ms)")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} completed`:"[queue] job completed"},outcome:unsupported},"queue.job.failed":{description:"A queued job exhausted its attempts and failed with an error.",fields:[field("jobId","Job"),field("type","Type"),field("attempt","Attempt"),field("maxRetries","Max retries"),field("durationMs","Duration (ms)"),field("error","Error")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} failed`:"[queue] job failed"},outcome:derivedFrom("error")},"queue.job.retrying":{description:"A queued job failed once and is scheduled for another attempt.",fields:[field("jobId","Job"),field("type","Type"),field("attempt","Attempt"),field("maxRetries","Max retries"),field("nextRetryAt","Next retry"),field("error","Error")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} retrying`:"[queue] job retrying"},outcome:{support:"derived",derive:({data})=>{let attempt=at(data,"attempt"),max=at(data,"maxRetries");if(typeof attempt==="number"&&typeof max==="number"&&Number.isFinite(attempt)&&Number.isFinite(max))return`retrying ${attempt}/${max}`;return s2(data,"error")}}},"queue.stats":{description:"Periodic job-queue statistics across ready, running, completed, and failed counts.",fields:[field("ready","Ready"),field("running","Running"),field("completed","Completed"),field("failed","Failed")],summary:()=>"[queue] stats",outcome:unsupported},"scheduler.job.executed":{description:"A scheduler job ran to completion or failed, with its duration.",fields:[field("name","Job"),field("action","Action"),field("durationMs","Duration (ms)"),field("error","Error")],summary:({data})=>{let name=s2(data,"name");return name!==void 0?`[scheduler] ${name}`:"[scheduler] job executed"},outcome:{support:"derived",derive:({data})=>s2(data,"error")??(at(data,"error")===null?"completed":void 0)}},"message.sent":{description:"A team message was sent from one member to another.",fields:[field("msgId","Message"),field("fromId","From"),field("toId","To"),field("threadId","Thread")],summary:({data})=>{let from=s2(data,"fromId"),to=s2(data,"toId");return from!==void 0&&to!==void 0?`[message] ${from} -> ${to}`:"[message] sent"},outcome:unsupported},"message.replied":{description:"A member replied to an existing message thread.",fields:[field("msgId","Message"),field("fromId","From"),field("toId","To"),field("threadId","Thread")],summary:({data})=>{let from=s2(data,"fromId"),thread=s2(data,"threadId");return from!==void 0&&thread!==void 0?`[message] ${from} replied in ${thread}`:"[message] replied"},outcome:unsupported},"process.spawned":{description:"A supervised process was spawned with a new pid.",fields:[field("label","Label"),field("pid","PID"),field("agentId","Agent")],summary:({data})=>{let label=s2(data,"label")??n2(data,"pid");return label!==void 0?`[process] ${label} spawned`:"[process] spawned"},outcome:unsupported},"process.exited":{description:"A supervised process exited, carrying its exit code, signal, or failure reason.",fields:[field("label","Label"),field("pid","PID"),field("exitCode","Exit code"),field("signal","Signal"),field("durationMs","Duration (ms)"),field("reason","Reason")],summary:({data})=>{let label=s2(data,"label")??n2(data,"pid");return label!==void 0?`[process] ${label} exited`:"[process] exited"},outcome:{support:"derived",derive:({data})=>{let reason=s2(data,"reason");if(reason!==void 0)return reason;let signal=s2(data,"signal");if(signal!==void 0)return`signal ${signal}`;let code=at(data,"exitCode");if(typeof code==="number"&&Number.isFinite(code))return code===0?"ok":`exit ${code}`;return}}},"process.stopped":{description:"A supervised process was stopped, naming the stopping reason.",fields:[field("label","Label"),field("pid","PID"),field("signal","Signal"),field("reason","Reason")],summary:({data})=>{let label=s2(data,"label")??n2(data,"pid");return label!==void 0?`[process] ${label} stopped`:"[process] stopped"},outcome:derivedFrom("reason")},"process.started":{description:"A process executor started a process with a new pid.",fields:[field("label","Label"),field("pid","PID")],summary:({data})=>{let label=s2(data,"label")??n2(data,"pid");return label!==void 0?`[process] ${label} started`:"[process] started"},outcome:unsupported},"agent.invoke.start":{description:"An agent invocation began, naming the agent and its operation.",fields:[field("agent","Agent"),field("operation","Operation"),field("routing.role","Role"),field("routing.tier","Tier"),field("routing.executor","Executor"),field("routing.source","Selection source")],summary:({data})=>{let agent=s2(data,"agent"),operation=s2(data,"operation");return agent!==void 0&&operation!==void 0?`[agent] ${agent} · ${operation}`:"[agent] invocation started"},outcome:unsupported},"agent.invoke.exit":{description:"An agent invocation exited, reporting its exit code or signal.",fields:[field("agent","Agent"),field("operation","Operation"),field("exitCode","Exit code"),field("signal","Signal"),field("routing.role","Role"),field("routing.tier","Tier"),field("routing.executor","Executor"),field("routing.source","Selection source")],summary:({data})=>{let agent=s2(data,"agent"),operation=s2(data,"operation");return agent!==void 0&&operation!==void 0?`[agent] ${agent} · ${operation} exited`:"[agent] invocation exited"},outcome:{support:"derived",derive:({data})=>{let signal=s2(data,"signal");if(signal!==void 0)return`signal ${signal}`;let code=at(data,"exitCode");if(typeof code==="number"&&Number.isFinite(code))return code===0?"ok":`exit ${code}`;return}}},"agent.invoke.escalated":{description:"An agent invocation escalated from one executor tier to another.",fields:[field("fromExecutor","From executor"),field("fromTier","From tier"),field("toExecutor","To executor"),field("toTier","To tier"),field("trigger","Trigger")],summary:({data})=>{let from=s2(data,"fromExecutor"),to=s2(data,"toExecutor");return from!==void 0&&to!==void 0?`[agent] ${from} -> ${to}`:"[agent] escalation"},outcome:{support:"derived",derive:({data})=>s2(data,"toTier")??s2(data,"trigger")}},"agent.invoke.exhausted":{description:"An agent invocation exhausted every eligible executor tier without success.",fields:[field("stage","Stage"),field("attempts","Attempts"),field("fromTier","From tier"),field("toTier","To tier"),field("fromExecutor","From executor"),field("toExecutor","To executor")],summary:({data})=>{let stage=s2(data,"stage");return stage!==void 0?`[agent] ${stage} escalation exhausted`:"[agent] escalation exhausted"},outcome:derivedFromValue("attempts")},"agent.started":{description:"An agent started, carrying its id and type.",fields:[field("agentId","Agent"),field("agentType","Agent type"),field("pid","PID")],summary:({data})=>{let id=s2(data,"agentId");return id!==void 0?`[agent] ${id} started`:"[agent] started"},outcome:unsupported},"agent.stopped":{description:"An agent stopped, reporting its exit code.",fields:[field("agentId","Agent"),field("exitCode","Exit code")],summary:({data})=>{let id=s2(data,"agentId");return id!==void 0?`[agent] ${id} stopped`:"[agent] stopped"},outcome:derivedFromValue("exitCode")},"strategy.changed":{description:"A project strategy changed (0838), minting a new strategy version for dispatch fencing.",fields:[field("data.projectPath","Project"),field("data.strategy","Strategy"),field("data.version","Version")],summary:({data})=>{let strategy=s2(data,"data.strategy"),version3=s2(data,"data.version");return strategy!==void 0?`[strategy] ${strategy}${version3!==void 0?` (v${version3})`:""}`:"[strategy] changed"},outcome:unsupported},"fleet.capacity.changed":{description:"The project write slot was claimed or released (0837), changing dispatch capacity.",fields:[field("data.projectPath","Project"),field("data.change","Change"),field("data.holderId","Holder")],summary:({data})=>{let change=s2(data,"data.change"),holder=s2(data,"data.holderId");return`[fleet] write slot ${change??"changed"}${holder!==void 0?` — ${holder}`:""}`},outcome:unsupported},"agent.message.sent":{description:"A message was sent to an agent, reporting delivery success.",fields:[field("agentId","Agent"),field("ok","Delivered")],summary:({data})=>{let id=s2(data,"agentId");return id!==void 0?`[agent] message -> ${id}`:"[agent] message sent"},outcome:derivedFromValue("ok")},"task.assigned":{description:"A task was assigned to an agent, naming the agent when resolved.",fields:[field("memberId","Member"),field("agentType","Agent type"),field("taskId","Task"),field("outcome","Outcome")],summary:({data})=>{let member=s2(data,"memberId"),task=s2(data,"taskId");return task!==void 0&&member!==void 0?`[task] ${task} assigned to ${member}`:"[task] assignment recorded"},outcome:derivedFrom("outcome")},"history.import.completed":{description:"A history import finished, reporting files, messages, and exit code.",fields:[field("source","Source"),field("sources","Sources"),field("files","Files"),field("messages","Messages"),field("durationMs","Duration (ms)"),field("exitCode","Exit code"),field("artifactPath","Artifact"),field("cwd","Project root")],retain:[field("trigger","Refresh trigger"),field("windowStart","Refresh window start"),field("windowEnd","Refresh window end"),field("importMode","Import mode"),field("coverage","Refresh coverage")],summary:({data})=>{let source=s2(data,"source")??s2(data,"sources");return source!==void 0?`[history] import · ${source}`:"[history] import completed"},outcome:derivedFromValue("exitCode")},"history.analyze.completed":{description:"A history analyze pass finished, reporting sources, duration, and exit code.",fields:[field("source","Source"),field("sources","Sources"),field("durationMs","Duration (ms)"),field("exitCode","Exit code"),field("artifactPath","Artifact")],retain:[field("trigger","Refresh trigger"),field("windowStart","Refresh window start"),field("windowEnd","Refresh window end"),field("importMode","Import mode")],summary:({data})=>{let source=s2(data,"source")??s2(data,"sources");return source!==void 0?`[history] analyze · ${source}`:"[history] analyze completed"},outcome:derivedFromValue("exitCode")},"history.daily.failed":{description:"The daily history refresh failed, carrying the detail, reason, and exit code.",fields:[field("source","Source"),field("sources","Sources"),field("detail","Detail"),field("reason","Reason"),field("exitCode","Exit code")],retain:[field("trigger","Refresh trigger"),field("windowStart","Refresh window start"),field("windowEnd","Refresh window end"),field("importMode","Import mode")],summary:()=>"[history] daily failed",outcome:{support:"derived",derive:({data})=>s2(data,"reason")??s2(data,"detail")??n2(data,"exitCode")}},"history.refresh.enqueued":{description:"A completion-triggered history refresh was enqueued, naming its window.",fields:[field("trigger","Trigger"),field("triggerId","Trigger id"),field("jobId","Queue job"),field("windowStart","Window start"),field("windowEnd","Window end"),field("coalesced","Coalesced"),field("outcome","Outcome")],summary:({data})=>{let start=s2(data,"windowStart"),end=s2(data,"windowEnd");return start!==void 0&&end!==void 0?`[history] refresh · ${start} -> ${end}`:"[history] refresh enqueued"},outcome:{support:"derived",derive:({data})=>{let status=s2(data,"outcome");return status!==void 0&&status!=="enqueued"?status:void 0}}},"rule.run.start":{description:"A rule run began with the rule count it will evaluate.",fields:[field("runId","Run"),field("ruleCount","Rules"),field("evaluator","Evaluator")],summary:({data,correlation})=>{let run=s2(data,"runId")??correlation.runId;return run!==void 0?`[rule] run ${run} started`:"[rule] run started"},outcome:unsupported},"rule.eval.start":{description:"A single rule began evaluating.",fields:[field("runId","Run"),field("ruleId","Rule"),field("evaluator","Evaluator"),field("index","Index"),field("total","Total")],summary:({data})=>{let id=s2(data,"ruleId");return id!==void 0?`[rule] ${id} evaluating`:"[rule] evaluating"},outcome:unsupported},"rule.eval.done":{description:"A rule finished evaluating, reporting its findings count and severity.",fields:[field("runId","Run"),field("ruleId","Rule"),field("evaluator","Evaluator"),field("findings","Findings"),field("durationMs","Duration (ms)"),field("severity","Severity")],summary:({data})=>{let id=s2(data,"ruleId");return id!==void 0?`[rule] ${id} evaluated`:"[rule] evaluated"},outcome:derivedFromValue("findings")},"rule.eval.error":{description:"A rule evaluation failed with an error.",fields:[field("runId","Run"),field("ruleId","Rule"),field("evaluator","Evaluator"),field("error","Error")],summary:({data})=>{let id=s2(data,"ruleId");return id!==void 0?`[rule] ${id} error`:"[rule] error"},outcome:derivedFrom("error")},"rule.run.done":{description:"A rule run finished, reporting findings and whether it stopped early.",fields:[field("runId","Run"),field("findings","Findings"),field("durationMs","Duration (ms)"),field("stoppedEarly","Stopped early"),field("severity","Severity")],summary:({data,correlation})=>{let run=s2(data,"runId")??correlation.runId;return run!==void 0?`[rule] run ${run} done`:"[rule] run done"},outcome:{support:"derived",derive:({data})=>n2(data,"findings")??s2(data,"stoppedEarly")}},"workflow.run.started":{description:"A workflow run started, naming the workflow definition.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("mode","Mode"),field("dryRun","Dry run")],summary:(input)=>{let name=humanWorkflowTitle(input);return name!==""?`[workflow] ${name} started`:"[workflow] started"},outcome:unsupported},"workflow.run.done":{description:"A workflow run reached a done terminal state.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("finalState","Final state"),field("transitionsTaken","Transitions")],summary:(input)=>{let name=humanWorkflowTitle(input);return name!==""?`[workflow] ${name} done`:"[workflow] done"},outcome:derivedFrom("finalState")},"workflow.run.failed":{description:"A workflow run failed with a terminal failure reason.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("finalState","Final state"),field("reason","Reason")],summary:(input)=>{let name=humanWorkflowTitle(input);return name!==""?`[workflow] ${name} failed`:"[workflow] failed"},outcome:derivedFrom("reason")},"workflow.run.finalized":{description:"A workflow run settled on a terminal status.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("status","Status")],summary:(input)=>{let name=humanWorkflowTitle(input);return name!==""?`[workflow] ${name} finalized`:"[workflow] finalized"},outcome:derivedFrom("status")},"workflow.escalation.created":{description:"A canonical escalation packet was projected from existing run evidence.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("fingerprint","Fingerprint"),field("artifactPath","Artifact"),field("decision","Decision")],summary:(input)=>{let name=humanWorkflowTitle(input),decision=typeof at(input.data,"decision")==="string"?` — ${String(at(input.data,"decision"))}`:"";return name!==""?`[workflow] escalation packet created (${name}${decision})`:`[workflow] escalation packet created${decision}`},outcome:derivedFrom("decision")},"workflow.escalation.projection_failed":{description:"Escalation packet projection failed; the original failure is preserved untouched.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("error","Error")],summary:()=>"[workflow] escalation packet projection failed",outcome:derivedFrom("error")},"workflow.run.paused":{description:"A workflow run paused at a step, naming the step when available.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("transitionsTaken","Transitions")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} paused`:"[workflow] paused"},outcome:unsupported},"workflow.run.resumed":{description:"A paused workflow run resumed at a step, naming the step when available.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} resumed`:"[workflow] resumed"},outcome:unsupported},"workflow.run.reseeded":{description:"A workflow run was reseeded to a new state, naming the transition.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("fromState","From"),field("toState","To")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"fromState"),to=s2(input.data,"toState");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} : ${from} -> ${to}`:`[workflow] : ${from} -> ${to}`;return name!==""?`[workflow] ${name} reseeded`:"[workflow] reseeded"},outcome:derivedFrom("toState")},"workflow.node.enter":{description:"The engine entered a workflow node, naming the step when available.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("transitionsTaken","Transitions")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] node entered"},outcome:unsupported},"workflow.phase":{description:"A workflow phase changed status, naming the phase.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("phase","Phase"),field("status","Status")],summary:(input)=>{let name=humanWorkflowTitle(input),phase=s2(input.data,"phase"),parts=[name,phase].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] phase"},outcome:derivedFrom("status")},"workflow.node.transition":{description:"A workflow transitioned between nodes, naming the from and to states.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("trigger","Trigger")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} : ${from} -> ${to}`:`[workflow] : ${from} -> ${to}`;return name!==""?`[workflow] ${name} transitioned`:"[workflow] transitioned"},outcome:derivedFrom("to")},"workflow.transition":{description:"A workflow state transition was committed.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("trigger","Trigger")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} : ${from} -> ${to}`:`[workflow] : ${from} -> ${to}`;return name!==""?`[workflow] ${name} transitioned`:"[workflow] transitioned"},outcome:derivedFrom("to")},"workflow.transition.requested":{description:"A workflow transition was requested and accepted for evaluation.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("trigger","Trigger")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} requested ${from} -> ${to}`:`[workflow] requested ${from} -> ${to}`;return name!==""?`[workflow] ${name} transition requested`:"[workflow] transition requested"},outcome:unsupported},"workflow.transition.denied":{description:"A workflow transition was denied with a reason.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("reason","Reason")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} denied ${from} -> ${to}`:`[workflow] denied ${from} -> ${to}`;return name!==""?`[workflow] ${name} transition denied`:"[workflow] transition denied"},outcome:derivedFrom("reason")},"workflow.action.started":{description:"A workflow action began executing, naming the step and kind.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("actionId","Action"),field("kind","Kind")],retain:[field("metadata.agent","Agent"),field("metadata.role","Role"),field("routing.executor","Executor")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} started`:"[workflow] action started"},outcome:unsupported},"workflow.action.finished":{description:"A workflow action finished, reporting its status and success.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("actionId","Action"),field("kind","Kind"),field("durationMs","Duration (ms)"),field("status","Status")],retain:[field("metadata.agent","Agent"),field("metadata.role","Role"),field("routing.executor","Executor")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} finished`:"[workflow] action finished"},outcome:{support:"derived",derive:({data})=>s2(data,"status")??n2(data,"ok")}},"workflow.action.failed_continue":{description:"A workflow action failed but the workflow continued, carrying the error.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("transitionsTaken","Transitions"),field("error","Error")],retain:[field("metadata.agent","Agent"),field("metadata.role","Role"),field("routing.executor","Executor")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} failed; continuing`:"[workflow] action failed; continuing"},outcome:derivedFrom("error")},"workflow.guard.evaluated":{description:"A workflow guard was evaluated for a transition, reporting whether it passed.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("kind","Kind"),field("passed","Passed")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} guard ${from} -> ${to}`:`[workflow] guard ${from} -> ${to}`;return name!==""?`[workflow] ${name} guard evaluated`:"[workflow] guard evaluated"},outcome:derivedFromValue("passed")},"workflow.hitl.ask":{description:"A workflow paused for human input, naming the step and kind.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("kind","Kind")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} awaiting input`:"[workflow] awaiting input"},outcome:unsupported},"workflow.hitl.response":{description:"Human input was received for a paused workflow step.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("ok","Accepted")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} input received`:"[workflow] input received"},outcome:derivedFromValue("ok")},"workflow.hitl.note":{description:"A note was recorded on a paused workflow step.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} note`:"[workflow] note"},outcome:unsupported},"workflow.custom":{description:"A custom workflow event was emitted, naming the custom event.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("name","Event")],summary:(input)=>{let name=humanWorkflowTitle(input),custom3=s2(input.data,"name"),parts=[name,custom3].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] custom"},outcome:unsupported},"workflow.agent":{description:"A workflow-dispatched agent execution lifecycle event, discriminated by kind.",fields:[field("runId","Run"),field("executionId","Execution"),field("actionId","Action"),field("kind","Kind"),field("agent","Agent"),field("model","Model")],retain:[field("metadata.agent","Agent"),field("metadata.role","Role"),field("routing.executor","Executor")],summary:(input)=>{let name=humanWorkflowTitle(input),kind=s2(input.data,"kind"),parts=[name,kind!==void 0?`agent ${kind}`:"agent"].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] agent"},outcome:{support:"derived",derive:({data})=>s2(data,"kind")==="finished"?s2(data,"outcome"):void 0}},"workflow.steering":{description:"A steering command was acknowledged for a workflow action boundary.",fields:[field("runId","Run"),field("actionId","Action"),field("operation","Operation"),field("actor","Actor"),field("accepted","Accepted"),field("state","State"),field("reason","Reason")],summary:(input)=>{let name=humanWorkflowTitle(input),operation=s2(input.data,"operation"),parts=[name,operation!==void 0?`steering ${operation}`:"steering"].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] steering"},outcome:{support:"derived",derive:({data})=>{let reason=s2(data,"reason");if(reason!==void 0)return reason;let accepted=at(data,"accepted");if(accepted===!0)return"accepted";if(accepted===!1)return"rejected";return s2(data,"state")}}},"api.request.error":{description:"An API request failed, naming the method, path, and status or error code.",fields:[field("method","Method"),field("path","Path"),field("status","Status"),field("code","Code"),field("requestId","Request"),field("error","Error")],summary:({data})=>{let method=s2(data,"method"),path8=s2(data,"path");return method!==void 0&&path8!==void 0?`[api] ${method} ${path8}`:"[api] request error"},outcome:{support:"derived",derive:({data})=>s2(data,"error")??s2(data,"code")??n2(data,"status")}},"bus.emit.done":{description:"An event was emitted to its handlers on the event bus.",fields:[field("event","Event"),field("handlers","Handlers"),field("durationMs","Duration (ms)")],summary:({data})=>{let event=s2(data,"event");return event!==void 0?`[bus] ${event} emitted`:"[bus] event emitted"},outcome:derivedFromValue("handlers")},"bus.emit.noop":{description:"An event was emitted but had no registered handlers.",fields:[field("event","Event"),field("handlers","Handlers"),field("durationMs","Duration (ms)")],summary:({data})=>{let event=s2(data,"event");return event!==void 0?`[bus] ${event} had no handlers`:"[bus] event had no handlers"},outcome:derivedFromValue("handlers")},"bus.handler.error":{description:"An event-bus handler threw an error while processing an event.",fields:[field("event","Event"),field("handlers","Handlers"),field("durationMs","Duration (ms)"),field("error","Error")],summary:({data})=>{let event=s2(data,"event");return event!==void 0?`[bus] ${event} handler error`:"[bus] handler error"},outcome:derivedFrom("error")},"bus.handler.async.enqueued":{description:"An event-bus handler was enqueued for asynchronous processing.",fields:[field("event","Event"),field("handlers","Handlers")],summary:({data})=>{let event=s2(data,"event");return event!==void 0?`[bus] ${event} handlers enqueued`:"[bus] handlers enqueued"},outcome:derivedFromValue("handlers")}};function inferSeverity(name){if(/(?:failed|error|denied)$/.test(name))return"error";if(/(?:retrying|paused|dropped)$/.test(name))return"warning";return"info"}function resolveCatalogEntry(base2){let profile=SOURCE_PROFILES[base2.source],presenter=SYSTEM_EVENT_PRESENTERS[base2.name];return{name:base2.name,prefix:base2.name.split(".")[0]??base2.name,source:base2.source,tier:base2.tier,persisted:!0,streamed:!0,payloadPolicy:base2.payloadPolicy,renderer:base2.renderer,...profile,...base2.producer!==void 0?{producerPackage:base2.producer.package,subsystem:base2.producer.subsystem}:{},severity:inferSeverity(base2.name),description:presenter.description,metadataFields:presenter.retain?[...presenter.fields,...presenter.retain.filter((r)=>!presenter.fields.some((f)=>f.path===r.path))]:presenter.fields,remediationKind:profile.remediationKind}}var SYSTEM_EVENT_CATALOG=BASE_CATALOG.map(resolveCatalogEntry),SYSTEM_EVENT_NAMES=SYSTEM_EVENT_CATALOG.map((entry)=>entry.name),SYSTEM_EVENT_PERSISTED_NAMES=SYSTEM_EVENT_CATALOG.filter((entry)=>entry.tier==="default").map((entry)=>entry.name),SYSTEM_EVENT_STREAMED_NAMES=SYSTEM_EVENT_CATALOG.filter((entry)=>entry.tier==="default").map((entry)=>entry.name),SYSTEM_EVENT_PREFIXES=Array.from(new Set(SYSTEM_EVENT_CATALOG.map((entry)=>entry.prefix))),SYSTEM_EVENT_DEFAULT_NAMES=SYSTEM_EVENT_CATALOG.filter((entry)=>entry.tier==="default").map((entry)=>entry.name),SYSTEM_EVENT_DIAGNOSTIC_NAMES=SYSTEM_EVENT_CATALOG.filter((entry)=>entry.tier==="diagnostic").map((entry)=>entry.name);var SYSTEM_EVENT_CATALOG_METADATA=SYSTEM_EVENT_CATALOG.map(({name,prefix,source,tier,renderer,producerPackage,subsystem,severity,description,metadataFields,remediationKind})=>({name,prefix,source,tier,renderer,producerPackage,subsystem,severity,description,metadataFields,remediationKind}));function workflowVersionLiteral(workflow){return typeof workflow.version==="string"&&workflow.version!==""?workflow.version:null}var{mkdirSync:mkdirSync2}=await import("node:fs");function parseIdentityMetadata(raw){if(raw.trim()==="")return{};try{let parsed=JSON.parse(raw);if(parsed===null||typeof parsed!=="object"||Array.isArray(parsed))return null;return parsed}catch{return null}}async function openInlineRunProjectDb(workdir){let url2=join5(resolve4(workdir),".spur","spur.db");mkdirSync2(join5(url2,".."),{recursive:!0});let adapter=await createMigratedDb({url:url2});return{adapter,close:()=>adapter.close()}}async function createOrAttachInlineRun(input){let runId=input.runId.trim();if(runId==="")return{ok:!1,error:"inline run setup requires a non-empty runId (driver Run setup step 2)"};let workdir=resolve4(input.workdir),resolved;try{let projection=input.inventory===void 0?void 0:parseWorkflowInventory(input.inventory);if(projection&&!projection.ok)return projection;let inventory=projection?.ok?projection.inventory:void 0;if(inventory&&(!inventory.source||inventory.kind!=="state-machine"))return{ok:!1,error:"inline run setup requires a state-machine inventory with definition source"};if(resolved=await resolveWorkflowDefinition(workdir,inventory?.source?.path??input.file,{validateSchema:!0,...input.embeddedSchemas!==void 0?{embeddedSchemas:input.embeddedSchemas}:{},...!inventory?{registered:input.registered}:{}}),(resolved.workflow.kind??"state-machine")!=="state-machine")return{ok:!1,error:"inline run setup requires a state-machine definition"};if(inventory?.source){let identity4=assertInventoryIdentity(inventory,resolved.digest);if(!identity4.ok)return identity4;if(inventory.name!==resolved.workflow.name)return{ok:!1,error:"inline run setup: inventory workflow name does not match its definition"};resolved={...resolved,layer:inventory.source.layer}}}catch(error51){return{ok:!1,error:`inline run setup could not resolve the workflow definition: ${error51.message}`}}let digest=resolved.digest,version3=workflowVersionLiteral(resolved.workflow),source={path:resolved.path,layer:resolved.layer,workdir},db2=await input.getDb(),existing=await new RunDao(db2).traceRowById(runId);if(existing!==void 0){let metadata=parseIdentityMetadata(existing.metadata_json);if(metadata===null)return{ok:!1,error:`inline run setup refuses run ${runId}: its existing row has malformed metadata_json, `+"so its identity cannot be verified — delete the stale run row or allocate a new run id"};let resumeDigest=typeof metadata.resumeDefinitionDigest==="string"?metadata.resumeDefinitionDigest:void 0,launchDigest=typeof metadata.definitionDigest==="string"?metadata.definitionDigest:void 0,effectiveDigest=resumeDigest??launchDigest;if(effectiveDigest===void 0)return{ok:!1,error:`inline run setup refuses run ${runId}: its existing row carries no definition digest `+"(pre-identity legacy row) — allocate a new run id instead of attaching an unverifiable identity"};if(effectiveDigest!==digest)return{ok:!1,error:`inline run setup refuses run ${runId}: the resolved definition digest (${digest}) does not match the run's recorded ${resumeDigest!==void 0?"resume":""} digest (${effectiveDigest}) — `+"a changed definition must resume through the explicit resume rules, not silently re-attach"};if(existing.workflow_name!==resolved.workflow.name)return{ok:!1,error:`inline run setup refuses run ${runId}: the run row records workflow "${existing.workflow_name}" but the resolved definition is "${resolved.workflow.name}" — conflicting run identity`};if(typeof metadata.definitionSource!=="object"||metadata.definitionSource===null||Array.isArray(metadata.definitionSource))return{ok:!1,error:`inline run setup refuses run ${runId}: its existing row carries no definition source `+"(path/layer/workdir) — allocate a new run id instead of attaching an unverifiable launch source"};let existingSource=metadata.definitionSource;if(!(typeof existingSource.path==="string"&&resolve4(existingSource.path)===resolved.path&&normalizePersistedWorkflowLayer(existingSource.layer)===resolved.layer&&typeof existingSource.workdir==="string"&&resolve4(existingSource.workdir)===workdir))return{ok:!1,error:`inline run setup refuses run ${runId}: the recorded definition source (${JSON.stringify(existingSource)}) does not match the resolved launch source (${JSON.stringify(source)}) — conflicting project/workdir identity`};return{ok:!0,attached:!0,runId,workflowName:resolved.workflow.name,definitionDigest:digest,workflowVersion:version3,resolvedPath:resolved.path,layer:resolved.layer,workdir,status:existing.status}}return await new WorkflowService(createDefaultWorkflowEngineHost(),new DbWorkflowPersistenceAdapter(db2)).createOrAttachRun({id:runId,workflow_name:resolved.workflow.name,mode:"state-machine",status:"running",started_at:new Date().toISOString(),completed_at:null,metadata_json:JSON.stringify({definitionDigest:digest,workflowVersion:version3,definitionSource:source})}),{ok:!0,attached:!1,runId,workflowName:resolved.workflow.name,definitionDigest:digest,workflowVersion:version3,resolvedPath:resolved.path,layer:resolved.layer,workdir,status:"running"}}import{basename as basename2,join as join6}from"node:path";var FEATURE_RECEIPT_SCHEMA_VERSION=1,DEFAULT_FEATURE_VERIFICATION_CMD="bun run spur-check-feature",RECEIPT_ID_PATTERN=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function assertReceiptId(kind,id){if(!RECEIPT_ID_PATTERN.test(id)||id.includes(".."))throw Error(`invalid ${kind} for receipt path: ${JSON.stringify(id)}`)}function featureReceiptPaths(runDir,featureId2,runId){return assertReceiptId("featureId",featureId2),assertReceiptId("runId",runId),{runScoped:join6(runDir,`${runId}-feature-verification.json`),featureScoped:join6(runDir,`${featureId2}-feature-verification.json`),log:join6(runDir,`${runId}-feature-verification.log`),status:join6(runDir,`${runId}-feature-verification.status`)}}async function atomicWriteReceipt(fs2,path8,receipt){let body=`${JSON.stringify(receipt,null,4)}
1462
+ `:this._frontmatterBlock.slice(0,rawStart)+raw+this._frontmatterBlock.slice(rawStart+oldRaw.length)}serialize(){let result=this._frontmatterBlock;result+=this._preamble;for(let section of this._sections)result+=section.modifiedText??section.originalText;return result}}function escapeYamlArrayElement(value){return`"${value.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function escapeYamlValue(value){if(value.startsWith('"')&&value.endsWith('"'))return value;if(/[:{}[\],&*?|>!%@`#"'\\\n\r]/.test(value))return`"${value.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`;if(/^(null|true|false|yes|no|on|off)$/i.test(value))return`"${value}"`;if(/^\d/.test(value)&&!/^\d{4}-\d{2}-\d{2}/.test(value))return`"${value}"`;return value}init_zod();var TASK_STATUSES=["backlog","todo","wip","testing","blocked","done","cancelled"],FEATURE_STATUSES=["backlog","active","verifying","blocked","done","cancelled"];var PRIORITIES=["P0","P1","P2","P3"],PROFILES=["simple","standard","complex","research","refine","plan","unit","review","docs"],TASK_TYPES=["task","issue","review","meta","brainstorm"],TASK_VARIANTS=["standard","feature-impl","issue","review","meta","brainstorm"];var FEATURE_ID_PATTERN=/^[A-Z][1-9]*$/;var TASK_STATUS_ALIASES={completed:"done",complete:"done","in-progress":"wip","in progress":"wip",in_progress:"wip",dropped:"cancelled",cancel:"cancelled",canceled:"cancelled",new:"backlog",pending:"backlog",blocked:"blocked",wip:"wip",testing:"testing",done:"done",cancelled:"cancelled",backlog:"backlog",todo:"todo"};function normalizeTaskStatus(raw){let key=raw.trim().toLowerCase(),resolved=TASK_STATUS_ALIASES[key];if(resolved===void 0)throw Error(`Unknown task status: ${JSON.stringify(raw)} (allowed: ${TASK_STATUSES.join(", ")})`);return resolved}var isoDateString=exports_external.string().min(1).refine((value)=>!Number.isNaN(Date.parse(value)),{message:"must be an ISO 8601 timestamp"}),featureId=exports_external.string().regex(FEATURE_ID_PATTERN,{message:"feature id must match ^[A-Z][1-9]*$ (DD-14)"}).nullable().optional(),wbsString=exports_external.string().regex(/^\d{4}$/,{message:"parent_wbs must be a 4-digit WBS string"}).nullable().optional(),taskFrontmatterSchema=exports_external.object({schema_version:exports_external.literal(1),name:exports_external.string().min(1),description:exports_external.string().optional(),status:exports_external.preprocess((val)=>{if(typeof val==="string")try{return normalizeTaskStatus(val)}catch{}return val},exports_external.enum(TASK_STATUSES)),type:exports_external.enum(TASK_TYPES).optional().default("task"),template:exports_external.enum(TASK_VARIANTS).optional(),profile:exports_external.enum(PROFILES).optional(),feature_id:featureId,parent_wbs:wbsString,priority:exports_external.enum(PRIORITIES).optional(),tags:exports_external.array(exports_external.string()).optional(),dependencies:exports_external.array(exports_external.string()).optional(),ac_numbering:exports_external.literal("task-local").optional(),ac_altitude:exports_external.enum(["graduating","task-local"]).optional(),done_forced:exports_external.preprocess((v)=>typeof v==="string"?v==="true":v,exports_external.boolean().optional()),done_reason:exports_external.string().optional(),feature_link_declined:exports_external.preprocess((v)=>typeof v==="string"?v==="true":v,exports_external.boolean().optional()),estimate_hours:exports_external.preprocess((v)=>typeof v==="string"&&v.trim()!==""?Number(v):v,exports_external.number().positive().optional()),created_at:isoDateString,updated_at:isoDateString}),featureFrontmatterSchema=exports_external.object({schema_version:exports_external.literal(1),id:exports_external.string().regex(FEATURE_ID_PATTERN,{message:"feature id must match ^[A-Z][1-9]*$ (DD-14)"}),name:exports_external.string().min(1),status:exports_external.enum(FEATURE_STATUSES),priority:exports_external.enum(PRIORITIES).optional(),tags:exports_external.array(exports_external.string()).optional(),created_at:isoDateString,updated_at:isoDateString});var taskBatchItemSchema=exports_external.object({name:exports_external.string().min(1,"name is required"),background:exports_external.string().optional(),requirements:exports_external.string().optional(),design:exports_external.string().optional(),plan:exports_external.string().optional(),acceptance_criteria:exports_external.string().optional(),feature_id:featureId,parent_wbs:wbsString,priority:exports_external.enum(PRIORITIES).optional(),tags:exports_external.array(exports_external.string()).optional(),template:exports_external.enum(TASK_VARIANTS).optional(),estimate_hours:exports_external.number().positive().optional()}).strict(),taskBatchSchema=exports_external.array(taskBatchItemSchema).min(1,"batch must contain at least one task");init_dist2();init_zod();var sectionNameSchema=exports_external.enum(TASK_CANONICAL_SECTIONS),matrixEntrySchema=exports_external.object({required:exports_external.array(sectionNameSchema).optional(),optional:exports_external.array(sectionNameSchema).optional(),forbidden:exports_external.array(sectionNameSchema).optional(),gate:exports_external.boolean().optional()}).strict(),matrixStatusSchema=exports_external.enum(["backlog","todo","wip","testing","blocked","done","cancelled"]),sectionMatrixSchema=exports_external.object({variants:exports_external.record(exports_external.string(),exports_external.partialRecord(matrixStatusSchema,matrixEntrySchema))}).strict();var CANONICAL_INDEX=new Map(TASK_CANONICAL_SECTIONS.map((s2,i2)=>[s2,i2]));init_zod();import crypto3 from"node:crypto";function canonicalJsonStringify(obj){if(obj===null||typeof obj!=="object")return JSON.stringify(obj);if(Array.isArray(obj))return`[${obj.map(canonicalJsonStringify).join(",")}]`;return`{${Object.keys(obj).sort().map((key)=>`${JSON.stringify(key)}:${canonicalJsonStringify(obj[key])}`).join(",")}}`}function computeDefinitionDigest(workflow){let canonical=canonicalJsonStringify(workflow);return`sha256:${crypto3.createHash("sha256").update(canonical,"utf8").digest("hex")}`}var DecideOptionsSchema=exports_external.object({id:exports_external.string().min(1),method:exports_external.enum(["choice","noul"]),question:exports_external.string().min(1),choices:exports_external.array(exports_external.string().min(1)).min(2).optional(),evidence:exports_external.array(exports_external.string().min(1)).optional(),default:exports_external.string().min(1),minConfidence:exports_external.number().min(0).max(1).optional(),resultFile:exports_external.string().min(1)}).strict().superRefine((options,ctx)=>{if(options.method==="choice"){if(options.choices===void 0)ctx.addIssue({code:"custom",message:"choices is required for method choice (at least 2 labels)"});else if(!options.choices.includes(options.default))ctx.addIssue({code:"custom",message:`default "${options.default}" is not one of choices [${options.choices.join(", ")}]`});return}if(options.choices!==void 0)ctx.addIssue({code:"custom",message:"choices is only valid for method choice; noul uses the engine yes/no outcomes"});if(options.default!=="yes"&&options.default!=="no")ctx.addIssue({code:"custom",message:'default must be "yes" or "no" for method noul'})});function parseWorkflowInventory(json2){if(typeof json2!=="object"||json2===null)return{ok:!1,error:"workflow inventory: projection is not an object"};let obj=json2,name=typeof obj.name==="string"?obj.name:"",kind=typeof obj.kind==="string"?obj.kind:"",format2=typeof obj.format==="string"?obj.format:"",version3=typeof obj.version==="string"||typeof obj.version==="number"?String(obj.version):"",definitionDigest=typeof obj.definitionDigest==="string"?obj.definitionDigest:"",source;if(obj.source!==void 0){if(typeof obj.source!=="object"||obj.source===null)return{ok:!1,error:"workflow inventory: invalid definition source"};let value=obj.source;if(typeof value.path!=="string"||value.path===""||typeof value.layer!=="string"||!["project","registered","shared"].includes(value.layer))return{ok:!1,error:"workflow inventory: invalid definition source path/layer"};source={path:value.path,layer:value.layer}}if(name==="")return{ok:!1,error:"workflow inventory: missing name"};if(kind==="")return{ok:!1,error:"workflow inventory: missing kind"};if(definitionDigest==="")return{ok:!1,error:"workflow inventory: missing definitionDigest"};if(!Array.isArray(obj.steps)||obj.steps.length===0)return{ok:!1,error:"workflow inventory: no declared steps"};let steps=[];for(let raw of obj.steps){if(typeof raw!=="object"||raw===null)return{ok:!1,error:"workflow inventory: a step is not an object"};let s2=raw;if(typeof s2.id!=="string"||s2.id==="")return{ok:!1,error:"workflow inventory: a step is missing its id"};steps.push({id:s2.id,initial:s2.initial===!0,terminal:s2.terminal===!0,failure:s2.failure===!0,pause:s2.pause===!0,loopBack:s2.loopBack===!0,conditional:s2.conditional===!0,...typeof s2.nodeType==="string"?{nodeType:s2.nodeType}:{},...typeof s2.description==="string"?{description:s2.description}:{}})}return{ok:!0,inventory:{name,kind,format:format2,version:version3,definitionDigest,steps,...source?{source}:{}}}}function assertInventoryIdentity(inventory,expectedDigest){if(expectedDigest==="")return{ok:!1,error:"workflow inventory: no expected definition digest to bind against"};if(inventory.definitionDigest!==expectedDigest)return{ok:!1,error:`workflow inventory: identity drift — projected ${inventory.definitionDigest} ≠ execution ${expectedDigest}`};return{ok:!0}}import{basename,isAbsolute,join as join3,resolve as resolve2}from"node:path";init_dist6();init_dist();init_dist2();init_zod();import{existsSync as existsSync3,statSync as statSync4}from"node:fs";import{homedir}from"node:os";import{dirname as dirname3,join as join2,resolve}from"node:path";import{fileURLToPath as fileURLToPath3}from"node:url";init_zod();var RFC3339_PATTERN=/^\d{4}-\d{2}-\d{2}[Tt]\d{2}:\d{2}:\d{2}(\.\d+)?([Zz]|[+-]\d{2}:\d{2})$/;function isRfc3339Timestamp(value){return RFC3339_PATTERN.test(value)&&Number.isFinite(Date.parse(value))}var ALL_FINDING_CODES=["L1.markdown-parse","L1.schema-validation","L2.missing-required-section","L2.forbidden-section","L2.disallowed-section","L2.heading-level","L2.section-order","L3.requirements-format","L3.requirements-checkbox","L3.requirements-empty","L3.ac-empty","L3.ac-requirement-coverage","L3.solution-file-line","L3.review-priority-table","L3.required-section-placeholder","L3.plan-format","L3.unchecked-checklist","L3.ac-checklist-text","L3.ac-bdd-error","L3.ac-bdd-warning","L3.ac-bdd-invalid","L3.scope-delineation","L3.one-active-goal","L3.children-limit","L3.review-testing-contradiction","L4.design-placeholder","L4.feature-not-found","L4.feature-terminal","L4.missing-feature-id","L4.parent-not-found","L4.dependency-not-found","L4.rollup-subtasks-open","L4.rollup-parent-open","L4.rollup-missing-roster","L4.rollup-roster-not-declared-dependency","L4.readiness-blocked","L4.prose-prerequisite-unlisted","L4.prerequisite-cycle","L4.prerequisite-not-done","L4.gate-language","L4.linked-task-parse-failed","L4.orphan-scenarios","L4.uncovered-task-scenario","L4.uncovered-feature-scenario","L4.verdict-rows-match-no-scenario","L4.verifying-incomplete-tasks","L4.dogfood-missing","L4.stale-line-anchor","L4.anchor-subject-mismatch","L4.malformed-verdict-artifact","L4.scenario-unverified","L4.testing-verdict-stub","L4.evidence-not-recoverable","L4.feature-receipt-missing","L4.feature-receipt-malformed","L4.feature-receipt-cross-feature","L4.feature-receipt-divergent","L4.feature-receipt-failed","L4.feature-receipt-run","L4.feature-receipt-stale","L4.feature-receipt-contract"];function isFindingCode(code){return ALL_FINDING_CODES.includes(code)}init_dist();init_zod();var projectEntrySchema=exports_external.object({name:exports_external.string().min(1),path:exports_external.string().min(1),port:exports_external.number().int().nonnegative().default(0)}),projectsFileSchema=exports_external.object({schema_version:exports_external.literal(1).default(1),projects:exports_external.array(projectEntrySchema).default([])});init_zod();var slashCommandCategorySchema=exports_external.enum(["git","dev","sys","harness"]),slashCommandItemSchema=exports_external.object({name:exports_external.string().min(1),description:exports_external.string().min(1),category:slashCommandCategorySchema.default("dev"),argumentHint:exports_external.string().optional(),tags:exports_external.array(exports_external.string()).default([]),role:exports_external.string().optional(),source:exports_external.string().optional()}),slashCommandsFileSchema=exports_external.object({version:exports_external.number().int().default(1),updatedAt:exports_external.string().optional(),commands:exports_external.array(slashCommandItemSchema).default([])});var SPUR_LOG_LEVELS=["debug","info","warn","error"],DEFAULT_TASKS_DIR="docs/tasks",DEFAULT_FEATURES_DIR="docs/features",DEFAULT_DATABASE_URL=".spur/spur.db";var folderConfigSchema=exports_external.object({baseCounter:exports_external.number().int().nonnegative().default(0),label:exports_external.string().optional()});function folderPathWithDefault(defaultPath){return exports_external.preprocess((v)=>v==null?void 0:v,exports_external.string().default(defaultPath))}var tasksConfigSchema=exports_external.object({folders:exports_external.record(exports_external.string(),folderConfigSchema).default({}),active:folderPathWithDefault(DEFAULT_TASKS_DIR),severity:exports_external.record(exports_external.string(),exports_external.enum(["error","warning","off"])).optional()}).superRefine((data,ctx)=>{if(data.severity){for(let code of Object.keys(data.severity))if(!isFindingCode(code))ctx.addIssue({code:exports_external.ZodIssueCode.custom,path:["severity",code],message:`Unknown finding code "${code}" in severity overrides map`})}}),featuresConfigSchema=exports_external.object({dir:folderPathWithDefault(DEFAULT_FEATURES_DIR)}),EXECUTOR_CAPABILITY_TIERS=["cheap","standard","capable-1","capable-2","capable-3"];function normalizeExecutorTier(value){return value==="capable"?"capable-1":value}var executorCapabilityTierSchema=exports_external.preprocess((value)=>{if(value===void 0||value===null)return;return typeof value==="string"?normalizeExecutorTier(value):value},exports_external.enum(EXECUTOR_CAPABILITY_TIERS).optional()),AGENT_ROLE_NAMES=["scribe","coder","reviewer","planner"];var EXECUTION_CAPABILITY_AXES=["fsRead","fsWrite","networkEgress","processSpawn","externalMutationApproval"],SESSION_CAPABILITY_AXES=["resumeById","sessionDir","persistentStdin","structuredOutput"],AGENT_RUN_CAPABILITY_AXES=[...EXECUTION_CAPABILITY_AXES,...SESSION_CAPABILITY_AXES],EXECUTION_CAPABILITY_STATES=["enforced","available","unavailable","unknown"],EXECUTION_CAPABILITY_PROVENANCES=["native-known","operator-configured","unattested"],ExecutionCapabilityAttestationSchema=exports_external.object({state:exports_external.enum(EXECUTION_CAPABILITY_STATES),provenance:exports_external.enum(EXECUTION_CAPABILITY_PROVENANCES)}),ExecutionCapabilitiesSchema=exports_external.object({version:exports_external.literal(1),axes:exports_external.partialRecord(exports_external.enum(EXECUTION_CAPABILITY_AXES),ExecutionCapabilityAttestationSchema)}),EXECUTION_CAPABILITY_REQUIREMENTS=["available","enforced"],RequiresCapabilitiesSchema=exports_external.partialRecord(exports_external.enum(AGENT_RUN_CAPABILITY_AXES),exports_external.enum(EXECUTION_CAPABILITY_REQUIREMENTS)),executorAvailabilityOwnerSchema=exports_external.enum(["operator","quota","probe"]),executorDisabledObjectSchema=exports_external.object({owner:executorAvailabilityOwnerSchema,since:exports_external.string().refine(isRfc3339Timestamp,{message:"since must be an RFC 3339 timestamp"}),reason:exports_external.string().min(1)}),AgentExecutorConfigSchema=exports_external.object({name:exports_external.string().min(1),agent:exports_external.string().min(1),model:exports_external.string().min(1).optional(),tier:executorCapabilityTierSchema.optional(),executionCapabilities:ExecutionCapabilitiesSchema.optional(),disabled:exports_external.union([exports_external.boolean(),executorDisabledObjectSchema]).default(!1)});var AgentRoleConfigSchema=exports_external.object({tier:exports_external.enum(EXECUTOR_CAPABILITY_TIERS).optional(),stages:exports_external.array(exports_external.string().min(1)).min(1).optional()});var FleetMemberSchema=exports_external.object({id:exports_external.string().min(1).optional(),role:exports_external.enum(AGENT_ROLE_NAMES,{error:(issue2)=>Error(`Unknown role "${issue2.input}" — expected one of: ${AGENT_ROLE_NAMES.join(", ")}`)}).optional(),executor:exports_external.string().min(1).optional(),purpose:exports_external.string().optional(),enabled:exports_external.boolean().optional()}),FLEET_STRATEGIES=["rest","gtd"],FleetMemberEntrySchema=FleetMemberSchema.superRefine((member,ctx)=>{if(member.role===void 0&&member.executor===void 0)ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:"must declare a role or an executor — at least one is required"})}),AgentFleetSchema=exports_external.object({enabled:exports_external.boolean().default(!1),strategy:exports_external.enum(FLEET_STRATEGIES).default("rest"),orchestrator:exports_external.string().min(1).optional(),members:exports_external.array(FleetMemberEntrySchema).default([])});var AgentOutputConfigSchema=exports_external.object({"max-bytes":exports_external.number().int().positive().optional(),"max-lines":exports_external.number().int().positive().optional()}),AgentConfigSchema=exports_external.object({default:exports_external.string().optional(),executors:exports_external.array(AgentExecutorConfigSchema).optional(),roles:exports_external.record(exports_external.string(),AgentRoleConfigSchema).optional(),output:AgentOutputConfigSchema.optional(),sessionAffinity:exports_external.boolean().optional(),fleet:AgentFleetSchema.optional()}).superRefine((value,ctx)=>{for(let key of Object.keys(value.roles??{}))if(!AGENT_ROLE_NAMES.includes(key))ctx.addIssue({code:exports_external.ZodIssueCode.custom,path:["roles",key],message:`Unknown role "${key}" — expected one of: ${AGENT_ROLE_NAMES.join(", ")}`});let executors=value.executors,executorNames=new Set;if(executors!==void 0){let seen=new Set;for(let[index2,executor]of executors.entries()){if(seen.has(executor.name))ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:`Duplicate executor name: ${executor.name}`,path:["executors",index2,"name"]});if(executor.name==="inline"||executor.name==="auto")ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:`Executor name "${executor.name}" is reserved (the --agent selector value '${executor.name}' has fixed semantics); rename executor at index ${index2}.`,path:["executors",index2,"name"]});if(AGENT_ROLE_NAMES.includes(executor.name))ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:`Executor name "${executor.name}" collides with the role selector namespace ("${executor.name}"); rename executor at index ${index2}.`,path:["executors",index2,"name"]});seen.add(executor.name),executorNames.add(executor.name)}}}),RulesConfigSchema=exports_external.object({paths:exports_external.array(exports_external.string()).optional()}),WorkflowsConfigSchema=exports_external.object({paths:exports_external.array(exports_external.string()).optional()}),WorkflowConfigSchema=exports_external.object({hitlDecisionMaker:exports_external.boolean().optional(),decideDecisionMaker:exports_external.boolean().optional(),logRetentionDays:exports_external.number().int().positive().default(30)}),RedactionConfigSchema=exports_external.object({enabled:exports_external.boolean().optional()}),HistoryRefreshConfigSchema=exports_external.object({on_completion:exports_external.boolean().default(!1),debounce_ms:exports_external.number().int().min(1000).default(600000)}),HistoryConfigSchema=exports_external.object({refresh:HistoryRefreshConfigSchema.optional()}),VersionCarrierEntrySchema=exports_external.looseObject({type:exports_external.string().min(1)}),BuilderBumpVerConfigSchema=exports_external.object({tagVersionSeparator:exports_external.string().min(1).default("-v"),aggregatePackage:exports_external.string().min(1).optional(),publishWorkflow:exports_external.string().min(1).default("publish.yml"),releaseCommitType:exports_external.string().min(1).default("chore"),releaseCommitScope:exports_external.string().min(1).default("release"),ghRunListLimit:exports_external.number().int().positive().default(5),versionCarriers:exports_external.array(VersionCarrierEntrySchema).default([])}),BuilderConfigSchema=exports_external.object({"bump-ver":BuilderBumpVerConfigSchema.optional()});var bootstrapOptionsSchema=exports_external.object({options:exports_external.record(exports_external.string(),exports_external.unknown()).optional()}),spurConfigSchema=exports_external.object({version:exports_external.string().optional(),name:exports_external.string().optional(),bootstrap:bootstrapOptionsSchema.optional(),agent:AgentConfigSchema.optional(),rules:RulesConfigSchema.optional(),workflows:WorkflowsConfigSchema.optional(),workflow:WorkflowConfigSchema.optional(),redaction:RedactionConfigSchema.optional(),history:HistoryConfigSchema.optional(),builder:BuilderConfigSchema.optional(),tasks:tasksConfigSchema.optional(),features:featuresConfigSchema.optional()});var configSchema3=exports_external.object({database:exports_external.object({url:exports_external.string().default(DEFAULT_DATABASE_URL)}).default({url:DEFAULT_DATABASE_URL}),server:exports_external.object({port:exports_external.coerce.number().int().positive().default(3000),host:exports_external.string().default("localhost"),openBrowser:exports_external.boolean().default(!0),webDistPath:exports_external.string().nullable().default(null)}).default({port:3000,host:"localhost",openBrowser:!0,webDistPath:null}),telemetry:exports_external.object({enabled:exports_external.boolean().default(!1),endpoint:exports_external.string().optional()}).default({enabled:!1}),logging:exports_external.object({level:exports_external.enum(SPUR_LOG_LEVELS).default("info")}).default({level:"info"})});import{existsSync as existsSync2,readdirSync as readdirSync2,statSync as statSync3}from"node:fs";import{dirname as dirname2,join}from"node:path";var BUNDLED_CONFIG_DIRS=["config","spur-cli/config"],cachedRoot;function bundledConfigRoot(){if(cachedRoot!==void 0)return cachedRoot;let dir=import.meta.dirname;while(!0){for(let name of BUNDLED_CONFIG_DIRS){let candidate=join(dir,name);if(isBundledConfigDir(candidate))return cachedRoot=candidate,cachedRoot}let parent=dirname2(dir);if(parent===dir)break;dir=parent}return cachedRoot=null,cachedRoot}function isBundledConfigDir(candidate){return existsSync2(candidate)&&statSync3(candidate).isDirectory()&&existsSync2(join(candidate,"rules"))&&existsSync2(join(candidate,"workflows"))}init_dist2();var SPUR_CONFIG_DIR=".spur",SPUR_CONFIG_FILE="config.yaml",GLOBAL_CONFIG_FILE=join2(homedir(),".config","spur","config.yaml"),LOADER_DIR=dirname3(fileURLToPath3(import.meta.url)),nextEmbeddedSchemasId=1,embeddedSchemasIds=new WeakMap,spurConfigCache=new Map;function embeddedSchemasId(embeddedSchemas){if(embeddedSchemas===void 0)return"disk";let id=embeddedSchemasIds.get(embeddedSchemas);if(id===void 0)id=nextEmbeddedSchemasId,nextEmbeddedSchemasId+=1,embeddedSchemasIds.set(embeddedSchemas,id);return`embedded:${id}`}function cacheKey(configPath,opts,validateJsonSchema2){return[configPath,validateJsonSchema2?"schema":"zod",opts?.schemaManifestSpecifier??"@gobing-ai/spur/package.json",embeddedSchemasId(opts?.embeddedSchemas)].join("\x00")}function resolveSchemaSpecifier(specifier,manifestSpecifier){if(specifier===manifestSpecifier){let workspaceManifest=join2(LOADER_DIR,"..","..","..","apps","cli","package.json");if(existsSync3(workspaceManifest))return workspaceManifest}try{let resolved=import.meta.resolve(specifier);return resolved.startsWith("file:")?fileURLToPath3(resolved):resolved}catch{return specifier}}function resolveConfigLayers(cwd){let layers={};if(!(cwd===void 0&&getEnvVar("SPUR_SKIP_PROJECT_CONFIG")==="true")){let projectConfig=join2(cwd??process.cwd(),SPUR_CONFIG_DIR,SPUR_CONFIG_FILE);if(existsSync3(projectConfig))layers.project=projectConfig}if(getEnvVar("SPUR_SKIP_GLOBAL_CONFIG")!=="true"&&existsSync3(GLOBAL_CONFIG_FILE))layers.global=GLOBAL_CONFIG_FILE;return layers}var EMBEDDED_PREFIX="\x00embedded-spur";function makeEmbeddedReader(embeddedSchemas){return async function(path8){if(path8.startsWith(EMBEDDED_PREFIX)){let subpath=path8.slice(EMBEDDED_PREFIX.length+1),embedded=embeddedSchemas.get(subpath);if(embedded===void 0)throw Error(`No embedded schema registered for "${subpath}".`);return embedded}return createNodeFileSystem2().readFile(path8)}}async function loadSpurConfig(cwd,opts){let layers=resolveConfigLayers(cwd),projectRoot=resolve(cwd??process.cwd());if(assertNoLegacyFleetFile(projectRoot,layers.project),layers.global===void 0&&layers.project===void 0)return spurConfigSchema.parse({});let validateJsonSchema2=opts?.validateJsonSchema??getEnvVar("NODE_ENV")!=="test",mtimeOf=(path8)=>path8!==void 0?String(statSync4(path8).mtimeMs):"-",key=[cacheKey(layers.project??layers.global??"",opts,validateJsonSchema2),layers.global??"-",mtimeOf(layers.project),mtimeOf(layers.global)].join("\x00"),cached2=spurConfigCache.get(key);if(cached2!==void 0)return cached2;let promise2=loadMergedConfig(layers,opts,validateJsonSchema2);return spurConfigCache.set(key,promise2),promise2.catch(()=>spurConfigCache.delete(key)),promise2}async function resolveDecideDecisionMakerEnabled(cwd,opts){return(await loadSpurConfig(cwd,opts)).workflow?.decideDecisionMaker===!0}function assertNoRetiredTeamKey(parsed,layerPath,replacementFile){let agent=parsed.agent;if(!isPlainObject5(agent)||!("team"in agent))return;throw Error(`agent.team is no longer supported (${layerPath??"the merged config"}). Declare the project fleet under agent.fleet in ${replacementFile}.`)}function assertNoGlobalFleetSection(globalRaw,layerPath,projectFile){let agent=globalRaw.agent;if(!isPlainObject5(agent)||!("fleet"in agent))return;throw Error(`agent.fleet is not supported in the global config (${layerPath??SPUR_CONFIG_FILE}). Declare the project fleet under agent.fleet in ${projectFile} — the flock belongs to a project, not to the machine.`)}function assertNoLegacyFleetFile(projectRoot,projectConfigPath){let candidates=new Set([join2(projectRoot,SPUR_CONFIG_DIR,"fleet.json")]);if(projectConfigPath!==void 0)candidates.add(join2(dirname3(projectConfigPath),"fleet.json"));for(let legacyFile of candidates){if(!existsSync3(legacyFile))continue;throw Error(`The retired fleet declaration ${legacyFile} still exists. Move its members and orchestrator under agent.fleet in the project config, then delete the file.`)}}function projectConfigReplacement(layers){return layers.project??join2(SPUR_CONFIG_DIR,SPUR_CONFIG_FILE)}function schemaValidationContext(opts){let embeddedSchemas=opts?.embeddedSchemas,manifestSpecifier=opts?.schemaManifestSpecifier??"@gobing-ai/spur/package.json",resolve2=(specifier)=>{if(embeddedSchemas!==void 0&&specifier===manifestSpecifier)return`${EMBEDDED_PREFIX}/package.json`;return resolveSchemaSpecifier(specifier,manifestSpecifier)},fileSystem=embeddedSchemas?{readFile:makeEmbeddedReader(embeddedSchemas)}:void 0;return{resolve:resolve2,...fileSystem!==void 0?{fileSystem}:{}}}async function readRawYamlLayer(configPath,kind){let nodeFs=createNodeFileSystem2(),text3;try{text3=await nodeFs.readFile(nodeFs.resolve(configPath))}catch(error51){throw Error(`Failed to read ${kind} config ${configPath}: ${error51.message}`)}try{return $parse(text3)??{}}catch(error51){throw Error(`Failed to parse ${kind} config ${configPath}: ${error51.message}`)}}function isPlainObject5(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function executorNameOf(item){return isPlainObject5(item)&&typeof item.name==="string"?item.name:void 0}function isConcatPath(segments){return segments.length===2&&segments[0]==="rules"&&segments[1]==="paths"||segments.length===2&&segments[0]==="workflows"&&segments[1]==="paths"}function byKeyIdentityFor(segments){if(segments.length===2&&segments[0]==="agent"&&segments[1]==="executors")return executorNameOf;return}function concatUnique(globalItems,projectItems){let out=[...globalItems];for(let item of projectItems)if(!out.includes(item))out.push(item);return out}function mergeByKeyIdentity(globalItems,projectItems,identityOf,segments){let merged=[],indexByIdentity=new Map;for(let item of globalItems){let identity4=identityOf(item);if(identity4!==void 0&&!indexByIdentity.has(identity4))indexByIdentity.set(identity4,merged.length);merged.push(item)}let matchedProjectIdentities=new Set;for(let item of projectItems){let identity4=identityOf(item),existing=identity4===void 0||matchedProjectIdentities.has(identity4)?void 0:indexByIdentity.get(identity4);if(existing===void 0){merged.push(item);continue}if(identity4!==void 0)matchedProjectIdentities.add(identity4);let base2=merged[existing];merged[existing]=isPlainObject5(base2)&&isPlainObject5(item)?mergeDeep(base2,item,[...segments,existing]):item}return merged}function mergeDeep(globalValue,projectValue,segments){if(isPlainObject5(globalValue)&&isPlainObject5(projectValue)){let out={...globalValue};for(let[key,projectItem]of Object.entries(projectValue))out[key]=key in out?mergeDeep(out[key],projectItem,[...segments,key]):projectItem;return out}if(Array.isArray(globalValue)&&Array.isArray(projectValue)){if(isConcatPath(segments))return concatUnique(globalValue,projectValue);let identityOf=byKeyIdentityFor(segments);if(identityOf!==void 0)return mergeByKeyIdentity(globalValue,projectValue,identityOf,segments);return projectValue}return projectValue}function mergeSpurConfigLayers(globalRaw,projectRaw){return mergeDeep(globalRaw,projectRaw,[])}function formatZodPath(path8){return path8.map((segment,index2)=>typeof segment==="number"?`[${segment}]`:index2===0?segment:`.${segment}`).join("")}function parseViolationPath(path8){let segments=[];for(let part of path8.split(".")){let bracket=part.indexOf("["),key=bracket===-1?part:part.slice(0,bracket);if(key!=="")segments.push(key);if(bracket!==-1)for(let match of part.slice(bracket).matchAll(/\[(\d+)\]/g))segments.push(Number(match[1]))}return segments}function findItemByIdentity(node,identityOf,identity4){return Array.isArray(node)?node.find((entry)=>identityOf(entry)===identity4):void 0}function describeIssueProvenance(issuePath,merged,globalRaw,projectRaw){let g=globalRaw,p=projectRaw,m=merged,segments=[],parentG=globalRaw,parentP=projectRaw,identityPrefix="";for(let segment of issuePath){if(parentG=g,parentP=p,segments=[...segments,segment],typeof segment==="number"){let mergedItem=Array.isArray(m)?m[segment]:void 0,identityOf=byKeyIdentityFor(segments.slice(0,-1));if(identityOf!==void 0&&mergedItem!==void 0){let identity4=identityOf(mergedItem);if(identity4!==void 0)identityPrefix=`executor "${identity4}" `,g=findItemByIdentity(g,identityOf,identity4),p=findItemByIdentity(p,identityOf,identity4)}else g=Array.isArray(g)&&segment<g.length?g[segment]:void 0,p=Array.isArray(p)&&segment<p.length?p[segment]:void 0;m=mergedItem;continue}g=isPlainObject5(g)?g[segment]:void 0,p=isPlainObject5(p)?p[segment]:void 0,m=isPlainObject5(m)?m[segment]:void 0}let label;if(g!==void 0&&p!==void 0)label="set in both layers (project value wins)";else if(g!==void 0)label="from global layer";else if(p!==void 0)label="from project layer";else if(parentP!==void 0&&parentG===void 0)label="from project layer (key absent there)";else if(parentG!==void 0&&parentP===void 0)label="from global layer (key absent there)";else label="missing in both layers";return`${identityPrefix}${label}`}function parseMergedWithProvenance(merged,globalRaw,projectRaw,layers){try{return spurConfigSchema.parse(merged)}catch(error51){if(!(error51 instanceof ZodError))throw error51;let details=error51.issues.map((issue2)=>{let path8=issue2.path.filter((segment)=>typeof segment!=="symbol");return` ${formatZodPath(path8)}: ${issue2.message} (${describeIssueProvenance(path8,merged,globalRaw,projectRaw)})`}).join(`
1463
+ `);throw Error(`Spur config validation failed after merging global ${layers.global??"(absent)"} with project ${layers.project??"(absent)"}:
1464
+ ${details}`)}}function enrichSchemaViolationError(error51,merged,globalRaw,projectRaw,layers){let violations=error51.violations;if(!Array.isArray(violations))return error51;let details=violations.map((violation)=>{let v=violation,path8=typeof v.path==="string"?v.path:"(root)",message=typeof v.message==="string"?v.message:"schema violation",label=describeIssueProvenance(parseViolationPath(path8),merged,globalRaw,projectRaw);return` ${path8}: ${message} (${label})`}).join(`
1465
+ `);return Error(`Merged Spur config failed JSON Schema validation (global ${layers.global??"(absent)"} + project ${layers.project??"(absent)"}):
1466
+ ${details}`)}async function loadMergedConfig(layers,opts,validateJsonSchema2){let globalRaw=layers.global!==void 0?await readRawYamlLayer(layers.global,"global"):{},projectRaw=layers.project!==void 0?await readRawYamlLayer(layers.project,"project"):{},replacementFile=projectConfigReplacement(layers);if(layers.global!==void 0)assertNoRetiredTeamKey(globalRaw,layers.global,replacementFile),assertNoGlobalFleetSection(globalRaw,layers.global,replacementFile);if(layers.project!==void 0)assertNoRetiredTeamKey(projectRaw,layers.project,replacementFile);let merged=mergeSpurConfigLayers(globalRaw,projectRaw);if(validateJsonSchema2){let source=layers.project??layers.global??"";try{await validateDeclaredJsonSchema(merged,source,schemaValidationContext(opts))}catch(error51){throw enrichSchemaViolationError(error51,merged,globalRaw,projectRaw,layers)}}return parseMergedWithProvenance(merged,globalRaw,projectRaw,layers)}init_dist6();init_dist2();var EMBEDDED_SCHEMA_PREFIX="\x00embedded-spur",SPUR_SCHEMA_MANIFEST="@gobing-ai/spur/package.json";function normalizeLayerPath(cwd,path8){return resolve2(cwd,path8)}function workflowLayers(opts){let sharedRoot=opts.sharedRoot!==void 0?opts.sharedRoot:bundledConfigRoot(),sharedPath=sharedRoot!==null?normalizeLayerPath(opts.cwd,join3(sharedRoot,"workflows")):null,layers=[],seen=new Set,add=(id,path8)=>{if(seen.has(path8))return;seen.add(path8),layers.push({id,path:path8})};add("project",normalizeLayerPath(opts.cwd,join3(opts.cwd,".spur","workflows")));for(let entry of opts.registered){if(sharedPath!==null&&normalizeLayerPath(opts.cwd,entry)===sharedPath)continue;add("registered",normalizeLayerPath(opts.cwd,entry))}if(sharedPath!==null)add("shared",sharedPath);return layers}function createEmbeddedSchemaOptions(embedded){if(embedded===void 0||embedded.size===0)return;let nodeFs=createNodeFileSystem2();return{resolve:(specifier)=>specifier===SPUR_SCHEMA_MANIFEST?`${EMBEDDED_SCHEMA_PREFIX}/package.json`:specifier,fileSystem:{readFile:async(path8)=>{if(!path8.startsWith(EMBEDDED_SCHEMA_PREFIX))return nodeFs.readFile(path8);let subpath=path8.slice(EMBEDDED_SCHEMA_PREFIX.length+1),text3=embedded.get(subpath);if(text3===void 0)throw Error(`No embedded schema registered for "${subpath}".`);return text3}}}}async function readWorkflowNameFast(fs2,filePath){try{let text3=await fs2.readFile(filePath),parsed=$parse(text3);return typeof parsed?.name==="string"?parsed.name:null}catch{return null}}async function scanWorkflowByName(cwd,name,registered){let fs2=createNodeFileSystem2();for(let layer of workflowLayers({cwd,registered}))try{let files=(await fs2.readDir(layer.path)).filter((f)=>f.endsWith(".yaml")||f.endsWith(".yml"));for(let f of files){let abs=join3(layer.path,f);if(await readWorkflowNameFast(fs2,abs)===name)return{path:abs,source:layer.id}}}catch{}return null}function resolveWorkflowFile(cwd,file2){let fs2=createNodeFileSystem2(),projectPath=resolve2(cwd,file2);if(fs2.exists(projectPath))return{path:projectPath,source:"project"};let isYaml=file2.endsWith(".yaml")||file2.endsWith(".yml"),base2=basename(file2);if(!isAbsolute(file2)){let withYaml=isYaml?file2:`${file2}.yaml`,projectSpur=resolve2(cwd,".spur","workflows",withYaml);if(fs2.exists(projectSpur))return{path:projectSpur,source:"project"};if(!isYaml){let projectDirect=resolve2(cwd,`${file2}.yaml`);if(fs2.exists(projectDirect))return{path:projectDirect,source:"project"};let projectSpurPipeline=resolve2(cwd,".spur","workflows",`${file2}-pipeline.yaml`);if(fs2.exists(projectSpurPipeline))return{path:projectSpurPipeline,source:"project"};let projectDirectPipeline=resolve2(cwd,`${file2}-pipeline.yaml`);if(fs2.exists(projectDirectPipeline))return{path:projectDirectPipeline,source:"project"}}}let bundledRoot=bundledConfigRoot();if(bundledRoot!==null){let sharedName=isYaml?base2:`${base2}.yaml`,sharedPath=join3(bundledRoot,"workflows",sharedName);if(fs2.exists(sharedPath))return{path:sharedPath,source:"shared"};if(!isYaml){let sharedPipeline=join3(bundledRoot,"workflows",`${base2}-pipeline.yaml`);if(fs2.exists(sharedPipeline))return{path:sharedPipeline,source:"shared"};let sharedLiteral=join3(bundledRoot,"workflows",base2);if(fs2.exists(sharedLiteral))return{path:sharedLiteral,source:"shared"}}return{path:null,probed:[projectPath,sharedPath]}}return{path:null,probed:[projectPath,null]}}async function resolveWorkflowDefinition(cwd,fileOrName,options={}){let registered=options.registered??[],resolved=(basename(fileOrName)===fileOrName&&!/\.ya?ml$/.test(fileOrName)&&!createNodeFileSystem2().exists(resolve2(cwd,fileOrName))?await scanWorkflowByName(cwd,fileOrName,registered):null)??resolveWorkflowFile(cwd,fileOrName);if(resolved.path===null){let scanned=await scanWorkflowByName(cwd,fileOrName,registered);if(scanned!==null)resolved=scanned;else{let[probedProject,probedShared]=resolved.probed;throw Error(`Workflow not found: ${probedProject}${probedShared!==null?` (shared: ${probedShared})`:""}`)}}let embedded=createEmbeddedSchemaOptions(options.embeddedSchemas),workflow=await loadWorkflowDef(resolved.path,{validateSchema:options.validateSchema!==!1,...embedded!==void 0?embedded:{}});if(workflow.version==="")throw Error(`Invalid workflow definition ${resolved.path}: root "version" is an empty string. Omit the field for an unversioned definition, or give it a non-empty literal.`);let digest=computeDefinitionDigest(workflow);return{path:resolved.path,workflow,digest,layer:resolved.source}}var TERMINAL_REASONS=["done","paused-operator","failed-check","failed-agent","failed-timeout","failed-guard","cancelled","interrupted","retry-exhausted"];function isTerminalReason(value){return TERMINAL_REASONS.includes(value)}function classifyTerminalReason({status,engineReason,actionKind,errorText}){if(engineReason!==void 0&&engineReason!==null&&isTerminalReason(engineReason))return engineReason;if(status==="interrupted")return"interrupted";if(status==="paused")return"paused-operator";if(status==="done")return"done";if(engineReason==="no-passing-transition"||engineReason==="no-passing-edge")return"failed-guard";if(engineReason==="iteration-bound-exceeded")return"retry-exhausted";if(errorText!==void 0&&errorText!==null&&/timeout/i.test(errorText))return"failed-timeout";if(actionKind==="agent.run")return"failed-agent";return"failed-check"}var UNPERSISTED_PREFIX="trace-unpersisted:";class RunRowNotFoundError extends Error{runId;constructor(runId){super(`run row not found: ${runId}`);this.name="RunRowNotFoundError",this.runId=runId}}class WorkflowActionTraceWriter{inner;recordFailure;db;boundaries=new Map;constructor(inner,recordFailure,db2){this.inner=inner;this.recordFailure=recordFailure;this.db=db2}async saveActionStart(runId,node,kind,options){let outcome=await this.guard("action.start",{runId,node,kind},()=>this.inner.saveActionStart(runId,node,kind,options));if(!outcome.ok){let syntheticId=`${UNPERSISTED_PREFIX}${crypto.randomUUID()}`;return this.boundaries.set(syntheticId,{runId,node,kind}),this.lastStart={runId,node,kind},syntheticId}return this.boundaries.set(outcome.value,{runId,node,kind}),this.lastStart={runId,node,kind},outcome.value}lastStart;async saveActionFinalize(actionId,status,durationMs,ok,kind,result,redactor){let origin2=this.boundaries.get(actionId)??this.lastStart;await this.guard("action.finish",{runId:origin2?.runId??"",node:origin2?.node,kind},()=>this.inner.saveActionFinalize(actionId,status,durationMs,ok,kind,result,redactor)),this.boundaries.delete(actionId)}async finalizeRun(runId,status,completedAt,fence,reason){await this.inner.finalizeRun(runId,status,completedAt,fence,reason===void 0?void 0:classifyTerminalReason({status,engineReason:reason,errorText:reason}))}async claimRunOwnership(runId,owner,expectedStatuses){return this.inner.claimRunOwnership(runId,owner,expectedStatuses)}async interruptRun(runId,reason){return this.inner.interruptRun(runId,reason)}async recordAction(boundary2){let start=await this.guard("action.start",{runId:boundary2.runId,node:boundary2.node,kind:boundary2.kind},()=>this.inner.saveActionStart(boundary2.runId,boundary2.node,boundary2.kind));if(!start.ok)return start;let finish=await this.guard("action.finish",{runId:boundary2.runId,node:boundary2.node,kind:boundary2.kind},()=>this.inner.saveActionFinalize(start.value,boundary2.status,boundary2.durationMs,boundary2.ok,boundary2.kind,boundary2.result,boundary2.redactor));if(!finish.ok)return finish;return await this.backdateStart(start.value,boundary2),{ok:!0,actionId:start.value}}async backdateStart(actionId,boundary2){let db2=this.db;if(db2===void 0||boundary2.durationMs<=0)return;await this.guard("action.backdate",{runId:boundary2.runId,node:boundary2.node,kind:boundary2.kind},async()=>{let dao2=new ActionRunDao(db2),completedAt=await dao2.completedAtById(actionId);if(completedAt===null)return;let startedAt=new Date(new Date(completedAt).getTime()-boundary2.durationMs).toISOString();await dao2.setStartedAt(actionId,startedAt)})}async closeRun(runId,status,completedAt,reason){if(await this.inner.loadRun(runId)===void 0)throw new RunRowNotFoundError(runId);return await this.inner.finalizeRun(runId,status,completedAt??new Date().toISOString(),void 0,reason===void 0?void 0:classifyTerminalReason({status,engineReason:reason,errorText:reason})),{ok:!0}}async guard(operation,context4,emit){try{return{ok:!0,value:await emit()}}catch(error51){let failure={operation,runId:context4.runId,...context4.node!==void 0?{node:context4.node}:{},...context4.kind!==void 0?{kind:context4.kind}:{},error:error51 instanceof Error?error51.message:String(error51),at:new Date().toISOString()};try{this.recordFailure?.(failure)}catch{}return{ok:!1,failure}}}createRun(record2){return this.inner.createRun(record2)}savePhase(runId,phase,status){return this.inner.savePhase(runId,phase,status)}saveTransition(runId,from,to,trigger){return this.inner.saveTransition(runId,from,to,trigger)}saveWorkflowState(runId,state,data){return this.inner.saveWorkflowState(runId,state,data)}commitTransition(runId,from,to,trigger,state,data,phase){return this.inner.commitTransition(runId,from,to,trigger,state,data,phase)}loadRun(runId){return this.inner.loadRun(runId)}listRuns(){return this.inner.listRuns()}findRunByKey(workflowName,externalKey){return this.inner.findRunByKey(workflowName,externalKey)}createOrAttachRun(record2){return this.inner.createOrAttachRun(record2)}reseedRun(runId,newState){return this.inner.reseedRun(runId,newState)}loadCurrentState(runId){return this.inner.loadCurrentState(runId)}loadLatestStateSnapshot(runId){return this.inner.loadLatestStateSnapshot(runId)}listPausedRuns(options){return this.inner.listPausedRuns(options)}}function createWorkflowActionTraceWriter(db2,recordFailure){return new WorkflowActionTraceWriter(new DbWorkflowPersistenceAdapter(db2),recordFailure,db2)}var TRIPWIRE_CATALOG=Object.freeze({"retry-exhausted":{id:"retry-exhausted",version:1,response:"fail",nextDecision:"Retries are exhausted; an operator must decide to escalate, extend the retry policy, or fail the stage. No further automatic retry is permitted."},"hard-budget":{id:"hard-budget",version:1,response:"fail",nextDecision:"An operator must raise the declared budget or trim the stage scope, then re-run the action; the run stays failed until then."},"capability-denied":{id:"capability-denied",version:1,response:"fail",nextDecision:"An operator must attest the executor capabilities in agent config or lower the stage requiresCapabilities, then re-run the action."},"proof-invalidated":{id:"proof-invalidated",version:1,response:"fail",nextDecision:"An operator must restore the proof inputs or re-establish the verdict (re-verify) before record; recording against a changed tree is blocked."},"output-drop":{id:"output-drop",version:1,response:"continue",nextDecision:"The dispatch completed but its captured evidence is incomplete (bounded relay dropped chunks). Inspect the session/trace for full output if the result is contested."}});var SHELL_METACHARACTERS=/[;&|<>$`(){}[\]!*?~#\n\r"']/;function splitLaunchCommand(value,label){if(SHELL_METACHARACTERS.test(value))return{error:`${label} must not contain shell metacharacters (got ${value})`};let tokens=value.trim().split(/\s+/).filter((t)=>t.length>0),command=tokens[0];if(command===void 0)return{error:`Action option ${label.slice(label.indexOf('"'))} must be a non-empty string`};return{command,leadingArgs:tokens.slice(1)}}import crypto4 from"node:crypto";import{tmpdir}from"node:os";import{dirname as dirname4,join as join4,resolve as resolve3,sep}from"node:path";init_dist6();class ProofCaptureError extends Error{stderr;constructor(message,stderr){super(message);this.stderr=stderr;this.name="ProofCaptureError"}}var TASK_SPEC_SECTIONS=["Background","Requirements","Acceptance Criteria","Design","Plan"],CANONICAL_TASK_HEADING_RE=/^##[ \t]+(\d+)\.[ \t]+(\S.*)$/m;function taskDocumentShapeError(content){let doc2=MarkdownDocument.parse(content,"task"),heading=CANONICAL_TASK_HEADING_RE.exec(doc2.bodyWithoutFrontmatter);if(heading===null)return"no canonical task heading (`## <WBS>. <title>`) was found";if((heading[2]??"").trim()==="")return`the canonical task heading for WBS ${heading[1]} has an empty title`;if(TASK_SPEC_SECTIONS.filter((section)=>doc2.hasSection(section)).length===0)return`no task specification section (${TASK_SPEC_SECTIONS.join(", ")}) was found`;return null}async function readProofInputContents(fileSystem=createNodeFileSystem2(),workdir,options){for(let name of["taskFile","featureFile"]){let value=options[name];if(value!==void 0&&typeof value!=="string")return{ok:!1,error:`${name} must be a string when supplied (got ${typeof value})`}}let readOne=async(name)=>{let raw=name==="taskFile"?options.taskFile:options.featureFile;if(raw===void 0||raw==="")return{};let workdirAbs=resolve3(workdir),resolved=resolve3(workdirAbs,raw);if(!(resolved===workdirAbs||resolved.startsWith(`${workdirAbs}${sep}`)))return{error:`${name} must resolve under the workflow workdir (${workdirAbs}): ${raw}`};let stat;try{stat=await fileSystem.stat(resolved)}catch(error51){return{error:`${name} could not be inspected: ${error51.message}`}}if(stat===null)return{error:`${name} does not exist: ${raw} (resolved ${resolved}) — an explicitly supplied spec must be readable, not silently omitted`};if(!stat.isFile())return{error:`${name} is not a regular file: ${resolved}`};let content;try{content=await fileSystem.readFile(resolved)}catch(error51){return{error:`${name} is not readable: ${error51.message}`}}if(name==="taskFile"){let shapeError=taskDocumentShapeError(content);if(shapeError!==null)return{error:`taskFile is not a task document: ${raw} (resolved ${resolved}) — ${shapeError}. Supply the task specification markdown itself: a \`## <WBS>. <title>\` heading plus at least one of ${TASK_SPEC_SECTIONS.join(", ")}. A file containing only a path is not dereferenced.`}}return{content}},task=await readOne("taskFile");if(task.error!==void 0)return{ok:!1,error:task.error};let feature=await readOne("featureFile");if(feature.error!==void 0)return{ok:!1,error:feature.error};return{ok:!0,...task.content!==void 0?{taskContent:task.content}:{},...feature.content!==void 0?{featureContent:feature.content}:{}}}var DEFAULT_EXCLUDE_GLOBS=["docs/tasks*","docs/features*"];async function createGitAlternateTree(cwd,excludeGlobs=DEFAULT_EXCLUDE_GLOBS,executor=new NodeProcessExecutor2,fs2=createNodeFileSystem2()){let indexFile=join4(tmpdir(),`spur-proof-fingerprint-${crypto4.randomUUID()}.index`);try{await fs2.ensureDir(dirname4(indexFile));let env2=Object.fromEntries(Object.entries(getEnvVars()).filter((entry)=>entry[1]!==void 0));env2.GIT_INDEX_FILE=indexFile;let common4={cwd,env:env2,forceBuffered:!0,rejectOnError:!1},read=await executor.run({command:"git",args:["read-tree","HEAD"],...common4});if(read.exitCode!==0)throw new ProofCaptureError(`git read-tree HEAD failed with exit code ${read.exitCode}`,read.stderr);let excludes=excludeGlobs.map((glob)=>`:(exclude)${glob}`),add=await executor.run({command:"git",args:["add","-A","--",".",...excludes],...common4});if(add.exitCode!==0)throw new ProofCaptureError(`git add -A failed with exit code ${add.exitCode}`,add.stderr);let tree=await executor.run({command:"git",args:["write-tree"],...common4});if(tree.exitCode!==0)throw new ProofCaptureError(`git write-tree failed with exit code ${tree.exitCode}`,tree.stderr);return tree.stdout.trim()}catch(error51){if(error51 instanceof ProofCaptureError)throw error51;throw new ProofCaptureError(`git alternate-tree capture threw: ${error51.message}`)}finally{if(await fs2.exists(indexFile))try{await fs2.deleteFile(indexFile)}catch{}}}function extractTaskProofData(content){let doc2=MarkdownDocument.parse(content,"task"),fm=doc2.frontmatterData??{},wbs=typeof fm.wbs==="string"?fm.wbs:void 0,name=typeof fm.name==="string"?fm.name:void 0,feature_id=typeof fm.feature_id==="string"?fm.feature_id:void 0,depends_on;if(Array.isArray(fm.depends_on))depends_on=fm.depends_on.filter((d)=>typeof d==="string");else if(Array.isArray(fm.dependencies))depends_on=fm.dependencies.filter((d)=>typeof d==="string");let sections={},taskSections=["Background","Requirements","Acceptance Criteria","Design","Plan"];for(let sec of taskSections)if(doc2.hasSection(sec)){let body=doc2.getSection(sec);if(body!==null)sections[sec]=body.trim()}return{...wbs!==void 0?{wbs}:{},...name!==void 0?{name}:{},...feature_id!==void 0?{feature_id}:{},...depends_on!==void 0?{depends_on}:{},sections}}function extractFeatureProofData(content){let doc2=MarkdownDocument.parse(content,"feature"),fm=doc2.frontmatterData??{},id=typeof fm.id==="string"?fm.id:void 0,name=typeof fm.name==="string"?fm.name:void 0,sections={},featureSections=["Goal","Scope","Acceptance Criteria"];for(let sec of featureSections)if(doc2.hasSection(sec)){let body=doc2.getSection(sec);if(body!==null)sections[sec]=body.trim()}return{...id!==void 0?{id}:{},...name!==void 0?{name}:{},sections}}async function computeProofInputFingerprint(options={}){let cwd=options.cwd??process.cwd(),gitTree=await createGitAlternateTree(cwd,options.excludeGlobs??DEFAULT_EXCLUDE_GLOBS,options.processExecutor,options.fileSystem),task;if(options.taskContent!==void 0)task=extractTaskProofData(options.taskContent);let feature;if(options.featureContent!==void 0)feature=extractFeatureProofData(options.featureContent);let canonical=canonicalJsonStringify({gitTree,...task!==void 0?{task}:{},...feature!==void 0?{feature}:{},...options.learningsContent!==void 0?{learnings:options.learningsContent}:{}});return`sha256:${crypto4.createHash("sha256").update(canonical,"utf8").digest("hex")}`}var ProofInputFingerprint={compute:computeProofInputFingerprint};init_zod();var VERDICT_AGGREGATES=["PASS","PARTIAL","FAIL","UNKNOWN"],ROW_STATUSES=["MET","PARTIAL","UNMET","N/A"],CHECK_SEVERITIES=["blocker","major","minor","advisory"],verdictSchema=exports_external.string().transform((v,ctx)=>{let up=v.toUpperCase();if(!VERDICT_AGGREGATES.includes(up))return ctx.addIssue({code:"custom",message:`invalid verdict "${v}" (expected PASS|PARTIAL|FAIL|UNKNOWN)`}),"UNKNOWN";return up}),coverageRowSchema=exports_external.object({id:exports_external.string().optional(),scenario:exports_external.string().optional(),status:exports_external.string(),evidenceType:exports_external.string().optional(),evidence:exports_external.string().optional()}).superRefine((r,ctx)=>{if(r.id!==void 0&&r.scenario!==void 0&&r.id!==r.scenario)ctx.addIssue({code:"custom",message:`id/scenario conflict ("${r.id}" vs "${r.scenario}")`,path:["scenario"]});if(!ROW_STATUSES.includes(r.status.toUpperCase()))ctx.addIssue({code:"custom",message:`invalid row status "${r.status}"`,path:["status"]})}).transform((r)=>({id:r.id??r.scenario??"",status:r.status.toUpperCase(),evidenceType:r.evidenceType??"",evidence:r.evidence??""})),checkSchema=exports_external.object({name:exports_external.string().optional(),check:exports_external.string().optional(),id:exports_external.string().optional(),status:exports_external.string(),evidence:exports_external.string().optional().default(""),severity:exports_external.enum(CHECK_SEVERITIES).optional()}).superRefine((c3,ctx)=>{if(c3.name===void 0&&c3.check===void 0&&c3.id===void 0)ctx.addIssue({code:"custom",message:"check row needs one of name/check/id",path:["name"]})}).transform((c3)=>({name:c3.name??c3.check??c3.id??"",status:c3.status,evidence:c3.evidence,severity:c3.severity})),verifyVerdictSchema=exports_external.object({wbs:exports_external.string().optional().default(""),verdict:verdictSchema,requirements:exports_external.array(coverageRowSchema).optional().default([]),acceptanceCriteria:exports_external.array(coverageRowSchema).optional().default([]),checks:exports_external.array(checkSchema).optional().default([]),source:exports_external.string().optional(),pipelineRunId:exports_external.string().optional(),recordedAt:exports_external.string().optional()});var field=(path8,label)=>({path:path8,label}),SOURCE_PROFILES={planning:{producerPackage:"spur",subsystem:"planning",remediationKind:"prefix-filter"},queue:{producerPackage:"@gobing-ai/ts-infra",subsystem:"job-queue",remediationKind:"prefix-filter"},scheduler:{producerPackage:"@gobing-ai/ts-infra",subsystem:"scheduler",remediationKind:"prefix-filter"},message:{producerPackage:"spur",subsystem:"coordination-messaging",remediationKind:"prefix-filter"},process:{producerPackage:"@gobing-ai/ts-runtime",subsystem:"process-executor",remediationKind:"prefix-filter"},workflow:{producerPackage:"@gobing-ai/ts-dual-workflow-engine",subsystem:"workflow",remediationKind:"workflow-trace"},rule:{producerPackage:"@gobing-ai/ts-rule-engine",subsystem:"rule-engine",remediationKind:"rule-trace"},agent:{producerPackage:"@gobing-ai/ts-ai-runner",subsystem:"agent-runner",remediationKind:"prefix-filter"},history:{producerPackage:"spur",subsystem:"history",remediationKind:"prefix-filter"},bus:{producerPackage:"@gobing-ai/ts-infra",subsystem:"event-bus",remediationKind:"prefix-filter"},api:{producerPackage:"spur",subsystem:"http-api",remediationKind:"prefix-filter"}};function at(data,path8){if(data===null)return;let current=data;for(let segment of path8.split(".")){if(current===null||typeof current!=="object"||Array.isArray(current))return;current=current[segment]}return current}function s2(data,...paths){for(let path8 of paths){let value=at(data,path8);if(typeof value==="string"&&value.length>0)return value}return}function n2(data,...paths){for(let path8 of paths){let value=at(data,path8);if(typeof value==="number"&&Number.isFinite(value))return String(value);if(typeof value==="boolean")return String(value)}return}function entityId(input){return s2(input.data,"entity.id")??input.correlation.entityId??""}function looksLikeOpaqueId(value){if(typeof value!=="string")return!1;let v=value.trim();if(v==="")return!1;if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v))return!0;if(/^live[-_][a-z0-9._-]+$/i.test(v))return!0;if(/^(?:eventId|rowId|runId|executionId|actionId)$/i.test(v))return!0;return!1}function humanWorkflowTitle(input){let raw=s2(input.data,"workflowName")??s2(input.data,"workflow");if(raw!==void 0&&!looksLikeOpaqueId(raw))return(raw.split("/").pop()?.replace(/\.(?:ya?ml|json)$/i,"")??raw).replace(/[._-]+$/,"");return""}function humanStepLabel(data){let label=s2(data,"nodeLabel")??s2(data,"stepName")??s2(data,"step");if(label!==void 0&&!looksLikeOpaqueId(label))return label;let node=s2(data,"node");if(node!==void 0&&!looksLikeOpaqueId(node))return node;return}function derivedFrom(...paths){return{support:"derived",derive:({data})=>s2(data,...paths)}}function derivedFromValue(...paths){return{support:"derived",derive:({data})=>n2(data,...paths)??s2(data,...paths)}}var unsupported={support:"unsupported"};function baseEvent(name,source,renderer,payloadPolicy="metadata-only",tier="default",producer){return{name,source,tier,payloadPolicy,renderer,...producer!==void 0?{producer}:{}}}var BASE_CATALOG=[baseEvent("task.created","planning","planning"),baseEvent("task.updated","planning","planning"),baseEvent("task.transitioned","planning","planning"),baseEvent("feature.created","planning","planning"),baseEvent("feature.updated","planning","planning"),baseEvent("feature.transitioned","planning","planning"),baseEvent("queue.consumer.started","queue","queue"),baseEvent("queue.consumer.stopped","queue","queue"),baseEvent("queue.job.enqueued","queue","queue"),baseEvent("queue.job.started","queue","queue"),baseEvent("queue.job.completed","queue","queue"),baseEvent("queue.job.failed","queue","queue"),baseEvent("queue.job.retrying","queue","queue"),baseEvent("queue.stats","queue","queue"),baseEvent("scheduler.job.executed","scheduler","scheduler"),baseEvent("message.sent","message","message"),baseEvent("message.replied","message","message"),baseEvent("process.spawned","process","process"),baseEvent("process.exited","process","process"),baseEvent("process.stopped","process","process"),baseEvent("process.started","process","process"),baseEvent("agent.invoke.start","agent","agent"),baseEvent("agent.invoke.exit","agent","agent"),baseEvent("agent.invoke.escalated","agent","agent","metadata-only","default",{package:"spur",subsystem:"agent-runner"}),baseEvent("agent.invoke.exhausted","agent","agent","metadata-only","default",{package:"spur",subsystem:"agent-runner"}),baseEvent("agent.started","agent","agent"),baseEvent("agent.stopped","agent","agent"),baseEvent("agent.message.sent","agent","agent"),baseEvent("strategy.changed","agent","agent","metadata-only","default",{package:"spur",subsystem:"fleet-strategy"}),baseEvent("fleet.capacity.changed","agent","agent","metadata-only","default",{package:"spur",subsystem:"write-slot"}),baseEvent("task.assigned","planning","planning"),baseEvent("history.import.completed","history","history-import"),baseEvent("history.analyze.completed","history","history-analyze"),baseEvent("history.daily.failed","history","history-daily"),baseEvent("history.refresh.enqueued","history","history-refresh"),baseEvent("rule.run.start","rule","rule"),baseEvent("rule.eval.start","rule","rule"),baseEvent("rule.eval.done","rule","rule"),baseEvent("rule.eval.error","rule","rule"),baseEvent("rule.run.done","rule","rule"),baseEvent("workflow.run.started","workflow","workflow-run"),baseEvent("workflow.run.done","workflow","workflow-run"),baseEvent("workflow.run.failed","workflow","workflow-run"),baseEvent("workflow.run.finalized","workflow","workflow-run"),baseEvent("workflow.escalation.created","workflow","workflow-run","redacted"),baseEvent("workflow.escalation.projection_failed","workflow","workflow-run","metadata-only"),baseEvent("workflow.run.paused","workflow","workflow-run"),baseEvent("workflow.run.resumed","workflow","workflow-run"),baseEvent("workflow.run.reseeded","workflow","workflow-run"),baseEvent("workflow.node.enter","workflow","workflow-phase"),baseEvent("workflow.phase","workflow","workflow-phase"),baseEvent("workflow.node.transition","workflow","workflow-transition"),baseEvent("workflow.transition","workflow","workflow-transition"),baseEvent("workflow.transition.requested","workflow","workflow-transition","metadata-only","diagnostic"),baseEvent("workflow.transition.denied","workflow","workflow-transition","metadata-only","diagnostic"),baseEvent("workflow.action.started","workflow","workflow-action"),baseEvent("workflow.action.finished","workflow","workflow-action"),baseEvent("workflow.action.failed_continue","workflow","workflow-action"),baseEvent("workflow.guard.evaluated","workflow","workflow-guard","metadata-only","diagnostic"),baseEvent("workflow.hitl.ask","workflow","workflow-hitl","redacted"),baseEvent("workflow.hitl.response","workflow","workflow-hitl","redacted"),baseEvent("workflow.hitl.note","workflow","workflow-hitl","redacted"),baseEvent("workflow.custom","workflow","workflow-custom"),baseEvent("workflow.agent","workflow","workflow-agent","redacted","diagnostic"),baseEvent("workflow.steering","workflow","workflow-steering","redacted"),baseEvent("api.request.error","api","api"),baseEvent("bus.emit.done","bus","bus","metadata-only","diagnostic"),baseEvent("bus.emit.noop","bus","bus","metadata-only","diagnostic"),baseEvent("bus.handler.error","bus","bus","metadata-only","diagnostic"),baseEvent("bus.handler.async.enqueued","bus","bus","metadata-only","diagnostic")],SYSTEM_EVENT_PRESENTERS={"task.created":{description:"A task file was created with a new WBS id.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity")],summary:({data,correlation})=>`[task] ${entityId({data,correlation})} created`,outcome:unsupported},"task.updated":{description:"An existing task file was updated in place, naming the section that changed.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity"),field("field","Field"),field("data.mutation.name","Section"),field("data.after","After"),field("data.diff","Diff")],summary:({data,correlation})=>{let section=s2(data,"data.mutation.name"),id=entityId({data,correlation});return section!==void 0?`[task] ${section}`:`[task] ${id||"updated"}`},outcome:unsupported},"task.transitioned":{description:"A task moved between lifecycle states, naming both the previous and new status.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity"),field("from","From"),field("to","To")],summary:({data,correlation})=>{let id=entityId({data,correlation}),from=s2(data,"from"),to=s2(data,"to");return from!==void 0&&to!==void 0?`[task] ${id} : ${from} -> ${to}`:`[task] ${id} transitioned`},outcome:{support:"derived",derive:({data})=>s2(data,"to")}},"feature.created":{description:"A feature file was created with a new feature id.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity")],summary:({data,correlation})=>`[feature] ${entityId({data,correlation})} created`,outcome:unsupported},"feature.updated":{description:"An existing feature file was updated in place, naming the section that changed.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity"),field("field","Field"),field("data.mutation.name","Section"),field("data.after","After"),field("data.diff","Diff")],summary:({data,correlation})=>{let section=s2(data,"data.mutation.name"),id=entityId({data,correlation});return section!==void 0?`[feature] ${section}`:`[feature] ${id||"updated"}`},outcome:unsupported},"feature.transitioned":{description:"A feature moved between lifecycle states, naming both the previous and new status.",fields:[field("entity.kind","Entity kind"),field("entity.id","Entity"),field("from","From"),field("to","To")],summary:({data,correlation})=>{let id=entityId({data,correlation}),from=s2(data,"from"),to=s2(data,"to");return from!==void 0&&to!==void 0?`[feature] ${id} : ${from} -> ${to}`:`[feature] ${id} transitioned`},outcome:{support:"derived",derive:({data})=>s2(data,"to")}},"queue.consumer.started":{description:"The configured queue consumer began polling its named queue.",fields:[field("queueName","Queue"),field("startedAt","Started"),field("pollInterval","Poll interval"),field("batchSize","Batch size"),field("maxConcurrency","Max concurrency"),field("visibilityTimeout","Visibility timeout")],summary:({data})=>{let name=s2(data,"queueName");return name!==void 0?`[queue] ${name} : consumer started`:"[queue] consumer started"},outcome:{support:"derived",derive:({data})=>at(data,"startedAt")!==void 0?"running":void 0}},"queue.consumer.stopped":{description:"The queue consumer stopped, reporting whether it drained in-flight work.",fields:[field("queueName","Queue"),field("stoppedAt","Stopped"),field("drainTimeoutMs","Drain timeout"),field("inFlightAtStop","In flight"),field("drained","Drained")],summary:({data})=>{let name=s2(data,"queueName");return name!==void 0?`[queue] ${name} : consumer stopped`:"[queue] consumer stopped"},outcome:{support:"derived",derive:({data})=>{let drained=at(data,"drained");if(drained===!0)return"drained";if(drained===!1)return"timeout";return}}},"queue.job.enqueued":{description:"A job was enqueued onto the job queue for later processing.",fields:[field("jobId","Job"),field("type","Type"),field("nextRetryAt","Next retry")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} enqueued`:"[queue] job enqueued"},outcome:unsupported},"queue.job.started":{description:"A queued job handler began executing (job identity and phase anchor).",fields:[field("jobId","Job"),field("type","Type"),field("name","Name")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} started`:"[queue] job started"},outcome:unsupported},"queue.job.completed":{description:"A queued job finished successfully with its attempt and duration.",fields:[field("jobId","Job"),field("type","Type"),field("attempt","Attempt"),field("durationMs","Duration (ms)")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} completed`:"[queue] job completed"},outcome:unsupported},"queue.job.failed":{description:"A queued job exhausted its attempts and failed with an error.",fields:[field("jobId","Job"),field("type","Type"),field("attempt","Attempt"),field("maxRetries","Max retries"),field("durationMs","Duration (ms)"),field("error","Error")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} failed`:"[queue] job failed"},outcome:derivedFrom("error")},"queue.job.retrying":{description:"A queued job failed once and is scheduled for another attempt.",fields:[field("jobId","Job"),field("type","Type"),field("attempt","Attempt"),field("maxRetries","Max retries"),field("nextRetryAt","Next retry"),field("error","Error")],summary:({data})=>{let type=s2(data,"type"),jobId=s2(data,"jobId");return type!==void 0&&jobId!==void 0?`[queue] ${type} · job ${jobId} retrying`:"[queue] job retrying"},outcome:{support:"derived",derive:({data})=>{let attempt=at(data,"attempt"),max=at(data,"maxRetries");if(typeof attempt==="number"&&typeof max==="number"&&Number.isFinite(attempt)&&Number.isFinite(max))return`retrying ${attempt}/${max}`;return s2(data,"error")}}},"queue.stats":{description:"Periodic job-queue statistics across ready, running, completed, and failed counts.",fields:[field("ready","Ready"),field("running","Running"),field("completed","Completed"),field("failed","Failed")],summary:()=>"[queue] stats",outcome:unsupported},"scheduler.job.executed":{description:"A scheduler job ran to completion or failed, with its duration.",fields:[field("name","Job"),field("action","Action"),field("durationMs","Duration (ms)"),field("error","Error")],summary:({data})=>{let name=s2(data,"name");return name!==void 0?`[scheduler] ${name}`:"[scheduler] job executed"},outcome:{support:"derived",derive:({data})=>s2(data,"error")??(at(data,"error")===null?"completed":void 0)}},"message.sent":{description:"A team message was sent from one member to another.",fields:[field("msgId","Message"),field("fromId","From"),field("toId","To"),field("threadId","Thread")],summary:({data})=>{let from=s2(data,"fromId"),to=s2(data,"toId");return from!==void 0&&to!==void 0?`[message] ${from} -> ${to}`:"[message] sent"},outcome:unsupported},"message.replied":{description:"A member replied to an existing message thread.",fields:[field("msgId","Message"),field("fromId","From"),field("toId","To"),field("threadId","Thread")],summary:({data})=>{let from=s2(data,"fromId"),thread=s2(data,"threadId");return from!==void 0&&thread!==void 0?`[message] ${from} replied in ${thread}`:"[message] replied"},outcome:unsupported},"process.spawned":{description:"A supervised process was spawned with a new pid.",fields:[field("label","Label"),field("pid","PID"),field("agentId","Agent")],summary:({data})=>{let label=s2(data,"label")??n2(data,"pid");return label!==void 0?`[process] ${label} spawned`:"[process] spawned"},outcome:unsupported},"process.exited":{description:"A supervised process exited, carrying its exit code, signal, or failure reason.",fields:[field("label","Label"),field("pid","PID"),field("exitCode","Exit code"),field("signal","Signal"),field("durationMs","Duration (ms)"),field("reason","Reason")],summary:({data})=>{let label=s2(data,"label")??n2(data,"pid");return label!==void 0?`[process] ${label} exited`:"[process] exited"},outcome:{support:"derived",derive:({data})=>{let reason=s2(data,"reason");if(reason!==void 0)return reason;let signal=s2(data,"signal");if(signal!==void 0)return`signal ${signal}`;let code=at(data,"exitCode");if(typeof code==="number"&&Number.isFinite(code))return code===0?"ok":`exit ${code}`;return}}},"process.stopped":{description:"A supervised process was stopped, naming the stopping reason.",fields:[field("label","Label"),field("pid","PID"),field("signal","Signal"),field("reason","Reason")],summary:({data})=>{let label=s2(data,"label")??n2(data,"pid");return label!==void 0?`[process] ${label} stopped`:"[process] stopped"},outcome:derivedFrom("reason")},"process.started":{description:"A process executor started a process with a new pid.",fields:[field("label","Label"),field("pid","PID")],summary:({data})=>{let label=s2(data,"label")??n2(data,"pid");return label!==void 0?`[process] ${label} started`:"[process] started"},outcome:unsupported},"agent.invoke.start":{description:"An agent invocation began, naming the agent and its operation.",fields:[field("agent","Agent"),field("operation","Operation"),field("routing.role","Role"),field("routing.tier","Tier"),field("routing.executor","Executor"),field("routing.source","Selection source")],summary:({data})=>{let agent=s2(data,"agent"),operation=s2(data,"operation");return agent!==void 0&&operation!==void 0?`[agent] ${agent} · ${operation}`:"[agent] invocation started"},outcome:unsupported},"agent.invoke.exit":{description:"An agent invocation exited, reporting its exit code or signal.",fields:[field("agent","Agent"),field("operation","Operation"),field("exitCode","Exit code"),field("signal","Signal"),field("routing.role","Role"),field("routing.tier","Tier"),field("routing.executor","Executor"),field("routing.source","Selection source")],summary:({data})=>{let agent=s2(data,"agent"),operation=s2(data,"operation");return agent!==void 0&&operation!==void 0?`[agent] ${agent} · ${operation} exited`:"[agent] invocation exited"},outcome:{support:"derived",derive:({data})=>{let signal=s2(data,"signal");if(signal!==void 0)return`signal ${signal}`;let code=at(data,"exitCode");if(typeof code==="number"&&Number.isFinite(code))return code===0?"ok":`exit ${code}`;return}}},"agent.invoke.escalated":{description:"An agent invocation escalated from one executor tier to another.",fields:[field("fromExecutor","From executor"),field("fromTier","From tier"),field("toExecutor","To executor"),field("toTier","To tier"),field("trigger","Trigger")],summary:({data})=>{let from=s2(data,"fromExecutor"),to=s2(data,"toExecutor");return from!==void 0&&to!==void 0?`[agent] ${from} -> ${to}`:"[agent] escalation"},outcome:{support:"derived",derive:({data})=>s2(data,"toTier")??s2(data,"trigger")}},"agent.invoke.exhausted":{description:"An agent invocation exhausted every eligible executor tier without success.",fields:[field("stage","Stage"),field("attempts","Attempts"),field("fromTier","From tier"),field("toTier","To tier"),field("fromExecutor","From executor"),field("toExecutor","To executor")],summary:({data})=>{let stage=s2(data,"stage");return stage!==void 0?`[agent] ${stage} escalation exhausted`:"[agent] escalation exhausted"},outcome:derivedFromValue("attempts")},"agent.started":{description:"An agent started, carrying its id and type.",fields:[field("agentId","Agent"),field("agentType","Agent type"),field("pid","PID")],summary:({data})=>{let id=s2(data,"agentId");return id!==void 0?`[agent] ${id} started`:"[agent] started"},outcome:unsupported},"agent.stopped":{description:"An agent stopped, reporting its exit code.",fields:[field("agentId","Agent"),field("exitCode","Exit code")],summary:({data})=>{let id=s2(data,"agentId");return id!==void 0?`[agent] ${id} stopped`:"[agent] stopped"},outcome:derivedFromValue("exitCode")},"strategy.changed":{description:"A project strategy changed (0838), minting a new strategy version for dispatch fencing.",fields:[field("data.projectPath","Project"),field("data.strategy","Strategy"),field("data.version","Version")],summary:({data})=>{let strategy=s2(data,"data.strategy"),version3=s2(data,"data.version");return strategy!==void 0?`[strategy] ${strategy}${version3!==void 0?` (v${version3})`:""}`:"[strategy] changed"},outcome:unsupported},"fleet.capacity.changed":{description:"The project write slot was claimed or released (0837), changing dispatch capacity.",fields:[field("data.projectPath","Project"),field("data.change","Change"),field("data.holderId","Holder")],summary:({data})=>{let change=s2(data,"data.change"),holder=s2(data,"data.holderId");return`[fleet] write slot ${change??"changed"}${holder!==void 0?` — ${holder}`:""}`},outcome:unsupported},"agent.message.sent":{description:"A message was sent to an agent, reporting delivery success.",fields:[field("agentId","Agent"),field("ok","Delivered")],summary:({data})=>{let id=s2(data,"agentId");return id!==void 0?`[agent] message -> ${id}`:"[agent] message sent"},outcome:derivedFromValue("ok")},"task.assigned":{description:"A task was assigned to an agent, naming the agent when resolved.",fields:[field("memberId","Member"),field("agentType","Agent type"),field("taskId","Task"),field("outcome","Outcome")],summary:({data})=>{let member=s2(data,"memberId"),task=s2(data,"taskId");return task!==void 0&&member!==void 0?`[task] ${task} assigned to ${member}`:"[task] assignment recorded"},outcome:derivedFrom("outcome")},"history.import.completed":{description:"A history import finished, reporting files, messages, and exit code.",fields:[field("source","Source"),field("sources","Sources"),field("files","Files"),field("messages","Messages"),field("durationMs","Duration (ms)"),field("exitCode","Exit code"),field("artifactPath","Artifact"),field("cwd","Project root")],retain:[field("trigger","Refresh trigger"),field("windowStart","Refresh window start"),field("windowEnd","Refresh window end"),field("importMode","Import mode"),field("coverage","Refresh coverage")],summary:({data})=>{let source=s2(data,"source")??s2(data,"sources");return source!==void 0?`[history] import · ${source}`:"[history] import completed"},outcome:derivedFromValue("exitCode")},"history.analyze.completed":{description:"A history analyze pass finished, reporting sources, duration, and exit code.",fields:[field("source","Source"),field("sources","Sources"),field("durationMs","Duration (ms)"),field("exitCode","Exit code"),field("artifactPath","Artifact")],retain:[field("trigger","Refresh trigger"),field("windowStart","Refresh window start"),field("windowEnd","Refresh window end"),field("importMode","Import mode")],summary:({data})=>{let source=s2(data,"source")??s2(data,"sources");return source!==void 0?`[history] analyze · ${source}`:"[history] analyze completed"},outcome:derivedFromValue("exitCode")},"history.daily.failed":{description:"The daily history refresh failed, carrying the detail, reason, and exit code.",fields:[field("source","Source"),field("sources","Sources"),field("detail","Detail"),field("reason","Reason"),field("exitCode","Exit code")],retain:[field("trigger","Refresh trigger"),field("windowStart","Refresh window start"),field("windowEnd","Refresh window end"),field("importMode","Import mode")],summary:()=>"[history] daily failed",outcome:{support:"derived",derive:({data})=>s2(data,"reason")??s2(data,"detail")??n2(data,"exitCode")}},"history.refresh.enqueued":{description:"A completion-triggered history refresh was enqueued, naming its window.",fields:[field("trigger","Trigger"),field("triggerId","Trigger id"),field("jobId","Queue job"),field("windowStart","Window start"),field("windowEnd","Window end"),field("coalesced","Coalesced"),field("outcome","Outcome")],summary:({data})=>{let start=s2(data,"windowStart"),end=s2(data,"windowEnd");return start!==void 0&&end!==void 0?`[history] refresh · ${start} -> ${end}`:"[history] refresh enqueued"},outcome:{support:"derived",derive:({data})=>{let status=s2(data,"outcome");return status!==void 0&&status!=="enqueued"?status:void 0}}},"rule.run.start":{description:"A rule run began with the rule count it will evaluate.",fields:[field("runId","Run"),field("ruleCount","Rules"),field("evaluator","Evaluator")],summary:({data,correlation})=>{let run=s2(data,"runId")??correlation.runId;return run!==void 0?`[rule] run ${run} started`:"[rule] run started"},outcome:unsupported},"rule.eval.start":{description:"A single rule began evaluating.",fields:[field("runId","Run"),field("ruleId","Rule"),field("evaluator","Evaluator"),field("index","Index"),field("total","Total")],summary:({data})=>{let id=s2(data,"ruleId");return id!==void 0?`[rule] ${id} evaluating`:"[rule] evaluating"},outcome:unsupported},"rule.eval.done":{description:"A rule finished evaluating, reporting its findings count and severity.",fields:[field("runId","Run"),field("ruleId","Rule"),field("evaluator","Evaluator"),field("findings","Findings"),field("durationMs","Duration (ms)"),field("severity","Severity")],summary:({data})=>{let id=s2(data,"ruleId");return id!==void 0?`[rule] ${id} evaluated`:"[rule] evaluated"},outcome:derivedFromValue("findings")},"rule.eval.error":{description:"A rule evaluation failed with an error.",fields:[field("runId","Run"),field("ruleId","Rule"),field("evaluator","Evaluator"),field("error","Error")],summary:({data})=>{let id=s2(data,"ruleId");return id!==void 0?`[rule] ${id} error`:"[rule] error"},outcome:derivedFrom("error")},"rule.run.done":{description:"A rule run finished, reporting findings and whether it stopped early.",fields:[field("runId","Run"),field("findings","Findings"),field("durationMs","Duration (ms)"),field("stoppedEarly","Stopped early"),field("severity","Severity")],summary:({data,correlation})=>{let run=s2(data,"runId")??correlation.runId;return run!==void 0?`[rule] run ${run} done`:"[rule] run done"},outcome:{support:"derived",derive:({data})=>n2(data,"findings")??s2(data,"stoppedEarly")}},"workflow.run.started":{description:"A workflow run started, naming the workflow definition.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("mode","Mode"),field("dryRun","Dry run")],summary:(input)=>{let name=humanWorkflowTitle(input);return name!==""?`[workflow] ${name} started`:"[workflow] started"},outcome:unsupported},"workflow.run.done":{description:"A workflow run reached a done terminal state.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("finalState","Final state"),field("transitionsTaken","Transitions")],summary:(input)=>{let name=humanWorkflowTitle(input);return name!==""?`[workflow] ${name} done`:"[workflow] done"},outcome:derivedFrom("finalState")},"workflow.run.failed":{description:"A workflow run failed with a terminal failure reason.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("finalState","Final state"),field("reason","Reason")],summary:(input)=>{let name=humanWorkflowTitle(input);return name!==""?`[workflow] ${name} failed`:"[workflow] failed"},outcome:derivedFrom("reason")},"workflow.run.finalized":{description:"A workflow run settled on a terminal status.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("status","Status")],summary:(input)=>{let name=humanWorkflowTitle(input);return name!==""?`[workflow] ${name} finalized`:"[workflow] finalized"},outcome:derivedFrom("status")},"workflow.escalation.created":{description:"A canonical escalation packet was projected from existing run evidence.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("fingerprint","Fingerprint"),field("artifactPath","Artifact"),field("decision","Decision")],summary:(input)=>{let name=humanWorkflowTitle(input),decision=typeof at(input.data,"decision")==="string"?` — ${String(at(input.data,"decision"))}`:"";return name!==""?`[workflow] escalation packet created (${name}${decision})`:`[workflow] escalation packet created${decision}`},outcome:derivedFrom("decision")},"workflow.escalation.projection_failed":{description:"Escalation packet projection failed; the original failure is preserved untouched.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("error","Error")],summary:()=>"[workflow] escalation packet projection failed",outcome:derivedFrom("error")},"workflow.run.paused":{description:"A workflow run paused at a step, naming the step when available.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("transitionsTaken","Transitions")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} paused`:"[workflow] paused"},outcome:unsupported},"workflow.run.resumed":{description:"A paused workflow run resumed at a step, naming the step when available.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} resumed`:"[workflow] resumed"},outcome:unsupported},"workflow.run.reseeded":{description:"A workflow run was reseeded to a new state, naming the transition.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("fromState","From"),field("toState","To")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"fromState"),to=s2(input.data,"toState");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} : ${from} -> ${to}`:`[workflow] : ${from} -> ${to}`;return name!==""?`[workflow] ${name} reseeded`:"[workflow] reseeded"},outcome:derivedFrom("toState")},"workflow.node.enter":{description:"The engine entered a workflow node, naming the step when available.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("transitionsTaken","Transitions")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] node entered"},outcome:unsupported},"workflow.phase":{description:"A workflow phase changed status, naming the phase.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("phase","Phase"),field("status","Status")],summary:(input)=>{let name=humanWorkflowTitle(input),phase=s2(input.data,"phase"),parts=[name,phase].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] phase"},outcome:derivedFrom("status")},"workflow.node.transition":{description:"A workflow transitioned between nodes, naming the from and to states.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("trigger","Trigger")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} : ${from} -> ${to}`:`[workflow] : ${from} -> ${to}`;return name!==""?`[workflow] ${name} transitioned`:"[workflow] transitioned"},outcome:derivedFrom("to")},"workflow.transition":{description:"A workflow state transition was committed.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("trigger","Trigger")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} : ${from} -> ${to}`:`[workflow] : ${from} -> ${to}`;return name!==""?`[workflow] ${name} transitioned`:"[workflow] transitioned"},outcome:derivedFrom("to")},"workflow.transition.requested":{description:"A workflow transition was requested and accepted for evaluation.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("trigger","Trigger")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} requested ${from} -> ${to}`:`[workflow] requested ${from} -> ${to}`;return name!==""?`[workflow] ${name} transition requested`:"[workflow] transition requested"},outcome:unsupported},"workflow.transition.denied":{description:"A workflow transition was denied with a reason.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("reason","Reason")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} denied ${from} -> ${to}`:`[workflow] denied ${from} -> ${to}`;return name!==""?`[workflow] ${name} transition denied`:"[workflow] transition denied"},outcome:derivedFrom("reason")},"workflow.action.started":{description:"A workflow action began executing, naming the step and kind.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("actionId","Action"),field("kind","Kind")],retain:[field("metadata.agent","Agent"),field("metadata.role","Role"),field("routing.executor","Executor")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} started`:"[workflow] action started"},outcome:unsupported},"workflow.action.finished":{description:"A workflow action finished, reporting its status and success.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("actionId","Action"),field("kind","Kind"),field("durationMs","Duration (ms)"),field("status","Status")],retain:[field("metadata.agent","Agent"),field("metadata.role","Role"),field("routing.executor","Executor")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} finished`:"[workflow] action finished"},outcome:{support:"derived",derive:({data})=>s2(data,"status")??n2(data,"ok")}},"workflow.action.failed_continue":{description:"A workflow action failed but the workflow continued, carrying the error.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("transitionsTaken","Transitions"),field("error","Error")],retain:[field("metadata.agent","Agent"),field("metadata.role","Role"),field("routing.executor","Executor")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} failed; continuing`:"[workflow] action failed; continuing"},outcome:derivedFrom("error")},"workflow.guard.evaluated":{description:"A workflow guard was evaluated for a transition, reporting whether it passed.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("from","From"),field("to","To"),field("kind","Kind"),field("passed","Passed")],summary:(input)=>{let name=humanWorkflowTitle(input),from=s2(input.data,"from"),to=s2(input.data,"to");if(from!==void 0&&to!==void 0)return name!==""?`[workflow] ${name} guard ${from} -> ${to}`:`[workflow] guard ${from} -> ${to}`;return name!==""?`[workflow] ${name} guard evaluated`:"[workflow] guard evaluated"},outcome:derivedFromValue("passed")},"workflow.hitl.ask":{description:"A workflow paused for human input, naming the step and kind.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("kind","Kind")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} awaiting input`:"[workflow] awaiting input"},outcome:unsupported},"workflow.hitl.response":{description:"Human input was received for a paused workflow step.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node"),field("ok","Accepted")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} input received`:"[workflow] input received"},outcome:derivedFromValue("ok")},"workflow.hitl.note":{description:"A note was recorded on a paused workflow step.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("nodeLabel","Step"),field("node","Node")],summary:(input)=>{let name=humanWorkflowTitle(input),step=humanStepLabel(input.data),parts=[name,step].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")} note`:"[workflow] note"},outcome:unsupported},"workflow.custom":{description:"A custom workflow event was emitted, naming the custom event.",fields:[field("runId","Run"),field("workflowName","Workflow"),field("name","Event")],summary:(input)=>{let name=humanWorkflowTitle(input),custom3=s2(input.data,"name"),parts=[name,custom3].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] custom"},outcome:unsupported},"workflow.agent":{description:"A workflow-dispatched agent execution lifecycle event, discriminated by kind.",fields:[field("runId","Run"),field("executionId","Execution"),field("actionId","Action"),field("kind","Kind"),field("agent","Agent"),field("model","Model")],retain:[field("metadata.agent","Agent"),field("metadata.role","Role"),field("routing.executor","Executor")],summary:(input)=>{let name=humanWorkflowTitle(input),kind=s2(input.data,"kind"),parts=[name,kind!==void 0?`agent ${kind}`:"agent"].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] agent"},outcome:{support:"derived",derive:({data})=>s2(data,"kind")==="finished"?s2(data,"outcome"):void 0}},"workflow.steering":{description:"A steering command was acknowledged for a workflow action boundary.",fields:[field("runId","Run"),field("actionId","Action"),field("operation","Operation"),field("actor","Actor"),field("accepted","Accepted"),field("state","State"),field("reason","Reason")],summary:(input)=>{let name=humanWorkflowTitle(input),operation=s2(input.data,"operation"),parts=[name,operation!==void 0?`steering ${operation}`:"steering"].filter((part)=>typeof part==="string"&&part!=="");return parts.length>0?`[workflow] ${parts.join(" · ")}`:"[workflow] steering"},outcome:{support:"derived",derive:({data})=>{let reason=s2(data,"reason");if(reason!==void 0)return reason;let accepted=at(data,"accepted");if(accepted===!0)return"accepted";if(accepted===!1)return"rejected";return s2(data,"state")}}},"api.request.error":{description:"An API request failed, naming the method, path, and status or error code.",fields:[field("method","Method"),field("path","Path"),field("status","Status"),field("code","Code"),field("requestId","Request"),field("error","Error")],summary:({data})=>{let method=s2(data,"method"),path8=s2(data,"path");return method!==void 0&&path8!==void 0?`[api] ${method} ${path8}`:"[api] request error"},outcome:{support:"derived",derive:({data})=>s2(data,"error")??s2(data,"code")??n2(data,"status")}},"bus.emit.done":{description:"An event was emitted to its handlers on the event bus.",fields:[field("event","Event"),field("handlers","Handlers"),field("durationMs","Duration (ms)")],summary:({data})=>{let event=s2(data,"event");return event!==void 0?`[bus] ${event} emitted`:"[bus] event emitted"},outcome:derivedFromValue("handlers")},"bus.emit.noop":{description:"An event was emitted but had no registered handlers.",fields:[field("event","Event"),field("handlers","Handlers"),field("durationMs","Duration (ms)")],summary:({data})=>{let event=s2(data,"event");return event!==void 0?`[bus] ${event} had no handlers`:"[bus] event had no handlers"},outcome:derivedFromValue("handlers")},"bus.handler.error":{description:"An event-bus handler threw an error while processing an event.",fields:[field("event","Event"),field("handlers","Handlers"),field("durationMs","Duration (ms)"),field("error","Error")],summary:({data})=>{let event=s2(data,"event");return event!==void 0?`[bus] ${event} handler error`:"[bus] handler error"},outcome:derivedFrom("error")},"bus.handler.async.enqueued":{description:"An event-bus handler was enqueued for asynchronous processing.",fields:[field("event","Event"),field("handlers","Handlers")],summary:({data})=>{let event=s2(data,"event");return event!==void 0?`[bus] ${event} handlers enqueued`:"[bus] handlers enqueued"},outcome:derivedFromValue("handlers")}};function inferSeverity(name){if(/(?:failed|error|denied)$/.test(name))return"error";if(/(?:retrying|paused|dropped)$/.test(name))return"warning";return"info"}function resolveCatalogEntry(base2){let profile=SOURCE_PROFILES[base2.source],presenter=SYSTEM_EVENT_PRESENTERS[base2.name];return{name:base2.name,prefix:base2.name.split(".")[0]??base2.name,source:base2.source,tier:base2.tier,persisted:!0,streamed:!0,payloadPolicy:base2.payloadPolicy,renderer:base2.renderer,...profile,...base2.producer!==void 0?{producerPackage:base2.producer.package,subsystem:base2.producer.subsystem}:{},severity:inferSeverity(base2.name),description:presenter.description,metadataFields:presenter.retain?[...presenter.fields,...presenter.retain.filter((r)=>!presenter.fields.some((f)=>f.path===r.path))]:presenter.fields,remediationKind:profile.remediationKind}}var SYSTEM_EVENT_CATALOG=BASE_CATALOG.map(resolveCatalogEntry),SYSTEM_EVENT_NAMES=SYSTEM_EVENT_CATALOG.map((entry)=>entry.name),SYSTEM_EVENT_PERSISTED_NAMES=SYSTEM_EVENT_CATALOG.filter((entry)=>entry.tier==="default").map((entry)=>entry.name),SYSTEM_EVENT_STREAMED_NAMES=SYSTEM_EVENT_CATALOG.filter((entry)=>entry.tier==="default").map((entry)=>entry.name),SYSTEM_EVENT_PREFIXES=Array.from(new Set(SYSTEM_EVENT_CATALOG.map((entry)=>entry.prefix))),SYSTEM_EVENT_DEFAULT_NAMES=SYSTEM_EVENT_CATALOG.filter((entry)=>entry.tier==="default").map((entry)=>entry.name),SYSTEM_EVENT_DIAGNOSTIC_NAMES=SYSTEM_EVENT_CATALOG.filter((entry)=>entry.tier==="diagnostic").map((entry)=>entry.name);var SYSTEM_EVENT_CATALOG_METADATA=SYSTEM_EVENT_CATALOG.map(({name,prefix,source,tier,renderer,producerPackage,subsystem,severity,description,metadataFields,remediationKind})=>({name,prefix,source,tier,renderer,producerPackage,subsystem,severity,description,metadataFields,remediationKind}));function workflowVersionLiteral(workflow){return typeof workflow.version==="string"&&workflow.version!==""?workflow.version:null}var{mkdirSync:mkdirSync2}=await import("node:fs"),{readFile}=await import("node:fs/promises");function parseIdentityMetadata(raw){if(raw.trim()==="")return{};try{let parsed=JSON.parse(raw);if(parsed===null||typeof parsed!=="object"||Array.isArray(parsed))return null;return parsed}catch{return null}}async function openInlineRunProjectDb(workdir){let url2=join5(resolve4(workdir),".spur","spur.db");mkdirSync2(join5(url2,".."),{recursive:!0});let adapter=await createMigratedDb({url:url2});return{adapter,close:()=>adapter.close()}}async function createOrAttachInlineRun(input){let runId=input.runId.trim();if(runId==="")return{ok:!1,error:"inline run setup requires a non-empty runId (driver Run setup step 2)"};let workdir=resolve4(input.workdir),resolved;try{let projection=input.inventory===void 0?void 0:parseWorkflowInventory(input.inventory);if(projection&&!projection.ok)return projection;let inventory=projection?.ok?projection.inventory:void 0;if(inventory&&(!inventory.source||inventory.kind!=="state-machine"))return{ok:!1,error:"inline run setup requires a state-machine inventory with definition source"};if(resolved=await resolveWorkflowDefinition(workdir,inventory?.source?.path??input.file,{validateSchema:!0,...input.embeddedSchemas!==void 0?{embeddedSchemas:input.embeddedSchemas}:{},...!inventory?{registered:input.registered}:{}}),(resolved.workflow.kind??"state-machine")!=="state-machine")return{ok:!1,error:"inline run setup requires a state-machine definition"};if(inventory?.source){let identity4=assertInventoryIdentity(inventory,resolved.digest);if(!identity4.ok)return identity4;if(inventory.name!==resolved.workflow.name)return{ok:!1,error:"inline run setup: inventory workflow name does not match its definition"};resolved={...resolved,layer:inventory.source.layer}}}catch(error51){return{ok:!1,error:`inline run setup could not resolve the workflow definition: ${error51.message}`}}let digest=resolved.digest,version3=workflowVersionLiteral(resolved.workflow),source={path:resolved.path,layer:resolved.layer,workdir},db2=await input.getDb(),existing=await new RunDao(db2).traceRowById(runId);if(existing!==void 0){let metadata=parseIdentityMetadata(existing.metadata_json);if(metadata===null)return{ok:!1,error:`inline run setup refuses run ${runId}: its existing row has malformed metadata_json, `+"so its identity cannot be verified — delete the stale run row or allocate a new run id"};let resumeDigest=typeof metadata.resumeDefinitionDigest==="string"?metadata.resumeDefinitionDigest:void 0,launchDigest=typeof metadata.definitionDigest==="string"?metadata.definitionDigest:void 0,effectiveDigest=resumeDigest??launchDigest;if(effectiveDigest===void 0)return{ok:!1,error:`inline run setup refuses run ${runId}: its existing row carries no definition digest `+"(pre-identity legacy row) — allocate a new run id instead of attaching an unverifiable identity"};if(effectiveDigest!==digest)return{ok:!1,error:`inline run setup refuses run ${runId}: the resolved definition digest (${digest}) does not match the run's recorded ${resumeDigest!==void 0?"resume":""} digest (${effectiveDigest}) — `+"a changed definition must resume through the explicit resume rules, not silently re-attach"};if(existing.workflow_name!==resolved.workflow.name)return{ok:!1,error:`inline run setup refuses run ${runId}: the run row records workflow "${existing.workflow_name}" but the resolved definition is "${resolved.workflow.name}" — conflicting run identity`};if(typeof metadata.definitionSource!=="object"||metadata.definitionSource===null||Array.isArray(metadata.definitionSource))return{ok:!1,error:`inline run setup refuses run ${runId}: its existing row carries no definition source `+"(path/layer/workdir) — allocate a new run id instead of attaching an unverifiable launch source"};let existingSource=metadata.definitionSource;if(!(typeof existingSource.path==="string"&&resolve4(existingSource.path)===resolved.path&&normalizePersistedWorkflowLayer(existingSource.layer)===resolved.layer&&typeof existingSource.workdir==="string"&&resolve4(existingSource.workdir)===workdir))return{ok:!1,error:`inline run setup refuses run ${runId}: the recorded definition source (${JSON.stringify(existingSource)}) does not match the resolved launch source (${JSON.stringify(source)}) — conflicting project/workdir identity`};return{ok:!0,attached:!0,runId,workflowName:resolved.workflow.name,definitionDigest:digest,workflowVersion:version3,resolvedPath:resolved.path,layer:resolved.layer,workdir,status:existing.status}}return await new WorkflowService(createDefaultWorkflowEngineHost(),new DbWorkflowPersistenceAdapter(db2)).createOrAttachRun({id:runId,workflow_name:resolved.workflow.name,mode:"state-machine",status:"running",started_at:new Date().toISOString(),completed_at:null,metadata_json:JSON.stringify({definitionDigest:digest,workflowVersion:version3,definitionSource:source})}),{ok:!0,attached:!1,runId,workflowName:resolved.workflow.name,definitionDigest:digest,workflowVersion:version3,resolvedPath:resolved.path,layer:resolved.layer,workdir,status:"running"}}import{basename as basename2,join as join6}from"node:path";var FEATURE_RECEIPT_SCHEMA_VERSION=1,DEFAULT_FEATURE_VERIFICATION_CMD="bun run spur-check-feature",RECEIPT_ID_PATTERN=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function assertReceiptId(kind,id){if(!RECEIPT_ID_PATTERN.test(id)||id.includes(".."))throw Error(`invalid ${kind} for receipt path: ${JSON.stringify(id)}`)}function featureReceiptPaths(runDir,featureId2,runId){return assertReceiptId("featureId",featureId2),assertReceiptId("runId",runId),{runScoped:join6(runDir,`${runId}-feature-verification.json`),featureScoped:join6(runDir,`${featureId2}-feature-verification.json`),log:join6(runDir,`${runId}-feature-verification.log`),status:join6(runDir,`${runId}-feature-verification.status`)}}async function atomicWriteReceipt(fs2,path8,receipt){let body=`${JSON.stringify(receipt,null,4)}
1459
1467
  `,tmp=`${path8}.tmp`;await fs2.writeFile(tmp,body),await fs2.rename(tmp,path8)}async function startFeatureVerificationReceipt(fs2,runDir,options){let receipt={schemaVersion:FEATURE_RECEIPT_SCHEMA_VERSION,featureId:options.featureId,runId:options.runId,workdir:options.workdir,verifier:options.verifier,verificationCmd:options.verificationCmd,inputDigest:options.inputDigest,status:"RUNNING",startedAt:options.startedAt??new Date().toISOString().replace(/\.\d{3}Z$/,"Z"),completedAt:null},paths=featureReceiptPaths(runDir,options.featureId,options.runId);return await fs2.ensureDir(runDir),await atomicWriteReceipt(fs2,paths.runScoped,receipt),await atomicWriteReceipt(fs2,paths.featureScoped,receipt),receipt}async function completeFeatureVerificationReceipt(fs2,runDir,running,options){if(running.status!=="RUNNING")throw Error(`receipt for run ${running.runId} is already ${running.status}`);let receipt={...running,status:options.status,inputDigest:options.inputDigest??running.inputDigest,completedAt:options.completedAt??new Date().toISOString().replace(/\.\d{3}Z$/,"Z")},paths=featureReceiptPaths(runDir,receipt.featureId,receipt.runId);return await fs2.ensureDir(runDir),await atomicWriteReceipt(fs2,paths.runScoped,receipt),await atomicWriteReceipt(fs2,paths.featureScoped,receipt),await fs2.writeFile(paths.status,`${receipt.status}
1460
- `),receipt}function parseReceipt(raw){let parsed;try{parsed=JSON.parse(raw)}catch(err){throw Error(`not JSON (${String(err)})`)}if(parsed===null||typeof parsed!=="object")throw Error("not an object");let r=parsed;if(r.schemaVersion!==FEATURE_RECEIPT_SCHEMA_VERSION)throw Error(`schemaVersion must be ${FEATURE_RECEIPT_SCHEMA_VERSION}`);let v=r.verifier;if(typeof r.featureId!=="string"||typeof r.runId!=="string"||typeof r.workdir!=="string"||typeof v?.name!=="string"||typeof v?.sourcePath!=="string"||typeof v?.layer!=="string"||typeof v?.definitionDigest!=="string"||typeof r.verificationCmd!=="string"||typeof r.inputDigest!=="string"||r.status!=="RUNNING"&&r.status!=="PASS"&&r.status!=="FAIL"||typeof r.startedAt!=="string"||r.completedAt!==null&&typeof r.completedAt!=="string")throw Error("required fields missing or mistyped");return parsed}async function readReceiptCopy(fs2,path8,label){let raw;try{raw=await fs2.readFile(path8)}catch{throw Error(`no ${label} receipt at ${path8}; run the feature-scoped verification pass`)}try{return parseReceipt(raw)}catch(err){throw Error(`${label} receipt at ${basename2(path8)} is not a valid schema-v1 artifact (${String(err)})`)}}async function validateFeatureVerificationReceipt(fs2,options){let latest;try{latest=await readReceiptCopy(fs2,join6(options.runDir,`${options.featureId}-feature-verification.json`),"feature-latest")}catch(err){let message=String(err);return{ok:!1,reason:message.includes("not a valid")?"malformed":"missing",detail:message}}let paths=featureReceiptPaths(options.runDir,options.featureId,latest.runId);try{let runScoped=await readReceiptCopy(fs2,paths.runScoped,"run-scoped");if(JSON.stringify(runScoped)!==JSON.stringify(latest))return{ok:!1,reason:"divergent",detail:`run-scoped ${paths.runScoped} and feature-latest receipts disagree — a newer attempt started or the evidence was tampered with`}}catch(err){let message=String(err);return{ok:!1,reason:message.includes("not a valid")?"malformed":"missing",detail:message}}if(latest.featureId!==options.featureId)return{ok:!1,reason:"cross-feature",detail:`receipt belongs to feature "${latest.featureId}", not "${options.featureId}"`};if(latest.status==="FAIL")return{ok:!1,reason:"failed",detail:`verification pass recorded FAIL (started ${latest.startedAt}, ended ${latest.completedAt})`};if(latest.status==="RUNNING")return{ok:!1,reason:"run",detail:`verification pass is still RUNNING (started ${latest.startedAt}); no completion evidence exists`};if(options.runPort?.readRunRow){let row=await options.runPort.readRunRow(latest.runId);if(!row)return{ok:!1,reason:"run",detail:`run ${latest.runId} that recorded the receipt does not exist in the run store`};if(row.status!=="done")return{ok:!1,reason:"run",detail:`run ${latest.runId} is "${row.status}", not terminal done — the recording run never finished`};if(row.definitionDigest&&row.definitionDigest!==latest.verifier.definitionDigest)return{ok:!1,reason:"run",detail:`run ${latest.runId} attached with definition digest ${row.definitionDigest}, receipt records ${latest.verifier.definitionDigest}`};let recordedCmd;try{let vars=row.varsJson?JSON.parse(row.varsJson):void 0;if(vars&&typeof vars==="object"&&typeof vars.verificationCmd==="string")recordedCmd=vars.verificationCmd}catch{recordedCmd=void 0}if(recordedCmd!==void 0&&recordedCmd!==latest.verificationCmd)return{ok:!1,reason:"run",detail:`run ${latest.runId} recorded effective command "${recordedCmd}", receipt records "${latest.verificationCmd}"`};if(options.runPort.hasArtifact&&!await options.runPort.hasArtifact(latest.runId,paths.runScoped))return{ok:!1,reason:"run",detail:`receipt ${basename2(paths.runScoped)} is not registered as an artifact of run ${latest.runId}`}}let verifier=latest.verifier;if(verifier.name!==options.currentVerifier.name||verifier.sourcePath!==options.currentVerifier.sourcePath||verifier.layer!==options.currentVerifier.layer||verifier.definitionDigest!==options.currentVerifier.definitionDigest)return{ok:!1,reason:"contract-mismatch",detail:`receipt recorded verifier ${verifier.name}@${verifier.layer} (${verifier.definitionDigest}), completion evaluates ${options.currentVerifier.name}@${options.currentVerifier.layer} (${options.currentVerifier.definitionDigest}) — the selected definition changed after the pass`};if(latest.verificationCmd!==options.currentVerificationCmd)return{ok:!1,reason:"contract-mismatch",detail:`receipt recorded with verifier "${latest.verificationCmd}", completion evaluates the configured command "${options.currentVerificationCmd}"`};if(latest.inputDigest!==options.currentDigest)return{ok:!1,reason:"stale",detail:`receipt digest ${latest.inputDigest} ≠ current inputs ${options.currentDigest} — tree, spec, learnings or check contract changed after the pass`};return{ok:!0,receipt:latest}}async function captureFeatureReceiptDigest(repoRoot,featureContent,learningsContent){return ProofInputFingerprint.compute({cwd:repoRoot,featureContent,learningsContent})}var section_matrix_schema_default={$schema:"http://json-schema.org/draft-07/schema#",$id:"https://gobing.ai/spur/schemas/section-matrix.schema.json",title:"Section-Status-Matrix Schema",description:"Validates the shipped section-matrix.yaml — which sections are required/optional/forbidden per task status. Design §3.2. Authored for ts-runtime's loadStructuredConfig validator (supports properties/required/additionalProperties + $defs/$ref/enum; NOT patternProperties/uniqueItems).",type:"object",required:["variants"],additionalProperties:!1,properties:{$schema:{type:"string",description:"JSON Schema ref this file validates against (loadStructuredConfig reads it)."},variants:{type:"object",description:"Map of template variant → per-status matrix. Variant names are extensible (user-defined variants allowed); each value is a variant.",additionalProperties:{$ref:"#/$defs/variant"}}},$defs:{section:{enum:["Background","Requirements","Acceptance Criteria","Q&A","Design","Plan","Solution","Root Cause","Testing","Review","References","Notes","History"],description:"Canonical task section vocabulary (DD-08). Any other value is a typo."},sectionList:{type:"array",items:{$ref:"#/$defs/section"}},entry:{type:"object",additionalProperties:!1,properties:{required:{$ref:"#/$defs/sectionList"},optional:{$ref:"#/$defs/sectionList"},forbidden:{$ref:"#/$defs/sectionList"},gate:{type:"boolean"}}},variant:{type:"object",additionalProperties:!1,description:"A variant may declare any subset of the 7 canonical statuses (enumerated below); an unknown status key is rejected.",properties:{backlog:{$ref:"#/$defs/entry"},todo:{$ref:"#/$defs/entry"},wip:{$ref:"#/$defs/entry"},testing:{$ref:"#/$defs/entry"},blocked:{$ref:"#/$defs/entry"},done:{$ref:"#/$defs/entry"},cancelled:{$ref:"#/$defs/entry"}}}}};var spur_config_schema_default={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://github.com/gobing-ai/spur/schemas/spur-config.schema.json",title:"Spur Project Configuration",description:"Schema for .spur/config.yaml — the single project configuration surface consumed by spur and (future) spur-server.",type:"object",properties:{$schema:{type:"string",description:"Reference to this schema for IDE validation. spur resolves this at runtime via loadStructuredConfig."},version:{type:"string",description:"Config schema version (string, not integer). Current recommended: '1.2' (config-1.2 layered global/project merge, ADR-033 executor tiers + planning blocks). '1' remains accepted for backward compatibility."},name:{type:"string",description:"Project name written by spur init."},bootstrap:{type:"object",description:"Portable bootstrap block consumed by @gobing-ai/ts-infra runNodeApplication. Shared across spur and spur-server.",properties:{logging:{type:"object",properties:{enabled:{type:"boolean",description:"Enable structured logging via LogTape."},level:{type:"string",enum:["trace","debug","info","warn","error","fatal"],description:"Minimum log level."},console:{type:"boolean",description:"Emit log records to console (stderr)."},json:{type:"boolean",description:"Format log records as JSON Lines. false = text format."},file:{type:"boolean",description:"Write log records to a file sink. Uses filePath when set, otherwise disabled."},filePath:{type:"string",description:"Path to the log file. Relative to project root. Default: .spur/logs/spur.log."}}},telemetry:{type:"object",properties:{enabled:{type:"boolean",description:"Enable OpenTelemetry tracing/metrics export."},serviceName:{type:"string",description:"Service name reported to OTel collectors."},environment:{type:"string",description:"Deployment environment label."}}},database:{type:"object",properties:{enabled:{type:"boolean",description:"Enable the SQLite database adapter."},driver:{type:"string",enum:["bun-sqlite"],description:"Database driver. Currently only bun-sqlite."},url:{type:"string",description:"Database file path. Supports ${DATABASE_URL} interpolation. Default: .spur/spur.db."}}},scheduler:{type:"object",properties:{enabled:{type:"boolean",description:"Enable the scheduled-task runner. OFF by default for CLI (run-once)."},jobs:{type:"array",description:"Declarative scheduled commands (task 0734). Each entry registers one scheduler tick that enqueues a `scheduler.custom` queue job running `command` through `/bin/sh -c`. Normalized and validated by @gobing-ai/ts-infra runNodeApplication before the server starts.",items:{type:"object",required:["name","command"],properties:{name:{type:"string",minLength:1,description:"Job name, unique across the list after trimming. Reported as the `scheduler.custom:<name>` display name on scheduler.job.executed."},command:{type:"string",minLength:1,description:"Shell command run by `/bin/sh -c` with the project root as cwd. Trusted operator input — never logged."},intervalMinutes:{type:"integer",minimum:1,maximum:35791,description:"Fixed interval in minutes. Mutually exclusive with `cron`. The upper bound is the Node timer ceiling (2147483647 ms)."},cron:{type:"string",minLength:1,description:"Five-field cron expression (minute hour day-of-month month day-of-week) evaluated in local time. Mutually exclusive with `intervalMinutes`."}},oneOf:[{required:["intervalMinutes"],not:{required:["cron"]}},{required:["cron"],not:{required:["intervalMinutes"]}}]}}}}}},agent:{type:"object",properties:{default:{type:"string",description:"Default role for `--agent auto` when nothing is declared (0542 R2). A role id (scribe, coder, reviewer, planner) selects its tier's cheapest eligible executor; a configured executor name still resolves during the transition with a one-time warning; any other value is rejected naming both accepted sets."},executors:{type:"array",description:"Named executor profiles: each pairs a canonical agent with an optional model override. Referenced by name from `agent.default` and stage model_policy (default-by-phase removed 0452).",items:{type:"object",required:["name","agent"],properties:{name:{type:"string",minLength:1,description:"Executor selector name (unique across the list)."},agent:{type:"string",minLength:1,description:"Canonical coding agent (claude, codex, gemini, pi, opencode, antigravity-cli, openclaw, hermes, omp)."},model:{type:"string",minLength:1,description:"Opaque model override passed straight to the agent (e.g. zai//glm-5.2). Applied only when the user passes no explicit --model."},tier:{type:"string",enum:["cheap","standard","capable-1","capable-2","capable-3"],description:"Capability tier for stage-registry adaptive model routing (ADR-033, 0343). Live values: cheap | standard | capable-1 | capable-2 | capable-3 (1=low output quality, 3=high within the capable band). A stage starts on the cheapest eligible executor meeting its model_policy min_tier. Bare legacy `capable` is accepted at runtime (zod preprocess → capable-1) during the deprecation window but is not part of this editor enum."},disabled:{description:"Routing kill-switch (111; ownership widened 0890): a disabled profile never serves a role, team, stage, or explicit selection, and doctor inventories it without probing. Omitted = enabled. Bare `true` is operator-owned (only humans write booleans); automatic writers emit the object form carrying owner (operator|quota|probe), since (RFC 3339) and reason.",anyOf:[{type:"boolean"},{type:"object",additionalProperties:!1,required:["owner","since","reason"],properties:{owner:{enum:["operator","quota","probe"]},since:{type:"string",format:"date-time",minLength:1},reason:{type:"string",minLength:1}}}]}}}},fleet:{type:"object",description:"The project's agent fleet (G65 / 0858): the single declaration of composition, the on/off switch, and the dispatch strategy. PROJECT LAYER ONLY — a global-layer agent.fleet fails the load. Replaces the retired .spur/fleet.json (0835) and agent.team (0857). Mirrors @gobing-ai/spur-config AgentFleetSchema (Zod is SSOT).",properties:{enabled:{type:"boolean",default:!1,description:"The single fleet switch. `spur serve` materializes and autostarts the roster only when true; an absent or disabled fleet starts nothing."},strategy:{type:"string",enum:["rest","gtd"],default:"rest",description:"Dispatch strategy, reconciled into project_strategy at serve start (0859). One name is added by a typed code change, not by config."},orchestrator:{type:"string",minLength:1,description:"memberLocalId of the one planner-role member carrying purpose: orchestrator. Absent = no orchestrator declared (never inferred)."},members:{type:"array",default:[],description:"The roster. Each member declares a role or an executor. `enabled: false` keeps the member's derived <role>-<n> id index but does not materialize it.",items:{type:"object",properties:{id:{type:"string",minLength:1,description:"Explicit stable id; wins over the derived <role>-<n> form."},role:{type:"string",enum:["scribe","coder","reviewer","planner"],description:"Layer-1 role id (closed vocabulary)."},executor:{type:"string",minLength:1,description:"Executor profile name or a raw canonical agent type."},purpose:{type:"string",description:"Free-form member purpose; `orchestrator` is the value the orchestrator pointer binds to."},enabled:{type:"boolean",description:"Default true. False preserves the member's derived id index without materializing it."}},anyOf:[{required:["role"]},{required:["executor"]}]}}}},roles:{type:"object",description:"Per-role tier/stage overrides over DEFAULT_AGENT_ROLES (0572 / ADR-061). Keys are the closed role vocabulary (scribe, coder, reviewer, planner); a present field replaces the default for that role, an omitted field keeps it. Mirrors @gobing-ai/spur-config AgentRoleConfigSchema (Zod is SSOT).",additionalProperties:{type:"object",properties:{tier:{type:"string",enum:["cheap","standard","capable-1","capable-2","capable-3"],description:"Replacement capability tier for the role. Must not sit below the highest min_tier among the role's folded stages (enforced at the CLI boundary)."},stages:{type:"array",minItems:1,items:{type:"string",minLength:1},description:"Replacement folded-stage list for the role. Ids must come from the canonical stage registry (validated at the CLI boundary). Omit the field to keep the default — an empty array is rejected."}}}}}},rules:{type:"object",properties:{paths:{type:"array",items:{type:"string"},description:"Glob paths to rule files."}}},workflows:{type:"object",properties:{paths:{type:"array",items:{type:"string"},description:"Glob paths to workflow directories."}}},redaction:{type:"object",properties:{enabled:{type:"boolean",description:"Enable sensitive-data redaction in CLI output."}}},history:{type:"object",description:"History import/analyze configuration (feature E3). Opt-in operation-triggered refresh.",properties:{refresh:{type:"object",properties:{on_completion:{type:"boolean",description:"Enqueue a coalesced history refresh when a task or pipeline run completes. Default false (opt-in; hidden automation is out of contract)."},debounce_ms:{type:"integer",minimum:0,description:"Coalescing window in milliseconds. Completions inside the window join one pending refresh. Default 60000."}}}}},builder:{type:"object",description:"Builder noun configuration. Currently hosts the release plumbing knobs for `spur builder bump-ver` / `drop-tags`; every field defaults to the built-in release convention, so an absent builder section keeps default behavior.",properties:{"bump-ver":{type:"object",description:"Release knobs for bump-ver/drop-tags. Defaults: -v separator, publish.yml workflow, chore(release) commit, gh run list limit 5.",properties:{aggregatePackage:{type:"string",minLength:1,description:'Package whose own release tag is the publish trigger for the aggregate (--all) path, as an unscoped package id (e.g. "spur" for @gobing-ai/spur). Default: the package whose full name equals the workspace root manifest name.'},tagVersionSeparator:{type:"string",minLength:1,description:'Release tag format: <package><separator><version>. Default "-v".'},publishWorkflow:{type:"string",minLength:1,description:'GitHub Actions workflow file the pushed release tag triggers. Default "publish.yml".'},releaseCommitType:{type:"string",minLength:1,description:'Conventional commit type for the release commit. Default "chore".'},releaseCommitScope:{type:"string",minLength:1,description:'Conventional commit scope for the release commit. Default "release".'},ghRunListLimit:{type:"integer",minimum:1,description:"gh run list --limit used to point at the triggered publish run. Default 5."},versionCarriers:{type:"array",description:"Extra version carriers beyond workspace package.json files. Default: none. Types are registered in apps/cli/src/version-carriers.ts (registerCarrierType), which validates instances at release time; registering a new type extends this description in the same commit.",items:{type:"object",description:"One carrier instance. Required field: type (string). Built-ins: plugin-manifest { paths: [..] } — repo-wide manifests synced to the release version (e.g. per-platform plugin.json mirrors); ts-literal { file?, identifier? } — version constant in a package source file (defaults src/config.ts / binaryVersion).",properties:{type:{type:"string",minLength:1}},required:["type"]}}}}}},tasks:{type:"object",description:"Task-folder registration (design §9). Absorbs the legacy docs/.tasks/config.json folders + baseCounter concepts. Mirrors @gobing-ai/spur-config tasksConfigSchema (Zod is SSOT).",properties:{folders:{type:"object",description:"Map of task-folder path → folder config.",additionalProperties:{type:"object",properties:{baseCounter:{type:"integer",minimum:0,description:"WBS base counter for new tasks in this folder. Default 0."},label:{type:"string",description:"Human-readable folder label."}}}},active:{type:"string",description:"Default folder for `spur task create`. Default: docs/tasks."},severity:{type:"object",description:"Rule severity overrides map by code (error | warning | off).",additionalProperties:{type:"string",enum:["error","warning","off"]}}}},features:{type:"object",description:"Feature directory location (design §9). Mirrors @gobing-ai/spur-config featuresConfigSchema (Zod is SSOT).",properties:{dir:{type:"string",description:"Feature files directory. Default: docs/features."}}}}};var state_machine_workflow_schema_default={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://github.com/gobing-ai/spur/schemas/state-machine-workflow.schema.json",title:"@gobing-ai/ts-dual-workflow-engine State-machine Workflow",type:"object",additionalProperties:!1,required:["name","initialState","states","transitions"],properties:{$schema:{type:"string"},kind:{const:"state-machine"},name:{type:"string",minLength:1},version:{type:"string",minLength:1,description:"Optional behavior-neutral identity tag (0756). Absent = unversioned; present = a non-empty opaque literal surfaced as explicit(<literal>). Not parsed, ordered, or compatibility-checked; no registry."},description:{type:"string"},initialState:{type:"string",minLength:1},terminalStates:{type:"array",items:{type:"string",minLength:1}},failureStates:{type:"array",items:{type:"string",minLength:1},description:"Subset of terminalStates whose reach finalizes the run as failed. Absent ⇒ every terminal is a success."},iterationBound:{type:"integer",exclusiveMinimum:0},vars:{type:"object",propertyNames:{pattern:"^[A-Za-z_][A-Za-z0-9_]*$"},additionalProperties:{type:"string"}},env:{type:"object",additionalProperties:!1,properties:{allow:{type:"array",items:{type:"string",pattern:"^[A-Za-z_][A-Za-z0-9_]*$"}}}},extensions:{type:"object",additionalProperties:!1,properties:{actions:{type:"array",items:{$ref:"#/$defs/relativeExtensionPath"}},guards:{type:"array",items:{$ref:"#/$defs/relativeExtensionPath"}}}},states:{type:"array",items:{type:"object",additionalProperties:!1,required:["id"],properties:{id:{type:"string",minLength:1},description:{type:"string"},pause:{type:"boolean",description:"When true, the engine pauses the run at this state for HITL (E3); resume with `spur workflow continue`."},onEnter:{type:"array",items:{$ref:"#/$defs/action"}},onExit:{type:"array",items:{$ref:"#/$defs/action"}}}}},transitions:{type:"array",items:{type:"object",additionalProperties:!1,required:["from","to"],properties:{from:{type:"string",minLength:1},to:{type:"string",minLength:1},description:{type:"string"},trigger:{type:"string"},guard:{$ref:"#/$defs/guard"}}}}},$defs:{action:{type:"object",additionalProperties:!1,required:["kind"],properties:{kind:{type:"string",minLength:1},options:{type:"object",additionalProperties:!0},onError:{type:"string",enum:["fail","continue"],description:"Per-action error handling policy: 'fail' halts the run; 'continue' logs the failure and proceeds so transition guards can route the outcome."}}},guard:{type:"object",additionalProperties:!1,required:["kind"],properties:{kind:{type:"string",minLength:1},options:{type:"object",additionalProperties:!0}}},relativeExtensionPath:{type:"string",minLength:1,description:"Relative module path; absolute paths and '..' traversal are forbidden.",not:{anyOf:[{pattern:"^[/\\\\]"},{pattern:"^[A-Za-z]:[/\\\\]"},{pattern:"(^|[/\\\\])\\.\\.([/\\\\]|$)"}]}}}};var transition_flow_workflow_schema_default={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://github.com/gobing-ai/spur/schemas/transition-flow-workflow.schema.json",title:"@gobing-ai/ts-dual-workflow-engine Transition-flow Workflow",type:"object",additionalProperties:!1,required:["kind","name","initialNode","nodes","edges"],properties:{$schema:{type:"string"},kind:{const:"transition-flow"},name:{type:"string",minLength:1},version:{type:"string",minLength:1,description:"Optional behavior-neutral identity tag (0756). Absent = unversioned; present = a non-empty opaque literal surfaced as explicit(<literal>). Not parsed, ordered, or compatibility-checked; no registry."},description:{type:"string"},initialNode:{type:"string",minLength:1},terminalNodes:{type:"array",items:{type:"string",minLength:1}},iterationBound:{type:"integer",exclusiveMinimum:0},vars:{type:"object",propertyNames:{pattern:"^[A-Za-z_][A-Za-z0-9_]*$"},additionalProperties:{type:"string"}},env:{type:"object",additionalProperties:!1,properties:{allow:{type:"array",items:{type:"string",pattern:"^[A-Za-z_][A-Za-z0-9_]*$"}}}},extensions:{type:"object",additionalProperties:!1,properties:{actions:{type:"array",items:{$ref:"#/$defs/relativeExtensionPath"}},guards:{type:"array",items:{$ref:"#/$defs/relativeExtensionPath"}}}},nodes:{type:"array",items:{type:"object",additionalProperties:!1,required:["id"],properties:{id:{type:"string",minLength:1},description:{type:"string"},type:{enum:["action","gate","parallel","decision"]},action:{$ref:"#/$defs/action"}}}},edges:{type:"array",items:{type:"object",additionalProperties:!1,required:["from","to"],properties:{from:{type:"string",minLength:1},to:{type:"string",minLength:1},description:{type:"string"},condition:{$ref:"#/$defs/guard"}}}}},$defs:{action:{type:"object",additionalProperties:!1,required:["kind"],properties:{kind:{type:"string",minLength:1},options:{type:"object",additionalProperties:!0},onError:{type:"string",enum:["fail","continue"],description:"Per-action error handling policy: 'fail' halts the run; 'continue' logs the failure and proceeds so edge conditions can route the outcome."}}},guard:{type:"object",additionalProperties:!1,required:["kind"],properties:{kind:{type:"string",minLength:1},options:{type:"object",additionalProperties:!0}}},relativeExtensionPath:{type:"string",minLength:1,description:"Relative module path; absolute paths and '..' traversal are forbidden.",not:{anyOf:[{pattern:"^[/\\\\]"},{pattern:"^[A-Za-z]:[/\\\\]"},{pattern:"(^|[/\\\\])\\.\\.([/\\\\]|$)"}]}}}};var EMBEDDED_SPUR_SCHEMAS=new Map([["schemas/spur-config.schema.json",JSON.stringify(spur_config_schema_default)],["schemas/section-matrix.schema.json",JSON.stringify(section_matrix_schema_default)],["schemas/state-machine-workflow.schema.json",JSON.stringify(state_machine_workflow_schema_default)],["schemas/transition-flow-workflow.schema.json",JSON.stringify(transition_flow_workflow_schema_default)]]);export{validateFeatureVerificationReceipt,startFeatureVerificationReceipt,splitLaunchCommand,resolveWorkflowDefinition,readProofInputContents,openInlineRunProjectDb,featureReceiptPaths,createWorkflowActionTraceWriter,createOrAttachInlineRun,computeProofInputFingerprint,completeFeatureVerificationReceipt,captureFeatureReceiptDigest,RunDao,EMBEDDED_SPUR_SCHEMAS,DEFAULT_FEATURE_VERIFICATION_CMD,ArtifactDao};
1468
+ `),receipt}function parseReceipt(raw){let parsed;try{parsed=JSON.parse(raw)}catch(err){throw Error(`not JSON (${String(err)})`)}if(parsed===null||typeof parsed!=="object")throw Error("not an object");let r=parsed;if(r.schemaVersion!==FEATURE_RECEIPT_SCHEMA_VERSION)throw Error(`schemaVersion must be ${FEATURE_RECEIPT_SCHEMA_VERSION}`);let v=r.verifier;if(typeof r.featureId!=="string"||typeof r.runId!=="string"||typeof r.workdir!=="string"||typeof v?.name!=="string"||typeof v?.sourcePath!=="string"||typeof v?.layer!=="string"||typeof v?.definitionDigest!=="string"||typeof r.verificationCmd!=="string"||typeof r.inputDigest!=="string"||r.status!=="RUNNING"&&r.status!=="PASS"&&r.status!=="FAIL"||typeof r.startedAt!=="string"||r.completedAt!==null&&typeof r.completedAt!=="string")throw Error("required fields missing or mistyped");return parsed}async function readReceiptCopy(fs2,path8,label){let raw;try{raw=await fs2.readFile(path8)}catch{throw Error(`no ${label} receipt at ${path8}; run the feature-scoped verification pass`)}try{return parseReceipt(raw)}catch(err){throw Error(`${label} receipt at ${basename2(path8)} is not a valid schema-v1 artifact (${String(err)})`)}}async function validateFeatureVerificationReceipt(fs2,options){let latest;try{latest=await readReceiptCopy(fs2,join6(options.runDir,`${options.featureId}-feature-verification.json`),"feature-latest")}catch(err){let message=String(err);return{ok:!1,reason:message.includes("not a valid")?"malformed":"missing",detail:message}}let paths=featureReceiptPaths(options.runDir,options.featureId,latest.runId);try{let runScoped=await readReceiptCopy(fs2,paths.runScoped,"run-scoped");if(JSON.stringify(runScoped)!==JSON.stringify(latest))return{ok:!1,reason:"divergent",detail:`run-scoped ${paths.runScoped} and feature-latest receipts disagree — a newer attempt started or the evidence was tampered with`}}catch(err){let message=String(err);return{ok:!1,reason:message.includes("not a valid")?"malformed":"missing",detail:message}}if(latest.featureId!==options.featureId)return{ok:!1,reason:"cross-feature",detail:`receipt belongs to feature "${latest.featureId}", not "${options.featureId}"`};if(latest.status==="FAIL")return{ok:!1,reason:"failed",detail:`verification pass recorded FAIL (started ${latest.startedAt}, ended ${latest.completedAt})`};if(latest.status==="RUNNING")return{ok:!1,reason:"run",detail:`verification pass is still RUNNING (started ${latest.startedAt}); no completion evidence exists`};if(options.runPort?.readRunRow){let row=await options.runPort.readRunRow(latest.runId);if(!row)return{ok:!1,reason:"run",detail:`run ${latest.runId} that recorded the receipt does not exist in the run store`};if(row.status!=="done")return{ok:!1,reason:"run",detail:`run ${latest.runId} is "${row.status}", not terminal done — the recording run never finished`};if(row.definitionDigest&&row.definitionDigest!==latest.verifier.definitionDigest)return{ok:!1,reason:"run",detail:`run ${latest.runId} attached with definition digest ${row.definitionDigest}, receipt records ${latest.verifier.definitionDigest}`};let recordedCmd;try{let vars=row.varsJson?JSON.parse(row.varsJson):void 0;if(vars&&typeof vars==="object"&&typeof vars.verificationCmd==="string")recordedCmd=vars.verificationCmd}catch{recordedCmd=void 0}if(recordedCmd!==void 0&&recordedCmd!==latest.verificationCmd)return{ok:!1,reason:"run",detail:`run ${latest.runId} recorded effective command "${recordedCmd}", receipt records "${latest.verificationCmd}"`};if(options.runPort.hasArtifact&&!await options.runPort.hasArtifact(latest.runId,paths.runScoped))return{ok:!1,reason:"run",detail:`receipt ${basename2(paths.runScoped)} is not registered as an artifact of run ${latest.runId}`}}let verifier=latest.verifier,current=options.currentVerifier,drifted=["name","layer","definitionDigest"].filter((k)=>verifier[k]!==current[k]);if(drifted.length>0)return{ok:!1,reason:"contract-mismatch",detail:`receipt recorded verifier ${verifier.name}@${verifier.layer} (${verifier.definitionDigest}), completion evaluates ${current.name}@${current.layer} (${current.definitionDigest}) — the selected definition changed after the pass (${drifted.join(", ")})`};if(latest.verificationCmd!==options.currentVerificationCmd)return{ok:!1,reason:"contract-mismatch",detail:`receipt recorded with verifier "${latest.verificationCmd}", completion evaluates the configured command "${options.currentVerificationCmd}"`};if(latest.inputDigest!==options.currentDigest)return{ok:!1,reason:"stale",detail:`receipt digest ${latest.inputDigest} ≠ current inputs ${options.currentDigest} — tree, spec, learnings or check contract changed after the pass`};return{ok:!0,receipt:latest}}async function captureFeatureReceiptDigest(repoRoot,featureContent,learningsContent){return ProofInputFingerprint.compute({cwd:repoRoot,featureContent,learningsContent})}var section_matrix_schema_default={$schema:"http://json-schema.org/draft-07/schema#",$id:"https://gobing.ai/spur/schemas/section-matrix.schema.json",title:"Section-Status-Matrix Schema",description:"Validates the shipped section-matrix.yaml — which sections are required/optional/forbidden per task status. Design §3.2. Authored for ts-runtime's loadStructuredConfig validator (supports properties/required/additionalProperties + $defs/$ref/enum; NOT patternProperties/uniqueItems).",type:"object",required:["variants"],additionalProperties:!1,properties:{$schema:{type:"string",description:"JSON Schema ref this file validates against (loadStructuredConfig reads it)."},variants:{type:"object",description:"Map of template variant → per-status matrix. Variant names are extensible (user-defined variants allowed); each value is a variant.",additionalProperties:{$ref:"#/$defs/variant"}}},$defs:{section:{enum:["Background","Requirements","Acceptance Criteria","Q&A","Design","Plan","Solution","Root Cause","Testing","Review","References","Notes","History"],description:"Canonical task section vocabulary (DD-08). Any other value is a typo."},sectionList:{type:"array",items:{$ref:"#/$defs/section"}},entry:{type:"object",additionalProperties:!1,properties:{required:{$ref:"#/$defs/sectionList"},optional:{$ref:"#/$defs/sectionList"},forbidden:{$ref:"#/$defs/sectionList"},gate:{type:"boolean"}}},variant:{type:"object",additionalProperties:!1,description:"A variant may declare any subset of the 7 canonical statuses (enumerated below); an unknown status key is rejected.",properties:{backlog:{$ref:"#/$defs/entry"},todo:{$ref:"#/$defs/entry"},wip:{$ref:"#/$defs/entry"},testing:{$ref:"#/$defs/entry"},blocked:{$ref:"#/$defs/entry"},done:{$ref:"#/$defs/entry"},cancelled:{$ref:"#/$defs/entry"}}}}};var spur_config_schema_default={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://github.com/gobing-ai/spur/schemas/spur-config.schema.json",title:"Spur Project Configuration",description:"Schema for .spur/config.yaml — the single project configuration surface consumed by spur and (future) spur-server.",type:"object",properties:{$schema:{type:"string",description:"Reference to this schema for IDE validation. spur resolves this at runtime via loadStructuredConfig."},version:{type:"string",description:"Config schema version (string, not integer). Current recommended: '1.2' (config-1.2 layered global/project merge, ADR-033 executor tiers + planning blocks). '1' remains accepted for backward compatibility."},name:{type:"string",description:"Project name written by spur init."},bootstrap:{type:"object",description:"Portable bootstrap block consumed by @gobing-ai/ts-infra runNodeApplication. Shared across spur and spur-server.",properties:{logging:{type:"object",properties:{enabled:{type:"boolean",description:"Enable structured logging via LogTape."},level:{type:"string",enum:["trace","debug","info","warn","error","fatal"],description:"Minimum log level."},console:{type:"boolean",description:"Emit log records to console (stderr)."},json:{type:"boolean",description:"Format log records as JSON Lines. false = text format."},file:{type:"boolean",description:"Write log records to a file sink. Uses filePath when set, otherwise disabled."},filePath:{type:"string",description:"Path to the log file. Relative to project root. Default: .spur/logs/spur.log."}}},telemetry:{type:"object",properties:{enabled:{type:"boolean",description:"Enable OpenTelemetry tracing/metrics export."},serviceName:{type:"string",description:"Service name reported to OTel collectors."},environment:{type:"string",description:"Deployment environment label."}}},database:{type:"object",properties:{enabled:{type:"boolean",description:"Enable the SQLite database adapter."},driver:{type:"string",enum:["bun-sqlite"],description:"Database driver. Currently only bun-sqlite."},url:{type:"string",description:"Database file path. Supports ${DATABASE_URL} interpolation. Default: .spur/spur.db."}}},scheduler:{type:"object",properties:{enabled:{type:"boolean",description:"Enable the scheduled-task runner. OFF by default for CLI (run-once)."},jobs:{type:"array",description:"Declarative scheduled commands (task 0734). Each entry registers one scheduler tick that enqueues a `scheduler.custom` queue job running `command` through `/bin/sh -c`. Normalized and validated by @gobing-ai/ts-infra runNodeApplication before the server starts.",items:{type:"object",required:["name","command"],properties:{name:{type:"string",minLength:1,description:"Job name, unique across the list after trimming. Reported as the `scheduler.custom:<name>` display name on scheduler.job.executed."},command:{type:"string",minLength:1,description:"Shell command run by `/bin/sh -c` with the project root as cwd. Trusted operator input — never logged."},intervalMinutes:{type:"integer",minimum:1,maximum:35791,description:"Fixed interval in minutes. Mutually exclusive with `cron`. The upper bound is the Node timer ceiling (2147483647 ms)."},cron:{type:"string",minLength:1,description:"Five-field cron expression (minute hour day-of-month month day-of-week) evaluated in local time. Mutually exclusive with `intervalMinutes`."}},oneOf:[{required:["intervalMinutes"],not:{required:["cron"]}},{required:["cron"],not:{required:["intervalMinutes"]}}]}}}}}},agent:{type:"object",properties:{default:{type:"string",description:"Default role for `--agent auto` when nothing is declared (0542 R2). A role id (scribe, coder, reviewer, planner) selects its tier's cheapest eligible executor; a configured executor name still resolves during the transition with a one-time warning; any other value is rejected naming both accepted sets."},executors:{type:"array",description:"Named executor profiles: each pairs a canonical agent with an optional model override. Referenced by name from `agent.default` and stage model_policy (default-by-phase removed 0452).",items:{type:"object",required:["name","agent"],properties:{name:{type:"string",minLength:1,description:"Executor selector name (unique across the list)."},agent:{type:"string",minLength:1,description:"Canonical coding agent (claude, codex, gemini, pi, opencode, antigravity-cli, openclaw, hermes, omp)."},model:{type:"string",minLength:1,description:"Opaque model override passed straight to the agent (e.g. zai//glm-5.2). Applied only when the user passes no explicit --model."},tier:{type:"string",enum:["cheap","standard","capable-1","capable-2","capable-3"],description:"Capability tier for stage-registry adaptive model routing (ADR-033, 0343). Live values: cheap | standard | capable-1 | capable-2 | capable-3 (1=low output quality, 3=high within the capable band). A stage starts on the cheapest eligible executor meeting its model_policy min_tier. Bare legacy `capable` is accepted at runtime (zod preprocess → capable-1) during the deprecation window but is not part of this editor enum."},disabled:{description:"Routing kill-switch (111; ownership widened 0890): a disabled profile never serves a role, team, stage, or explicit selection, and doctor inventories it without probing. Omitted = enabled. Bare `true` is operator-owned (only humans write booleans); automatic writers emit the object form carrying owner (operator|quota|probe), since (RFC 3339) and reason.",anyOf:[{type:"boolean"},{type:"object",additionalProperties:!1,required:["owner","since","reason"],properties:{owner:{enum:["operator","quota","probe"]},since:{type:"string",format:"date-time",minLength:1},reason:{type:"string",minLength:1}}}]}}}},fleet:{type:"object",description:"The project's agent fleet (G65 / 0858): the single declaration of composition, the on/off switch, and the dispatch strategy. PROJECT LAYER ONLY — a global-layer agent.fleet fails the load. Replaces the retired .spur/fleet.json (0835) and agent.team (0857). Mirrors @gobing-ai/spur-config AgentFleetSchema (Zod is SSOT).",properties:{enabled:{type:"boolean",default:!1,description:"The single fleet switch. `spur serve` materializes and autostarts the roster only when true; an absent or disabled fleet starts nothing."},strategy:{type:"string",enum:["rest","gtd"],default:"rest",description:"Dispatch strategy, reconciled into project_strategy at serve start (0859). One name is added by a typed code change, not by config."},orchestrator:{type:"string",minLength:1,description:"memberLocalId of the one planner-role member carrying purpose: orchestrator. Absent = no orchestrator declared (never inferred)."},members:{type:"array",default:[],description:"The roster. Each member declares a role or an executor. `enabled: false` keeps the member's derived <role>-<n> id index but does not materialize it.",items:{type:"object",properties:{id:{type:"string",minLength:1,description:"Explicit stable id; wins over the derived <role>-<n> form."},role:{type:"string",enum:["scribe","coder","reviewer","planner"],description:"Layer-1 role id (closed vocabulary)."},executor:{type:"string",minLength:1,description:"Executor profile name or a raw canonical agent type."},purpose:{type:"string",description:"Free-form member purpose; `orchestrator` is the value the orchestrator pointer binds to."},enabled:{type:"boolean",description:"Default true. False preserves the member's derived id index without materializing it."}},anyOf:[{required:["role"]},{required:["executor"]}]}}}},roles:{type:"object",description:"Per-role tier/stage overrides over DEFAULT_AGENT_ROLES (0572 / ADR-061). Keys are the closed role vocabulary (scribe, coder, reviewer, planner); a present field replaces the default for that role, an omitted field keeps it. Mirrors @gobing-ai/spur-config AgentRoleConfigSchema (Zod is SSOT).",additionalProperties:{type:"object",properties:{tier:{type:"string",enum:["cheap","standard","capable-1","capable-2","capable-3"],description:"Replacement capability tier for the role. Must not sit below the highest min_tier among the role's folded stages (enforced at the CLI boundary)."},stages:{type:"array",minItems:1,items:{type:"string",minLength:1},description:"Replacement folded-stage list for the role. Ids must come from the canonical stage registry (validated at the CLI boundary). Omit the field to keep the default — an empty array is rejected."}}}}}},rules:{type:"object",properties:{paths:{type:"array",items:{type:"string"},description:"Glob paths to rule files."}}},workflows:{type:"object",properties:{paths:{type:"array",items:{type:"string"},description:"Glob paths to workflow directories."}}},redaction:{type:"object",properties:{enabled:{type:"boolean",description:"Enable sensitive-data redaction in CLI output."}}},history:{type:"object",description:"History import/analyze configuration (feature E3). Opt-in operation-triggered refresh.",properties:{refresh:{type:"object",properties:{on_completion:{type:"boolean",description:"Enqueue a coalesced history refresh when a task or pipeline run completes. Default false (opt-in; hidden automation is out of contract)."},debounce_ms:{type:"integer",minimum:0,description:"Coalescing window in milliseconds. Completions inside the window join one pending refresh. Default 60000."}}}}},builder:{type:"object",description:"Builder noun configuration. Currently hosts the release plumbing knobs for `spur builder bump-ver` / `drop-tags`; every field defaults to the built-in release convention, so an absent builder section keeps default behavior.",properties:{"bump-ver":{type:"object",description:"Release knobs for bump-ver/drop-tags. Defaults: -v separator, publish.yml workflow, chore(release) commit, gh run list limit 5.",properties:{aggregatePackage:{type:"string",minLength:1,description:'Package whose own release tag is the publish trigger for the aggregate (--all) path, as an unscoped package id (e.g. "spur" for @gobing-ai/spur). Default: the package whose full name equals the workspace root manifest name.'},tagVersionSeparator:{type:"string",minLength:1,description:'Release tag format: <package><separator><version>. Default "-v".'},publishWorkflow:{type:"string",minLength:1,description:'GitHub Actions workflow file the pushed release tag triggers. Default "publish.yml".'},releaseCommitType:{type:"string",minLength:1,description:'Conventional commit type for the release commit. Default "chore".'},releaseCommitScope:{type:"string",minLength:1,description:'Conventional commit scope for the release commit. Default "release".'},ghRunListLimit:{type:"integer",minimum:1,description:"gh run list --limit used to point at the triggered publish run. Default 5."},versionCarriers:{type:"array",description:"Extra version carriers beyond workspace package.json files. Default: none. Types are registered in apps/cli/src/version-carriers.ts (registerCarrierType), which validates instances at release time; registering a new type extends this description in the same commit.",items:{type:"object",description:"One carrier instance. Required field: type (string). Built-ins: plugin-manifest { paths: [..] } — repo-wide manifests synced to the release version (e.g. per-platform plugin.json mirrors); ts-literal { file?, identifier? } — version constant in a package source file (defaults src/config.ts / binaryVersion).",properties:{type:{type:"string",minLength:1}},required:["type"]}}}}}},tasks:{type:"object",description:"Task-folder registration (design §9). Absorbs the legacy docs/.tasks/config.json folders + baseCounter concepts. Mirrors @gobing-ai/spur-config tasksConfigSchema (Zod is SSOT).",properties:{folders:{type:"object",description:"Map of task-folder path → folder config.",additionalProperties:{type:"object",properties:{baseCounter:{type:"integer",minimum:0,description:"WBS base counter for new tasks in this folder. Default 0."},label:{type:"string",description:"Human-readable folder label."}}}},active:{type:"string",description:"Default folder for `spur task create`. Default: docs/tasks."},severity:{type:"object",description:"Rule severity overrides map by code (error | warning | off).",additionalProperties:{type:"string",enum:["error","warning","off"]}}}},features:{type:"object",description:"Feature directory location (design §9). Mirrors @gobing-ai/spur-config featuresConfigSchema (Zod is SSOT).",properties:{dir:{type:"string",description:"Feature files directory. Default: docs/features."}}}}};var state_machine_workflow_schema_default={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://github.com/gobing-ai/spur/schemas/state-machine-workflow.schema.json",title:"@gobing-ai/ts-dual-workflow-engine State-machine Workflow",type:"object",additionalProperties:!1,required:["name","initialState","states","transitions"],properties:{$schema:{type:"string"},kind:{const:"state-machine"},name:{type:"string",minLength:1},version:{type:"string",minLength:1,description:"Optional behavior-neutral identity tag (0756). Absent = unversioned; present = a non-empty opaque literal surfaced as explicit(<literal>). Not parsed, ordered, or compatibility-checked; no registry."},description:{type:"string"},initialState:{type:"string",minLength:1},terminalStates:{type:"array",items:{type:"string",minLength:1}},failureStates:{type:"array",items:{type:"string",minLength:1},description:"Subset of terminalStates whose reach finalizes the run as failed. Absent ⇒ every terminal is a success."},iterationBound:{type:"integer",exclusiveMinimum:0},vars:{type:"object",propertyNames:{pattern:"^[A-Za-z_][A-Za-z0-9_]*$"},additionalProperties:{type:"string"}},env:{type:"object",additionalProperties:!1,properties:{allow:{type:"array",items:{type:"string",pattern:"^[A-Za-z_][A-Za-z0-9_]*$"}}}},extensions:{type:"object",additionalProperties:!1,properties:{actions:{type:"array",items:{$ref:"#/$defs/relativeExtensionPath"}},guards:{type:"array",items:{$ref:"#/$defs/relativeExtensionPath"}}}},states:{type:"array",items:{type:"object",additionalProperties:!1,required:["id"],properties:{id:{type:"string",minLength:1},description:{type:"string"},pause:{type:"boolean",description:"When true, the engine pauses the run at this state for HITL (E3); resume with `spur workflow continue`."},onEnter:{type:"array",items:{$ref:"#/$defs/action"}},onExit:{type:"array",items:{$ref:"#/$defs/action"}}}}},transitions:{type:"array",items:{type:"object",additionalProperties:!1,required:["from","to"],properties:{from:{type:"string",minLength:1},to:{type:"string",minLength:1},terminalReason:{type:"string",description:"Closed terminal-reason enum declared when this edge finalizes the run (0937 R3; required for edges into failureStates)."},description:{type:"string"},trigger:{type:"string"},guard:{$ref:"#/$defs/guard"}}}}},$defs:{action:{type:"object",additionalProperties:!1,required:["kind"],properties:{kind:{type:"string",minLength:1},options:{type:"object",additionalProperties:!0},onError:{type:"string",enum:["fail","continue"],description:"Per-action error handling policy: 'fail' halts the run; 'continue' logs the failure and proceeds so transition guards can route the outcome."}}},guard:{type:"object",additionalProperties:!1,required:["kind"],properties:{kind:{type:"string",minLength:1},options:{type:"object",additionalProperties:!0}}},relativeExtensionPath:{type:"string",minLength:1,description:"Relative module path; absolute paths and '..' traversal are forbidden.",not:{anyOf:[{pattern:"^[/\\\\]"},{pattern:"^[A-Za-z]:[/\\\\]"},{pattern:"(^|[/\\\\])\\.\\.([/\\\\]|$)"}]}}}};var transition_flow_workflow_schema_default={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://github.com/gobing-ai/spur/schemas/transition-flow-workflow.schema.json",title:"@gobing-ai/ts-dual-workflow-engine Transition-flow Workflow",type:"object",additionalProperties:!1,required:["kind","name","initialNode","nodes","edges"],properties:{$schema:{type:"string"},kind:{const:"transition-flow"},name:{type:"string",minLength:1},version:{type:"string",minLength:1,description:"Optional behavior-neutral identity tag (0756). Absent = unversioned; present = a non-empty opaque literal surfaced as explicit(<literal>). Not parsed, ordered, or compatibility-checked; no registry."},description:{type:"string"},initialNode:{type:"string",minLength:1},terminalNodes:{type:"array",items:{type:"string",minLength:1}},iterationBound:{type:"integer",exclusiveMinimum:0},vars:{type:"object",propertyNames:{pattern:"^[A-Za-z_][A-Za-z0-9_]*$"},additionalProperties:{type:"string"}},env:{type:"object",additionalProperties:!1,properties:{allow:{type:"array",items:{type:"string",pattern:"^[A-Za-z_][A-Za-z0-9_]*$"}}}},extensions:{type:"object",additionalProperties:!1,properties:{actions:{type:"array",items:{$ref:"#/$defs/relativeExtensionPath"}},guards:{type:"array",items:{$ref:"#/$defs/relativeExtensionPath"}}}},nodes:{type:"array",items:{type:"object",additionalProperties:!1,required:["id"],properties:{id:{type:"string",minLength:1},description:{type:"string"},type:{enum:["action","gate","parallel","decision"]},action:{$ref:"#/$defs/action"}}}},edges:{type:"array",items:{type:"object",additionalProperties:!1,required:["from","to"],properties:{from:{type:"string",minLength:1},to:{type:"string",minLength:1},description:{type:"string"},condition:{$ref:"#/$defs/guard"}}}}},$defs:{action:{type:"object",additionalProperties:!1,required:["kind"],properties:{kind:{type:"string",minLength:1},options:{type:"object",additionalProperties:!0},onError:{type:"string",enum:["fail","continue"],description:"Per-action error handling policy: 'fail' halts the run; 'continue' logs the failure and proceeds so edge conditions can route the outcome."}}},guard:{type:"object",additionalProperties:!1,required:["kind"],properties:{kind:{type:"string",minLength:1},options:{type:"object",additionalProperties:!0}}},relativeExtensionPath:{type:"string",minLength:1,description:"Relative module path; absolute paths and '..' traversal are forbidden.",not:{anyOf:[{pattern:"^[/\\\\]"},{pattern:"^[A-Za-z]:[/\\\\]"},{pattern:"(^|[/\\\\])\\.\\.([/\\\\]|$)"}]}}}};var EMBEDDED_SPUR_SCHEMAS=new Map([["schemas/spur-config.schema.json",JSON.stringify(spur_config_schema_default)],["schemas/section-matrix.schema.json",JSON.stringify(section_matrix_schema_default)],["schemas/state-machine-workflow.schema.json",JSON.stringify(state_machine_workflow_schema_default)],["schemas/transition-flow-workflow.schema.json",JSON.stringify(transition_flow_workflow_schema_default)]]);export{validateFeatureVerificationReceipt,startFeatureVerificationReceipt,splitLaunchCommand,resolveWorkflowDefinition,resolveDecideDecisionMakerEnabled,readProofInputContents,openInlineRunProjectDb,featureReceiptPaths,createWorkflowActionTraceWriter,createOrAttachInlineRun,computeProofInputFingerprint,completeFeatureVerificationReceipt,captureFeatureReceiptDigest,RunDao,EMBEDDED_SPUR_SCHEMAS,DEFAULT_FEATURE_VERIFICATION_CMD,ArtifactDao};