@runcofactor/cli 0.15.1 → 0.16.0

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 (123) hide show
  1. package/dist/{account-62I7FG5G.js → account-ZMV7NEFM.js} +4 -4
  2. package/dist/account-ZMV7NEFM.js.map +1 -0
  3. package/dist/{api-catalog-CAJUASVC.js → api-catalog-6HNOGVPA.js} +3 -3
  4. package/dist/{attachment-RL4AZUJE.js → attachment-QAHR54HQ.js} +3 -3
  5. package/dist/{augmentor-GAF3MFY6.js → augmentor-7T3L6ZR4.js} +3 -3
  6. package/dist/{chunk-26U3DGUM.js → chunk-7YJTQCPX.js} +3 -5
  7. package/dist/chunk-7YJTQCPX.js.map +1 -0
  8. package/dist/{chunk-PXFDH6YL.js → chunk-A4ISG3VX.js} +55 -15
  9. package/dist/{chunk-PXFDH6YL.js.map → chunk-A4ISG3VX.js.map} +1 -1
  10. package/dist/{chunk-5R4HMSNX.js → chunk-AI3Y3AZH.js} +24834 -24813
  11. package/dist/chunk-AI3Y3AZH.js.map +1 -0
  12. package/dist/{chunk-HKQ5XQAQ.js → chunk-CEXV3MOC.js} +3 -3
  13. package/dist/{chunk-VKBTI5EF.js → chunk-D6AVOPOS.js} +2 -2
  14. package/dist/{chunk-ZXRVFFCY.js → chunk-DT2CEH2V.js} +2 -2
  15. package/dist/{chunk-IWKJQZJQ.js → chunk-GZVCNYR4.js} +55 -55
  16. package/dist/chunk-GZVCNYR4.js.map +1 -0
  17. package/dist/{chunk-CJEKEW7R.js → chunk-LFFWD5JZ.js} +2 -2
  18. package/dist/{chunk-UZ2ZA5A6.js → chunk-RGDIVW3O.js} +2 -2
  19. package/dist/{chunk-CFJXYPTF.js → chunk-UAJUZLDE.js} +11 -3
  20. package/dist/chunk-UAJUZLDE.js.map +1 -0
  21. package/dist/{credential-JGVSEGVH.js → credential-X6QKX473.js} +3 -3
  22. package/dist/{credential-template-CWWMOKB2.js → credential-template-GD3D4MBI.js} +3 -3
  23. package/dist/{debug-workflow-BXRU72YZ.js → debug-workflow-AAEOAME2.js} +6 -6
  24. package/dist/{src-CV57ZD6I.js → dist-QLTVBUMD.js} +7 -9
  25. package/dist/{docs-PVBXPTGR.js → docs-BVUEXBY3.js} +3 -3
  26. package/dist/{environment-WZKIO3R3.js → environment-WE7VVE6I.js} +3 -3
  27. package/dist/{feature-flag-K5REGGDY.js → feature-flag-VJO2TJFT.js} +9 -8
  28. package/dist/feature-flag-VJO2TJFT.js.map +1 -0
  29. package/dist/index.js +129 -44
  30. package/dist/index.js.map +1 -1
  31. package/dist/{init-FFUZO5D7.js → init-RQHHKJJD.js} +8 -8
  32. package/dist/{install-XRKEQAFZ.js → install-CQLHNZ6U.js} +3 -3
  33. package/dist/{issues-I3V6GEXU.js → issues-HK2JA5JS.js} +3 -3
  34. package/dist/{knobs-6WLJMB44.js → knobs-ETJAV6YM.js} +3 -3
  35. package/dist/{list-PHC7VYNS.js → list-F6DGGW3Z.js} +3 -3
  36. package/dist/{local-VGYRSW22.js → local-CMAY54I5.js} +5 -5
  37. package/dist/{login-QPU2BKG2.js → login-6CKG664C.js} +8 -8
  38. package/dist/{mcp-LA452TOA.js → mcp-GC2WOOZO.js} +5 -6
  39. package/dist/{mcp-LA452TOA.js.map → mcp-GC2WOOZO.js.map} +1 -1
  40. package/dist/metrics-IXICURAA.js +367 -0
  41. package/dist/metrics-IXICURAA.js.map +1 -0
  42. package/dist/{product-RSZV5HMB.js → product-BUJWPYKB.js} +4 -3
  43. package/dist/product-BUJWPYKB.js.map +1 -0
  44. package/dist/{property-YP4GHQAR.js → property-4EXPWRNT.js} +3 -3
  45. package/dist/{record-KWKHP2ZY.js → record-HL4QA7OX.js} +4 -4
  46. package/dist/{record-KWKHP2ZY.js.map → record-HL4QA7OX.js.map} +1 -1
  47. package/dist/{release-NDRHPW6V.js → release-2SMK5Y3V.js} +3 -3
  48. package/dist/{sandbox-OOCANWOG.js → sandbox-ORAPKOH3.js} +3 -3
  49. package/dist/{scenarios-2HRLCGFY.js → scenarios-DM5FDCAF.js} +3 -3
  50. package/dist/{session-M4ULYDYP.js → session-X6IYGWYG.js} +14 -16
  51. package/dist/{session-M4ULYDYP.js.map → session-X6IYGWYG.js.map} +1 -1
  52. package/dist/{skill-4DGPRDUC.js → skill-ZU5V2EE5.js} +24 -14
  53. package/dist/skill-ZU5V2EE5.js.map +1 -0
  54. package/dist/skills/optimize-cache/SKILL.md +9 -3
  55. package/dist/{spec-XZ2TKUFZ.js → spec-KO5QD6AY.js} +3 -3
  56. package/dist/{src-HL7HEJIW.js → src-DSD34JIX.js} +2 -2
  57. package/dist/{src-2FK3JHGW.js → src-HTGNKBUF.js} +15 -7
  58. package/dist/{src-2FK3JHGW.js.map → src-HTGNKBUF.js.map} +1 -1
  59. package/dist/{src-OU7544PM.js → src-PDYXACRP.js} +2 -2
  60. package/dist/{start-IYKF3C3X.js → start-2ECN4LX5.js} +6 -6
  61. package/dist/{tag-T45MMSCH.js → tag-R5I72HJ6.js} +4 -4
  62. package/dist/{task-MCUHAVTD.js → task-V3JMSJIM.js} +3 -3
  63. package/dist/{test-suite-BICBRSBP.js → test-suite-NOYVK6YX.js} +5 -5
  64. package/dist/{trace-2BAPMYAS.js → trace-NOYEKNO4.js} +4 -5
  65. package/dist/{triage-M3RZ2ASB.js → triage-4RFATHBE.js} +4 -4
  66. package/dist/utilities-3WMXE743.js +441 -0
  67. package/dist/utilities-3WMXE743.js.map +1 -0
  68. package/dist/{workflow-4J23FV7K.js → workflow-DC7WOTTW.js} +13 -17
  69. package/dist/workflow-DC7WOTTW.js.map +1 -0
  70. package/dist/{workflow-cache-XPSK6KC7.js → workflow-cache-SDSI6SMF.js} +6 -6
  71. package/dist/{workflow-cache-XPSK6KC7.js.map → workflow-cache-SDSI6SMF.js.map} +1 -1
  72. package/dist/{workflow-debug-W4USZH35.js → workflow-debug-6UQYP67Q.js} +6 -7
  73. package/dist/{workflow-debug-W4USZH35.js.map → workflow-debug-6UQYP67Q.js.map} +1 -1
  74. package/dist/{workflow-proposals-5E3DTYZB.js → workflow-proposals-67AVGMHX.js} +6 -6
  75. package/package.json +1 -1
  76. package/dist/account-62I7FG5G.js.map +0 -1
  77. package/dist/chunk-26U3DGUM.js.map +0 -1
  78. package/dist/chunk-5R4HMSNX.js.map +0 -1
  79. package/dist/chunk-CFJXYPTF.js.map +0 -1
  80. package/dist/chunk-IWKJQZJQ.js.map +0 -1
  81. package/dist/chunk-KRWRUU6R.js +0 -114
  82. package/dist/chunk-KRWRUU6R.js.map +0 -1
  83. package/dist/feature-flag-K5REGGDY.js.map +0 -1
  84. package/dist/pdf-extract-YHE54XU4.js +0 -13
  85. package/dist/product-RSZV5HMB.js.map +0 -1
  86. package/dist/skill-4DGPRDUC.js.map +0 -1
  87. package/dist/triage-M3RZ2ASB.js.map +0 -1
  88. package/dist/workflow-4J23FV7K.js.map +0 -1
  89. /package/dist/{api-catalog-CAJUASVC.js.map → api-catalog-6HNOGVPA.js.map} +0 -0
  90. /package/dist/{attachment-RL4AZUJE.js.map → attachment-QAHR54HQ.js.map} +0 -0
  91. /package/dist/{augmentor-GAF3MFY6.js.map → augmentor-7T3L6ZR4.js.map} +0 -0
  92. /package/dist/{chunk-HKQ5XQAQ.js.map → chunk-CEXV3MOC.js.map} +0 -0
  93. /package/dist/{chunk-VKBTI5EF.js.map → chunk-D6AVOPOS.js.map} +0 -0
  94. /package/dist/{chunk-ZXRVFFCY.js.map → chunk-DT2CEH2V.js.map} +0 -0
  95. /package/dist/{chunk-CJEKEW7R.js.map → chunk-LFFWD5JZ.js.map} +0 -0
  96. /package/dist/{chunk-UZ2ZA5A6.js.map → chunk-RGDIVW3O.js.map} +0 -0
  97. /package/dist/{credential-JGVSEGVH.js.map → credential-X6QKX473.js.map} +0 -0
  98. /package/dist/{credential-template-CWWMOKB2.js.map → credential-template-GD3D4MBI.js.map} +0 -0
  99. /package/dist/{debug-workflow-BXRU72YZ.js.map → debug-workflow-AAEOAME2.js.map} +0 -0
  100. /package/dist/{pdf-extract-YHE54XU4.js.map → dist-QLTVBUMD.js.map} +0 -0
  101. /package/dist/{docs-PVBXPTGR.js.map → docs-BVUEXBY3.js.map} +0 -0
  102. /package/dist/{environment-WZKIO3R3.js.map → environment-WE7VVE6I.js.map} +0 -0
  103. /package/dist/{init-FFUZO5D7.js.map → init-RQHHKJJD.js.map} +0 -0
  104. /package/dist/{install-XRKEQAFZ.js.map → install-CQLHNZ6U.js.map} +0 -0
  105. /package/dist/{issues-I3V6GEXU.js.map → issues-HK2JA5JS.js.map} +0 -0
  106. /package/dist/{knobs-6WLJMB44.js.map → knobs-ETJAV6YM.js.map} +0 -0
  107. /package/dist/{list-PHC7VYNS.js.map → list-F6DGGW3Z.js.map} +0 -0
  108. /package/dist/{local-VGYRSW22.js.map → local-CMAY54I5.js.map} +0 -0
  109. /package/dist/{login-QPU2BKG2.js.map → login-6CKG664C.js.map} +0 -0
  110. /package/dist/{property-YP4GHQAR.js.map → property-4EXPWRNT.js.map} +0 -0
  111. /package/dist/{release-NDRHPW6V.js.map → release-2SMK5Y3V.js.map} +0 -0
  112. /package/dist/{sandbox-OOCANWOG.js.map → sandbox-ORAPKOH3.js.map} +0 -0
  113. /package/dist/{scenarios-2HRLCGFY.js.map → scenarios-DM5FDCAF.js.map} +0 -0
  114. /package/dist/{spec-XZ2TKUFZ.js.map → spec-KO5QD6AY.js.map} +0 -0
  115. /package/dist/{src-HL7HEJIW.js.map → src-DSD34JIX.js.map} +0 -0
  116. /package/dist/{src-CV57ZD6I.js.map → src-PDYXACRP.js.map} +0 -0
  117. /package/dist/{start-IYKF3C3X.js.map → start-2ECN4LX5.js.map} +0 -0
  118. /package/dist/{src-OU7544PM.js.map → tag-R5I72HJ6.js.map} +0 -0
  119. /package/dist/{task-MCUHAVTD.js.map → task-V3JMSJIM.js.map} +0 -0
  120. /package/dist/{test-suite-BICBRSBP.js.map → test-suite-NOYVK6YX.js.map} +0 -0
  121. /package/dist/{tag-T45MMSCH.js.map → trace-NOYEKNO4.js.map} +0 -0
  122. /package/dist/{trace-2BAPMYAS.js.map → triage-4RFATHBE.js.map} +0 -0
  123. /package/dist/{workflow-proposals-5E3DTYZB.js.map → workflow-proposals-67AVGMHX.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../canary-spec/src/parse.ts","../../canary-spec/src/grammar.ts","../../canary-spec/src/lint.ts","../../canary-spec/src/input-refs.ts","../../canary-spec/src/emit.ts","../../canary-spec/src/node-hash.ts","../../canary-spec/src/diff.ts","../../canary-spec/src/pull.ts","../../canary-spec/src/api-sequence-file.ts","../../canary-spec/src/writeback.ts"],"sourcesContent":["/**\n * Parse a `.canary.md` file into a SpecAst.\n *\n * The grammar is constrained enough that a hand-rolled parser stays small and\n * keeps the CLI bundle thin (no remark/unified pull-in). We tokenize lines,\n * split on H2 headings, and dispatch by section name. Frontmatter parses as\n * YAML; structured per-node bullets are parsed inline.\n *\n * @module spec/parse\n */\n\nimport yaml from 'yaml';\nimport type { AssertionSeverity } from '@chatsdet/types';\nimport {\n type CredentialRef,\n type AttachmentDecl,\n type DeclaredOutput,\n type Frontmatter,\n FrontmatterSchema,\n type InputDecl,\n type JourneyNode,\n type Scenario,\n type SpecAst,\n type SpecIssue,\n} from './grammar.js';\n\nconst FRONTMATTER_FENCE = /^---\\s*$/;\n\nexport type ParseResult = { ok: true; ast: SpecAst } | { ok: false; issues: SpecIssue[] };\n\nexport function parseSpec(source: string): ParseResult {\n const issues: SpecIssue[] = [];\n const lines = source.split(/\\r?\\n/);\n\n // 1. Frontmatter\n const fmEnd = findFrontmatterEnd(lines);\n if (fmEnd === -1) {\n return fail([{ severity: 'error', message: 'Spec must begin with `---` frontmatter.' }]);\n }\n const rawFrontmatter = lines.slice(1, fmEnd).join('\\n');\n let frontmatter: Frontmatter;\n try {\n const parsed = yaml.parse(rawFrontmatter) ?? {};\n frontmatter = FrontmatterSchema.parse(normalizeActor(parsed));\n } catch (err) {\n return fail([\n {\n severity: 'error',\n message: `Frontmatter is invalid: ${err instanceof Error ? err.message : String(err)}`,\n line: 1,\n },\n ]);\n }\n\n // 2. Body — split into H1 (title, ignored — frontmatter.name is authoritative)\n // and H2 sections.\n const bodyStart = fmEnd + 1;\n const sections = splitH2Sections(lines.slice(bodyStart), bodyStart);\n\n let spirit: string | undefined;\n let preflight: string | undefined;\n let cleanup: string | undefined;\n let inputs: InputDecl[] = [];\n let scenarios: Scenario[] = [];\n let attachments: AttachmentDecl[] = [];\n let declaredOutputs: DeclaredOutput[] = [];\n let journey: JourneyNode[] = [];\n\n for (const section of sections) {\n const heading = section.heading.toLowerCase();\n if (heading.startsWith('spirit')) spirit = stripBlockquoteOrPlain(section.body).trim() || undefined;\n else if (heading.startsWith('preflight')) preflight = section.body.trim() || undefined;\n else if (heading.startsWith('cleanup')) cleanup = section.body.trim() || undefined;\n else if (heading.startsWith('inputs')) inputs = parseInputs(section.body, section.startLine, issues);\n else if (heading.startsWith('scenarios')) scenarios = parseScenarios(section.body, section.startLine, issues);\n else if (heading.startsWith('attachments')) attachments = parseAttachments(section.body, section.startLine, issues);\n else if (heading.startsWith('declared outputs')) declaredOutputs = parseDeclaredOutputs(section.body, section.startLine, issues);\n else if (heading.startsWith('journey')) journey = parseJourney(section.body, section.startLine, issues);\n else if (heading.startsWith('metadata')) {\n // Opaque round-trip block — ignored by parse for now (compiler handles it).\n } else {\n issues.push({\n severity: 'warn',\n message: `Unknown H2 section \"${section.heading}\" — ignored.`,\n line: section.startLine,\n });\n }\n }\n\n if (journey.length === 0) {\n issues.push({\n severity: 'error',\n message: 'Spec must include a `## Journey` section with at least one node.',\n });\n }\n\n if (issues.some((i) => i.severity === 'error')) return { ok: false, issues };\n\n return {\n ok: true,\n ast: {\n frontmatter,\n spirit,\n preflight,\n cleanup,\n inputs,\n scenarios,\n attachments,\n declaredOutputs,\n journey,\n },\n };\n}\n\nfunction fail(issues: SpecIssue[]): ParseResult {\n return { ok: false, issues };\n}\n\nfunction findFrontmatterEnd(lines: string[]): number {\n if (!FRONTMATTER_FENCE.test(lines[0] ?? '')) return -1;\n for (let i = 1; i < lines.length; i++) if (FRONTMATTER_FENCE.test(lines[i])) return i;\n return -1;\n}\n\n/**\n * Parse a credential-reference string into its discriminated form. Accepts:\n * \"admin\" -> { kind: 'template', role: 'admin' }\n * \"persona admin\" -> { kind: 'template', role: 'admin' }\n * \"template admin\" -> { kind: 'template', role: 'admin' }\n * \"credential admin-bob\" -> { kind: 'credential', name: 'admin-bob' }\n * \"seed-output qaUser\" -> { kind: 'seedOutput', ref: 'qaUser' }\n *\n * Used by both the frontmatter `actor:` field and mid-journey\n * `**Switch role to**` nodes so the two surfaces stay symmetric.\n */\nexport function parseCredentialRef(raw: string): CredentialRef {\n const trimmed = raw.trim();\n if (trimmed.startsWith('credential ')) {\n return { kind: 'credential', name: trimmed.slice('credential '.length).trim() };\n }\n if (trimmed.startsWith('seed-output ')) {\n return { kind: 'seedOutput', ref: trimmed.slice('seed-output '.length).trim() };\n }\n let explicitTemplatePrefix: 'template ' | 'persona ' | null = null;\n if (trimmed.startsWith('template ')) {\n explicitTemplatePrefix = 'template ';\n } else if (trimmed.startsWith('persona ')) {\n explicitTemplatePrefix = 'persona ';\n }\n const role = explicitTemplatePrefix\n ? trimmed.slice(explicitTemplatePrefix.length).trim()\n : trimmed;\n return { kind: 'template', role };\n}\n\nfunction normalizeActor(raw: Record<string, unknown>): Record<string, unknown> {\n const a = raw.actor;\n if (typeof a !== 'string') return raw;\n return { ...raw, actor: parseCredentialRef(a) };\n}\n\ntype Section = { heading: string; body: string; startLine: number };\n\nfunction splitH2Sections(lines: string[], offset: number): Section[] {\n const sections: Section[] = [];\n let current: { heading: string; body: string[]; startLine: number } | null = null;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const m = /^##\\s+(.+?)\\s*$/.exec(line);\n if (m) {\n if (current) sections.push({ heading: current.heading, body: current.body.join('\\n'), startLine: current.startLine });\n current = { heading: m[1], body: [], startLine: offset + i + 1 };\n continue;\n }\n if (current) current.body.push(line);\n // Pre-first-H2 content (typically the H1 title) is ignored.\n }\n if (current) sections.push({ heading: current.heading, body: current.body.join('\\n'), startLine: current.startLine });\n return sections;\n}\n\nfunction stripBlockquoteOrPlain(body: string): string {\n return body\n .split('\\n')\n .map((l) => (l.startsWith('> ') ? l.slice(2) : l.startsWith('>') ? l.slice(1) : l))\n .join('\\n');\n}\n\n/* ── ## Inputs ───────────────────────────────────────────────────────── */\n\nfunction parseInputs(body: string, startLine: number, issues: SpecIssue[]): InputDecl[] {\n const out: InputDecl[] = [];\n for (const { line, lineNo } of bulletLines(body, startLine)) {\n // `- credential <name>: <value>` or `- <name>: <value>`\n const credMatch = /^credential\\s+([A-Za-z0-9_-]+)\\s*:\\s*(.+)$/.exec(line);\n if (credMatch) {\n out.push({ name: credMatch[1], kind: 'credential', defaultValue: credMatch[2].trim() });\n continue;\n }\n const m = /^([A-Za-z0-9_-]+)\\s*:\\s*(.+)$/.exec(line);\n if (!m) {\n issues.push({ severity: 'warn', message: `Could not parse Inputs entry: \"${line}\"`, line: lineNo });\n continue;\n }\n out.push({ name: m[1], kind: 'value', defaultValue: stripQuotes(m[2].trim()) });\n }\n return out;\n}\n\n/* ── ## Scenarios ────────────────────────────────────────────────────── */\n\nfunction parseScenarios(body: string, startLine: number, issues: SpecIssue[]): Scenario[] {\n const out: Scenario[] = [];\n const blocks = splitH3Blocks(body, startLine);\n for (const block of blocks) {\n const headingRaw = block.heading;\n // Strip *(default)* and *(skip: …)* annotations\n let isDefault = false;\n let includeInSuite = true;\n let skipReason: string | undefined;\n let nameClean = headingRaw;\n const defaultMatch = /\\*\\(default\\)\\*/i.exec(headingRaw);\n if (defaultMatch) {\n isDefault = true;\n nameClean = nameClean.replace(defaultMatch[0], '').trim();\n }\n const skipMatch = /\\*\\(skip(?::\\s*([^)]+))?\\)\\*/i.exec(headingRaw);\n if (skipMatch) {\n includeInSuite = false;\n skipReason = (skipMatch[1] ?? '').trim() || undefined;\n nameClean = nameClean.replace(skipMatch[0], '').trim();\n }\n\n let bodyYaml: Record<string, unknown> = {};\n try {\n // Convert top-level bullets to YAML mapping by stripping the leading '- '\n const content = block.body\n .split('\\n')\n .map((l) => l.replace(/^-\\s+/, ''))\n .join('\\n');\n bodyYaml = (yaml.parse(content) ?? {}) as Record<string, unknown>;\n } catch (err) {\n issues.push({\n severity: 'warn',\n message: `Could not parse scenario \"${nameClean}\": ${err instanceof Error ? err.message : String(err)}`,\n line: block.startLine,\n });\n }\n\n out.push({\n name: nameClean,\n description: typeof bodyYaml.description === 'string' ? bodyYaml.description : undefined,\n isDefault,\n includeInSuite,\n skipReason,\n values: (bodyYaml.values ?? {}) as Record<string, string>,\n credentials: (bodyYaml.credentials ?? {}) as Record<string, string>,\n });\n }\n return out;\n}\n\n/* ── ## Attachments ──────────────────────────────────────────────────── */\n\nfunction parseAttachments(body: string, startLine: number, issues: SpecIssue[]): AttachmentDecl[] {\n const out: AttachmentDecl[] = [];\n for (const { line, lineNo } of bulletLines(body, startLine)) {\n const m = /^([A-Za-z0-9_-]+)\\s*:\\s*(.+)$/.exec(line);\n if (!m) {\n issues.push({ severity: 'warn', message: `Could not parse Attachments entry: \"${line}\"`, line: lineNo });\n continue;\n }\n out.push({ ref: m[1], source: m[2].trim() });\n }\n return out;\n}\n\n/* ── ## Declared Outputs ─────────────────────────────────────────────── */\n\nfunction parseDeclaredOutputs(\n body: string,\n startLine: number,\n issues: SpecIssue[],\n): DeclaredOutput[] {\n // Each top-level bullet introduces a dataKey; indented sub-bullets carry\n // optional `label:`, `property:`, `description:` fields. We round-trip\n // through YAML so multi-line descriptions or quoted values work without\n // bespoke escape handling.\n const out: DeclaredOutput[] = [];\n const lines = body.split('\\n');\n let i = 0;\n while (i < lines.length) {\n const m = /^-\\s+([A-Za-z0-9_-]+)\\s*$/.exec(lines[i].trim());\n if (!m) {\n i++;\n continue;\n }\n const dataKey = m[1];\n const block: string[] = [];\n i++;\n while (i < lines.length) {\n const raw = lines[i];\n // Sub-bullets must be indented; a non-indented bullet starts a new entry.\n if (/^-\\s/.test(raw)) break;\n const sub = /^\\s+-\\s+(.+)$/.exec(raw);\n if (sub) block.push(sub[1]);\n else if (raw.trim() === '') {\n // blank line — keep scanning, allows visual spacing inside an entry.\n } else {\n break;\n }\n i++;\n }\n let body: Record<string, unknown> = {};\n if (block.length > 0) {\n try {\n body = (yaml.parse(block.join('\\n')) ?? {}) as Record<string, unknown>;\n } catch (err) {\n issues.push({\n severity: 'warn',\n message: `Could not parse Declared Outputs entry \"${dataKey}\": ${err instanceof Error ? err.message : String(err)}`,\n line: startLine,\n });\n }\n }\n out.push({\n dataKey,\n label: typeof body.label === 'string' ? body.label : undefined,\n // Spec writes `property: <name>`; the AST uses `propertyName` to make\n // the name-vs-id distinction explicit (sync.ts resolves to id at compile).\n propertyName: typeof body.property === 'string' ? body.property : undefined,\n description: typeof body.description === 'string' ? body.description : undefined,\n });\n }\n return out;\n}\n\n/* ── ## Journey ──────────────────────────────────────────────────────── */\n\nfunction parseJourney(body: string, startLine: number, issues: SpecIssue[]): JourneyNode[] {\n const lines = body.split('\\n');\n return parseJourneyBlock(lines, 0, lines.length, /* baseIndent */ 0, startLine, issues).nodes;\n}\n\ntype BlockResult = { nodes: JourneyNode[]; nextIndex: number };\n\nfunction parseJourneyBlock(\n lines: string[],\n start: number,\n end: number,\n baseIndent: number,\n startLine: number,\n issues: SpecIssue[]\n): BlockResult {\n const nodes: JourneyNode[] = [];\n let i = start;\n while (i < end) {\n const raw = lines[i];\n const trimmed = raw.trim();\n if (!trimmed) {\n i++;\n continue;\n }\n const indent = leadingSpaces(raw);\n if (indent < baseIndent) break;\n\n const lineNo = startLine + i;\n\n // Extract `<!-- @id <uuid> -->` from the line if present. The compiler\n // writes these back after a successful create; on recompile they key\n // the diff against the live workflow's node UUIDs.\n const { stripped, nodeId } = extractNodeId(trimmed);\n\n // Block-level lead-in detection. Lead-ins start with `**…**`.\n const leadInMatch = /^\\*\\*([^*]+)\\*\\*\\s*(.*)$/.exec(stripped);\n if (!leadInMatch) {\n issues.push({\n severity: 'warn',\n message: `Unexpected line in Journey: \"${trimmed}\"`,\n line: lineNo,\n });\n i++;\n continue;\n }\n const leadIn = leadInMatch[1].trim();\n const remainder = leadInMatch[2].trim();\n const idMeta: { nodeId?: string; sourceLine?: number } = {\n sourceLine: lineNo,\n ...(nodeId ? { nodeId } : {}),\n };\n\n const lower = leadIn.toLowerCase();\n\n // ── If / Then / Else (condition) ─────────────────────────────────\n if (lower.startsWith('if')) {\n let expression = stripPunctuation(leadIn.replace(/^if\\b\\s*/i, '') + (remainder ? ' ' + remainder : '')).trim();\n i++;\n // Multi-line condition: when the lead-in carries no inline expression,\n // the expression is the following blockquote (preserves newlines).\n if (!expression) {\n const bq = readBlockquote(lines, i, end);\n if (bq) {\n expression = bq;\n i += countBlockquoteLines(lines, i, end);\n }\n }\n // Look for **Then:** and optional **Else:**\n const childIndent = baseIndent + 2;\n let thenBranch: JourneyNode[] = [];\n let elseBranch: JourneyNode[] = [];\n while (i < end) {\n const nextRaw = lines[i];\n const nextTrim = nextRaw.trim();\n if (!nextTrim) {\n i++;\n continue;\n }\n if (leadingSpaces(nextRaw) < baseIndent) break;\n const branch = /^\\*\\*(then|else):\\*\\*\\s*$/i.exec(nextTrim);\n if (!branch) break;\n i++;\n const sub = parseJourneyBlock(lines, i, end, childIndent, startLine, issues);\n if (branch[1].toLowerCase() === 'then') thenBranch = sub.nodes;\n else elseBranch = sub.nodes;\n i = sub.nextIndex;\n }\n nodes.push({ ...idMeta, kind: 'condition', expression, thenBranch, elseBranch });\n continue;\n }\n\n // ── Single-line nodes ────────────────────────────────────────────\n // The description blockquote may be separated from the lead-in by one or\n // more blank lines (common in hand-authored specs). Skip them when\n // detecting it, and fold the skipped blanks into the consumed count so\n // bullet collection starts *after* the blockquote. Without this, a blank\n // line before the `>` description makes readBlockquote miss it, leaving\n // readBullets pointed at the `>` line — so the action's bullets\n // (assertions, captures) are silently dropped.\n let descScan = i + 1;\n while (descScan < end && !lines[descScan].trim()) descScan++;\n const description = readBlockquote(lines, descScan, end);\n const descLineCount = description\n ? descScan - (i + 1) + countBlockquoteLines(lines, descScan, end)\n : 0;\n let consumedMain = 1 + descLineCount;\n\n if (lower.startsWith('navigate to')) {\n const url = stripPunctuation(remainder);\n nodes.push({ ...idMeta, kind: 'navigate', pageUrl: url || (description ?? '').trim() });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('switch role to')) {\n // Accept both `**Switch role to X**` (role inside the bold lead-in, what\n // `pull` emits) and `**Switch role to** X` (role outside the bold, more\n // natural to author by hand). For the latter, leadIn is exactly\n // `Switch role to` with no trailing whitespace for the `\\s+` to match,\n // so the strip leaves the prefix intact — detect that and fall back to\n // remainder instead of the stripped string.\n const stripped = leadIn.replace(/^switch role to\\s+/i, '').trim();\n const fromLeadIn = stripped && stripped.toLowerCase() !== 'switch role to' ? stripped : '';\n const rest = fromLeadIn || remainder;\n const credentialRef = parseCredentialRef(stripPunctuation(rest));\n nodes.push({ ...idMeta, kind: 'switchRole', credentialRef });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('wait')) {\n const dur = parseDuration(remainder || leadIn.replace(/^wait\\s*/i, ''));\n if (dur === null) {\n issues.push({ severity: 'error', message: `Could not parse Wait duration: \"${remainder}\"`, line: lineNo });\n } else {\n nodes.push({ ...idMeta, kind: 'wait', durationSeconds: dur });\n }\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('end')) {\n const outcome = lower.includes('fail') ? 'fail' : 'pass';\n nodes.push({ ...idMeta, kind: 'end', outcome });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('seed')) {\n const specName = stripPunctuation(remainder.replace(/^[`\"]|[`\"]$/g, '')) || stripPunctuation(leadIn.replace(/^seed\\s*/i, ''));\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const opts = parseKvBullets(subBullets.bullets);\n const inputs = parseSeedInputBullets(subBullets.bullets);\n nodes.push({ ...idMeta,\n kind: 'seed',\n specName,\n description,\n version: opts.version === 'latest' || opts.version === undefined ? opts.version as 'latest' | undefined : Number(opts.version),\n onFailure: opts.onFailure as 'block' | 'warn' | undefined,\n mode: opts.mode as 'recommended' | 'api' | 'browser' | undefined,\n apiTimeoutSeconds: opts.apiTimeoutSeconds === undefined ? undefined : Number(opts.apiTimeoutSeconds),\n scope: opts.scope as 'inline' | 'suite' | undefined,\n runTeardown: typeof opts.runTeardown === 'string' ? opts.runTeardown !== 'false' : undefined,\n inputs,\n });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('setup')) {\n const specName = stripPunctuation(remainder.replace(/^[`\"]|[`\"]$/g, '')) || stripPunctuation(leadIn.replace(/^setup\\s*/i, ''));\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const opts = parseKvBullets(subBullets.bullets);\n nodes.push({ ...idMeta,\n kind: 'setup',\n specName,\n description,\n version: opts.version === 'latest' || opts.version === undefined ? opts.version as 'latest' | undefined : Number(opts.version),\n mode: opts.mode as 'inline' | 'suite' | undefined,\n });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('action')) {\n const title = leadIn.replace(/^action\\s*[—-]\\s*/i, '').trim() || remainder;\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const action = parseActionBullets(subBullets.bullets, lineNo, issues);\n nodes.push({ ...idMeta,\n kind: 'action',\n title,\n description,\n ...action,\n });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('assert audio')) {\n const label = leadIn.replace(/^assert audio\\s*/i, '').trim() || remainder;\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const opts = parseKvBullets(subBullets.bullets);\n nodes.push({ ...idMeta,\n kind: 'audioAssertion',\n label,\n description,\n severity: (opts.severity as AssertionSeverity) ?? 'fail',\n prompt: typeof opts.prompt === 'string' ? opts.prompt : undefined,\n model: opts.model as 'gpt-audio' | 'gemini-2.x' | undefined,\n minDurationMs: numOpt(opts.minDurationMs),\n maxDurationMs: numOpt(opts.maxDurationMs),\n minRmsDb: numOpt(opts.minRmsDb),\n silenceFractionMax: numOpt(opts.silenceFractionMax),\n reference: typeof opts.reference === 'string' ? opts.reference : undefined,\n envelopeCorrelationMin: numOpt(opts.envelopeCorrelationMin),\n });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('assert')) {\n const condition = leadIn.replace(/^assert\\s*/i, '').trim() + (remainder ? ' ' + remainder : '');\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const opts = parseKvBullets(subBullets.bullets);\n nodes.push({ ...idMeta,\n kind: 'assertion',\n condition: stripPunctuation(condition),\n description,\n severity: (opts.severity as AssertionSeverity) ?? 'fatal',\n expectedOutcome: typeof opts.expectedOutcome === 'string' ? opts.expectedOutcome : undefined,\n alwaysUseAgent: opts.alwaysUseAgent === 'true' ? true : undefined,\n });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('play audio')) {\n const ref = leadIn.replace(/^play audio\\s*/i, '').trim() || remainder;\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const opts = parseKvBullets(subBullets.bullets);\n nodes.push({ ...idMeta,\n kind: 'audio',\n attachmentRef: stripPunctuation(ref),\n description,\n loop: opts.loop === 'true' ? true : undefined,\n waitForCompletion: opts.waitForCompletion === 'false' ? false : undefined,\n label: typeof opts.label === 'string' ? opts.label : undefined,\n });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('notify')) {\n const m = /^notify\\s+([A-Za-z0-9_-]+)\\s*:?\\s*(.*)$/i.exec(leadIn + (remainder ? ' ' + remainder : ''));\n if (!m) {\n issues.push({ severity: 'error', message: `Could not parse Notify lead-in: \"${leadIn}\"`, line: lineNo });\n } else {\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const opts = parseKvBullets(subBullets.bullets);\n nodes.push({ ...idMeta,\n kind: 'notification',\n channel: m[1],\n to: stripPunctuation(stripBackticks(m[2])),\n subject: typeof opts.subject === 'string' ? opts.subject : undefined,\n body: description ?? '',\n attach: typeof opts.attach === 'string' ? opts.attach : undefined,\n });\n }\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('sandbox action')) {\n const slug = stripPunctuation(\n leadIn.replace(/^sandbox action\\s*[—-]\\s*/i, '').trim() || remainder\n );\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const opts = parseKvBullets(subBullets.bullets);\n const params = parseActionParamBullets(subBullets.bullets);\n nodes.push({ ...idMeta,\n kind: 'sandboxAction',\n actionSlug: slug,\n description,\n label: typeof opts.label === 'string' ? opts.label : undefined,\n params,\n outputs:\n typeof opts.outputs === 'string'\n ? opts.outputs\n .split(',')\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n : undefined,\n });\n i += consumedMain;\n continue;\n }\n\n if (lower.startsWith('api sequence')) {\n const title = leadIn.replace(/^api sequence\\s*[—-]\\s*/i, '').trim();\n const subBullets = readBullets(lines, i + 1 + descLineCount, end, baseIndent);\n consumedMain += subBullets.consumed;\n const opts = parseKvBullets(subBullets.bullets);\n nodes.push({ ...idMeta,\n kind: 'apiSequence',\n title,\n apiEndpointContext: description ?? '',\n credentialInputName: typeof opts.credential === 'string' ? opts.credential : undefined,\n // Sidecar reference (e.g. `- apiSequence: ./sequences/x.yaml`).\n // Resolved by the CLI at compile/diff time relative to the spec file\n // path; parse.ts has no filesystem context so we just carry the string.\n sidecar: typeof opts.apiSequence === 'string' ? opts.apiSequence : undefined,\n });\n i += consumedMain;\n continue;\n }\n\n issues.push({ severity: 'error', message: `Unrecognized lead-in: \"${leadIn}\"`, line: lineNo });\n i++;\n }\n return { nodes, nextIndex: i };\n}\n\nfunction leadingSpaces(s: string): number {\n let n = 0;\n while (n < s.length && s[n] === ' ') n++;\n return n;\n}\n\nfunction stripPunctuation(s: string): string {\n return s.replace(/[`\"]/g, '').replace(/\\.$/, '').trim();\n}\n\nfunction stripBackticks(s: string): string {\n return s.replace(/`/g, '').trim();\n}\n\nfunction stripQuotes(s: string): string {\n if ((s.startsWith('\"') && s.endsWith('\"')) || (s.startsWith(\"'\") && s.endsWith(\"'\"))) {\n return s.slice(1, -1);\n }\n return s;\n}\n\nfunction parseDuration(s: string): number | null {\n const m = /^(\\d+(?:\\.\\d+)?)\\s*(s|m|h)?\\.?$/i.exec(s.trim());\n if (!m) return null;\n const n = Number(m[1]);\n const unit = (m[2] ?? 's').toLowerCase();\n const seconds = unit === 'h' ? n * 3600 : unit === 'm' ? n * 60 : n;\n return Math.round(seconds);\n}\n\nfunction readBlockquote(lines: string[], start: number, end: number): string | undefined {\n if (start >= end) return undefined;\n if (!lines[start].trimStart().startsWith('>')) return undefined;\n const out: string[] = [];\n for (let i = start; i < end; i++) {\n const t = lines[i].trimStart();\n if (!t.startsWith('>')) break;\n out.push(t.replace(/^>\\s?/, ''));\n }\n return out.join('\\n').trim();\n}\n\nfunction countBlockquoteLines(lines: string[], start: number, end: number): number {\n let n = 0;\n for (let i = start; i < end; i++) {\n if (!lines[i].trimStart().startsWith('>')) break;\n n++;\n }\n return n;\n}\n\nfunction readBullets(\n lines: string[],\n start: number,\n end: number,\n baseIndent: number\n): { bullets: string[]; consumed: number } {\n const bullets: string[] = [];\n let i = start;\n while (i < end) {\n const raw = lines[i];\n const trimmed = raw.trim();\n if (!trimmed) {\n i++;\n continue;\n }\n if (!trimmed.startsWith('- ')) break;\n if (leadingSpaces(raw) < baseIndent) break;\n bullets.push(trimmed.slice(2).trim());\n i++;\n }\n return { bullets, consumed: i - start };\n}\n\nfunction bulletLines(body: string, startLine: number): { line: string; lineNo: number }[] {\n const out: { line: string; lineNo: number }[] = [];\n const lines = body.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const t = lines[i].trim();\n if (t.startsWith('- ')) out.push({ line: t.slice(2).trim(), lineNo: startLine + i });\n }\n return out;\n}\n\nfunction splitH3Blocks(body: string, startLine: number): { heading: string; body: string; startLine: number }[] {\n const out: { heading: string; body: string; startLine: number }[] = [];\n const lines = body.split('\\n');\n let cur: { heading: string; body: string[]; startLine: number } | null = null;\n for (let i = 0; i < lines.length; i++) {\n const m = /^###\\s+(.+?)\\s*$/.exec(lines[i]);\n if (m) {\n if (cur) out.push({ heading: cur.heading, body: cur.body.join('\\n'), startLine: cur.startLine });\n cur = { heading: m[1], body: [], startLine: startLine + i };\n continue;\n }\n if (cur) cur.body.push(lines[i]);\n }\n if (cur) out.push({ heading: cur.heading, body: cur.body.join('\\n'), startLine: cur.startLine });\n return out;\n}\n\n/* ── Action sub-bullet parser ────────────────────────────────────────── */\n\nfunction parseActionBullets(\n bullets: string[],\n lineNo: number,\n issues: SpecIssue[]\n): {\n fields: { name: string; type?: string; value: string }[];\n capture: string[];\n assertions: { condition: string; severity: AssertionSeverity; agentic?: boolean }[];\n captureAudio?: boolean;\n captureLabel?: string;\n captureExtraMs?: number;\n alwaysUseAgent?: boolean;\n} {\n const fields: { name: string; type?: string; value: string }[] = [];\n const capture: string[] = [];\n const assertions: { condition: string; severity: AssertionSeverity; agentic?: boolean }[] = [];\n let captureAudio: boolean | undefined;\n let captureLabel: string | undefined;\n let captureExtraMs: number | undefined;\n let alwaysUseAgent: boolean | undefined;\n\n for (const b of bullets) {\n // - field <name> [(type)]: <value>\n // <name> can be quoted, a bare identifier, or a plain multi-word label.\n const fieldM = /^field\\s+(?:\"([^\"]+)\"|(.+?))\\s*(?:\\(([^)]+)\\))?\\s*:\\s*(.+)$/i.exec(b);\n if (fieldM) {\n const name = (fieldM[1] ?? fieldM[2] ?? '').trim();\n fields.push({\n name,\n type: fieldM[3],\n value: stripQuotes(fieldM[4].trim()),\n });\n continue;\n }\n // - capture: <name> OR - capture <name>\n const capM = /^capture\\s*:?\\s*(.+)$/i.exec(b);\n if (capM) {\n capture.push(stripQuotes(capM[1].trim()));\n continue;\n }\n // - assert (severity[, agentic]): <condition>\n const assertM = /^assert\\s*\\(([^)]+)\\)\\s*:\\s*(.+)$/i.exec(b);\n if (assertM) {\n const flags = assertM[1].split(',').map((s) => s.trim().toLowerCase());\n const severity: AssertionSeverity = flags.includes('fatal')\n ? 'fatal'\n : flags.includes('fail')\n ? 'fail'\n : flags.includes('warn')\n ? 'warn'\n : 'fatal';\n const agentic = flags.includes('agentic') || undefined;\n assertions.push({ condition: stripQuotes(assertM[2].trim()), severity, agentic });\n continue;\n }\n const kv = /^([A-Za-z][A-Za-z0-9]*)\\s*:\\s*(.+)$/.exec(b);\n if (kv) {\n const key = kv[1];\n const value = kv[2].trim();\n if (key === 'captureAudio') captureAudio = value === 'true';\n else if (key === 'captureLabel') captureLabel = stripQuotes(value);\n else if (key === 'captureExtraMs') captureExtraMs = Number(value);\n else if (key === 'alwaysUseAgent') alwaysUseAgent = value === 'true';\n else issues.push({ severity: 'warn', message: `Unknown action option \"${key}\"`, line: lineNo });\n continue;\n }\n issues.push({ severity: 'warn', message: `Could not parse action bullet: \"${b}\"`, line: lineNo });\n }\n return { fields, capture, assertions, captureAudio, captureLabel, captureExtraMs, alwaysUseAgent };\n}\n\n/* ── Generic key:value bullet parser ─────────────────────────────────── */\n\nfunction parseKvBullets(bullets: string[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const b of bullets) {\n const m = /^([A-Za-z][A-Za-z0-9_-]*)\\s*:\\s*(.+)$/.exec(b);\n if (!m) continue;\n out[m[1]] = stripQuotes(m[2].trim());\n }\n return out;\n}\n\n/**\n * Parse `input.<name>: <value>` sub-bullets on a seed node into a value-input\n * override map. Dotted keys are intentionally outside parseKvBullets' grammar\n * so plain kv consumers never see them. Returns undefined when none present.\n */\nfunction parseSeedInputBullets(bullets: string[]): Record<string, string> | undefined {\n let out: Record<string, string> | undefined;\n for (const b of bullets) {\n const m = /^input\\.([A-Za-z_][A-Za-z0-9_]*)\\s*:\\s*(.+)$/.exec(b);\n if (!m) continue;\n out ??= {};\n out[m[1]] = stripQuotes(m[2].trim());\n }\n return out;\n}\n\n/**\n * Parse `param.<name>: <value>` sub-bullets on a sandbox action node into an\n * input-param map. Mirrors {@link parseSeedInputBullets}; dotted keys are\n * intentionally outside parseKvBullets' grammar. Returns undefined when none.\n */\nfunction parseActionParamBullets(bullets: string[]): Record<string, string> | undefined {\n let out: Record<string, string> | undefined;\n for (const b of bullets) {\n const m = /^param\\.([A-Za-z_][A-Za-z0-9_]*)\\s*:\\s*(.+)$/.exec(b);\n if (!m) continue;\n out ??= {};\n out[m[1]] = stripQuotes(m[2].trim());\n }\n return out;\n}\n\nfunction numOpt(v: string | undefined): number | undefined {\n if (v === undefined) return undefined;\n const n = Number(v);\n return Number.isFinite(n) ? n : undefined;\n}\n\nconst NODE_ID_RE =\n /\\s*<!--\\s*@id\\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\s*-->/i;\n\n/**\n * Strip a trailing `<!-- @id <uuid> -->` comment from a lead-in line and\n * return both the cleaned line and the extracted UUID. If no comment is\n * present, returns the line unchanged and nodeId = undefined.\n */\nexport function extractNodeId(line: string): { stripped: string; nodeId: string | undefined } {\n const m = NODE_ID_RE.exec(line);\n if (!m) return { stripped: line, nodeId: undefined };\n return { stripped: line.replace(NODE_ID_RE, '').trimEnd(), nodeId: m[1].toLowerCase() };\n}\n","/**\n * Zod schemas for the parsed `.canary.md` spec AST.\n *\n * The spec format is a single workflow per file. Frontmatter carries the strict\n * top-level fields; H2 sections carry prose (Spirit/Preflight/Cleanup) and\n * structured lists (Inputs, Scenarios, Attachments). The Journey body is a\n * linear sequence of bold lead-in nodes that map 1:1 to canary node types.\n *\n * @module spec/grammar\n */\n\nimport { InlineAssertionSchema } from '@chatsdet/types';\nimport { z } from 'zod';\n\n/* ── Frontmatter ─────────────────────────────────────────────────────── */\n\n/**\n * A reference to either a credential template (resolved at run/suite level)\n * or a specific raw credential by name. Used for both the frontmatter\n * `actor:` field and mid-journey `**Switch role to**` nodes.\n */\nexport const CredentialRefSchema = z.union([\n z.object({ kind: z.literal('template'), role: z.string().min(1) }),\n z.object({ kind: z.literal('credential'), name: z.string().min(1) }),\n /**\n * `seed-output <ref>` — the journey runs as a credential that was provisioned\n * by an upstream seed workflow. The `ref` is the seed's `dataKey`; the\n * runtime resolves it at suite-prep time via the seed_outputs lookup.\n */\n z.object({ kind: z.literal('seedOutput'), ref: z.string().min(1) }),\n]);\nexport type CredentialRef = z.infer<typeof CredentialRefSchema>;\n\nexport type Actor = CredentialRef;\n\nexport const FrontmatterSchema = z\n .object({\n name: z.string().min(1),\n /**\n * Workflow ID this spec is bound to. Absent on first compile; the\n * compiler writes it back into the frontmatter after a successful\n * create. On recompile, the compiler keys the diff on this ID.\n */\n workflowId: z.string().uuid().optional(),\n // 'published' is a deprecated legacy value (pre approval/promotion split);\n // accepted for old spec files and normalized to 'draft'.\n status: z\n .enum(['draft', 'approved', 'published'])\n .transform((s): 'draft' | 'approved' => (s === 'published' ? 'draft' : s))\n .optional(),\n flowType: z.enum(['standard', 'setup', 'seed', 'teardown']).optional(),\n /**\n * Credential the journey runs as. Required for authenticated specs (the\n * common case); optional for unauthenticated flows, which have no leading\n * login node to represent.\n */\n actor: CredentialRefSchema.optional(),\n authenticated: z.boolean().default(true),\n tags: z.array(z.string()).optional(),\n requirementRef: z.string().optional(),\n apiOnly: z.boolean().optional(),\n sandboxTemplate: z.string().optional(),\n environments: z\n .union([\n z.object({ only: z.array(z.string()).min(1) }),\n z.object({ types: z.array(z.enum(['permanent', 'ephemeral', 'local', 'sandbox'])).min(1) }),\n ])\n .optional(),\n /**\n * Teardown linkage for `flowType: seed` workflows. Two surface forms:\n * teardown: cleanup-demo-org # shorthand, defaults applied\n * teardown:\n * spec: cleanup-demo-org # nested for explicit overrides\n * snapshotVersion: 3 # or 'latest' (default)\n * enabled: false # default true\n * The DB stores teardownWorkflowId/teardownSnapshotVersion/teardownEnabled\n * on the seed row; compile resolves spec name → id and PATCHes the seed,\n * pull reverses (FK → name).\n */\n teardown: z\n .union([\n z.string().min(1),\n z.object({\n spec: z.string().min(1),\n snapshotVersion: z\n .union([z.literal('latest'), z.number().int().nonnegative()])\n .optional(),\n enabled: z.boolean().optional(),\n }),\n ])\n .optional(),\n })\n .strict();\nexport type Frontmatter = z.infer<typeof FrontmatterSchema>;\n\n/* ── Inputs / Scenarios / Attachments ────────────────────────────────── */\n\nexport const InputDeclSchema = z.object({\n name: z.string().min(1),\n kind: z.enum(['value', 'credential']).default('value'),\n defaultValue: z.string(),\n});\nexport type InputDecl = z.infer<typeof InputDeclSchema>;\n\nexport const ScenarioSchema = z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n isDefault: z.boolean().default(false),\n includeInSuite: z.boolean().default(true),\n skipReason: z.string().optional(),\n values: z.record(z.string(), z.string()).default({}),\n credentials: z.record(z.string(), z.string()).default({}),\n});\nexport type Scenario = z.infer<typeof ScenarioSchema>;\n\nexport const AttachmentDeclSchema = z.object({\n ref: z.string().min(1),\n source: z.string().min(1), // path or attachmentId\n});\nexport type AttachmentDecl = z.infer<typeof AttachmentDeclSchema>;\n\n/**\n * A seed workflow's declared output. Maps spec-author intent (dataKey + label +\n * description + property name) onto the DB row's authoritative\n * `seedOutputsJson[*]` shape. `propertyName` is resolved to `propertyId` at\n * compile by the CLI sync layer. Credential outputs (the richer\n * `credentialOutput` config) ride in a sidecar follow-up; for now the parser\n * surfaces a clear \"this seed output has credentialOutput — author it in the\n * UI for now\" issue rather than dropping the data.\n */\nexport const DeclaredOutputSchema = z.object({\n dataKey: z.string().min(1),\n label: z.string().min(1).optional(),\n description: z.string().optional(),\n propertyName: z.string().optional(),\n});\nexport type DeclaredOutput = z.infer<typeof DeclaredOutputSchema>;\n\n/* ── Journey nodes ───────────────────────────────────────────────────── */\n\nconst NodeBase = z.object({\n description: z.string().optional(),\n /**\n * Workflow node UUID — present after first compile, when the compiler\n * writes `<!-- @id <uuid> -->` next to the node's lead-in. Drives the\n * recompile diff.\n */\n nodeId: z.string().uuid().optional(),\n /**\n * Source line index of the lead-in. Used by the writeback step to\n * insert `<!-- @id <uuid> -->` after a CREATE without re-finding the\n * line. Populated by the parser; not user-authored.\n */\n sourceLine: z.number().int().nonnegative().optional(),\n});\n\n/**\n * Accept absolute http(s) URLs or root-relative paths only. Rejects\n * `javascript:`, `data:`, `file:`, custom schemes — important because the\n * spec is LLM-emitted and later loaded into a browser session.\n */\nconst PageUrlSchema = z\n .string()\n .min(1)\n .refine(\n (s) => {\n if (s.startsWith('/')) return true; // root-relative path\n try {\n const u = new URL(s);\n return u.protocol === 'http:' || u.protocol === 'https:';\n } catch {\n return false;\n }\n },\n {\n message:\n 'pageUrl must be a root-relative path (e.g. /dashboard) or an absolute http(s) URL',\n }\n );\n\nexport const NavigateNodeSchema = NodeBase.extend({\n kind: z.literal('navigate'),\n pageUrl: PageUrlSchema,\n openInNewTab: z.boolean().optional(),\n});\n\nexport const SwitchRoleNodeSchema = NodeBase.extend({\n kind: z.literal('switchRole'),\n credentialRef: CredentialRefSchema,\n});\n\nexport const ActionFieldSchema = z.object({\n name: z.string().min(1),\n type: z.string().optional(),\n value: z.string(),\n});\n\nexport const ActionNodeSchema = NodeBase.extend({\n kind: z.literal('action'),\n title: z.string().min(1),\n fields: z.array(ActionFieldSchema).default([]),\n capture: z.array(z.string()).default([]),\n assertions: z.array(InlineAssertionSchema).default([]),\n captureAudio: z.boolean().optional(),\n captureLabel: z.string().optional(),\n captureExtraMs: z.number().int().nonnegative().optional(),\n alwaysUseAgent: z.boolean().optional(),\n});\n\nexport const AssertionNodeSchema = NodeBase.extend({\n kind: z.literal('assertion'),\n condition: z.string().min(1),\n severity: z.enum(['warn', 'fail', 'fatal']).default('fatal'),\n expectedOutcome: z.string().optional(),\n alwaysUseAgent: z.boolean().optional(),\n});\n\nexport const SeedNodeSchema = NodeBase.extend({\n kind: z.literal('seed'),\n specName: z.string().min(1),\n version: z.union([z.number().int().nonnegative(), z.literal('latest')]).optional(),\n onFailure: z.enum(['block', 'warn']).optional(),\n mode: z.enum(['recommended', 'api', 'browser']).optional(),\n /** Per-request timeout (seconds) for the seed/teardown api_sequence calls (API mode only). */\n apiTimeoutSeconds: z.number().int().positive().optional(),\n scope: z.enum(['inline', 'suite']).optional(),\n runTeardown: z.boolean().optional(),\n /**\n * Per-node overrides for the seed flow's `kind: 'value'` workflow inputs,\n * keyed by input name. Only honored for inline-scoped seeds — suite-scoped\n * seeds run with the seed flow's input defaults. Spec syntax:\n * `- input.<name>: <value>` sub-bullets.\n */\n inputs: z.record(z.string(), z.string()).optional(),\n});\n\nexport const SetupNodeSchema = NodeBase.extend({\n kind: z.literal('setup'),\n specName: z.string().min(1),\n version: z.union([z.number().int().nonnegative(), z.literal('latest')]).optional(),\n mode: z.enum(['inline', 'suite']).optional(),\n});\n\nexport const WaitNodeSchema = NodeBase.extend({\n kind: z.literal('wait'),\n durationSeconds: z.number().int().positive(),\n});\n\nexport const ConditionNodeSchema: z.ZodType<{\n kind: 'condition';\n expression: string;\n description?: string;\n nodeId?: string;\n sourceLine?: number;\n hints?: string;\n thenBranch: JourneyNode[];\n elseBranch: JourneyNode[];\n}> = NodeBase.extend({\n kind: z.literal('condition'),\n expression: z.string().min(1),\n hints: z.string().optional(),\n thenBranch: z.lazy(() => z.array(JourneyNodeSchema)),\n elseBranch: z.lazy(() => z.array(JourneyNodeSchema)),\n});\n\nexport const NotificationNodeSchema = NodeBase.extend({\n kind: z.literal('notification'),\n channel: z.string().min(1),\n to: z.string().min(1),\n subject: z.string().optional(),\n body: z.string().min(1),\n attach: z.string().optional(),\n});\n\nexport const AudioPlayNodeSchema = NodeBase.extend({\n kind: z.literal('audio'),\n attachmentRef: z.string().min(1),\n loop: z.boolean().optional(),\n waitForCompletion: z.boolean().optional(),\n label: z.string().optional(),\n});\n\nexport const AudioAssertionNodeSchema = NodeBase.extend({\n kind: z.literal('audioAssertion'),\n label: z.string().min(1),\n // Audio default stays 'fail' (not 'fatal' like standalone assertions):\n // audio assertions never halt mid-run, so fail ≈ fatal here and fail is the\n // historical default.\n severity: z.enum(['warn', 'fail', 'fatal']).default('fail'),\n prompt: z.string().optional(),\n model: z.enum(['gpt-audio', 'gemini-2.x']).optional(),\n minDurationMs: z.number().int().nonnegative().optional(),\n maxDurationMs: z.number().int().nonnegative().optional(),\n minRmsDb: z.number().optional(),\n silenceFractionMax: z.number().min(0).max(1).optional(),\n reference: z.string().optional(),\n envelopeCorrelationMin: z.number().min(-1).max(1).optional(),\n});\n\nexport const ApiSequenceNodeSchema = NodeBase.extend({\n kind: z.literal('apiSequence'),\n title: z.string().min(1),\n apiEndpointContext: z.string().min(1),\n credentialInputName: z.string().optional(),\n /**\n * Optional sidecar YAML carrying the full ApiSequenceConfig (steps, exports,\n * validations). Path is resolved relative to the .canary.md file. When set,\n * compile POSTs the loaded config to `/api-sequences/save` after the node\n * sync; pull writes the file when an api_sequence row exists. Multiple\n * api_sequence nodes in the same workflow share one sidecar (the DB has a\n * unique index on workflow_id), so the path should typically be identical\n * across nodes — the parser warns when the paths conflict.\n */\n sidecar: z.string().min(1).optional(),\n});\n\nexport const SandboxActionNodeSchema = NodeBase.extend({\n kind: z.literal('sandboxAction'),\n /** Slug of the sandbox action; resolved against the run env's template at run time. */\n actionSlug: z.string().min(1),\n /** Cosmetic display label. */\n label: z.string().optional(),\n /** Input params; values may carry `$var.*` / macro tokens (passed verbatim). */\n params: z.record(z.string(), z.string()).optional(),\n /**\n * Output variable keys the action produces (denormalized from its\n * outputSchema). Optional — compile resolves them from the action when\n * omitted and a verified template declares the slug.\n */\n outputs: z.array(z.string().min(1)).optional(),\n});\n\nexport const EndNodeSchema = NodeBase.extend({\n kind: z.literal('end'),\n outcome: z.enum(['pass', 'fail']).default('pass'),\n});\n\nexport type JourneyNode =\n | z.infer<typeof NavigateNodeSchema>\n | z.infer<typeof SwitchRoleNodeSchema>\n | z.infer<typeof ActionNodeSchema>\n | z.infer<typeof AssertionNodeSchema>\n | z.infer<typeof SeedNodeSchema>\n | z.infer<typeof SetupNodeSchema>\n | z.infer<typeof WaitNodeSchema>\n | { kind: 'condition'; expression: string; description?: string; nodeId?: string; sourceLine?: number; hints?: string; thenBranch: JourneyNode[]; elseBranch: JourneyNode[] }\n | z.infer<typeof NotificationNodeSchema>\n | z.infer<typeof AudioPlayNodeSchema>\n | z.infer<typeof AudioAssertionNodeSchema>\n | z.infer<typeof ApiSequenceNodeSchema>\n | z.infer<typeof SandboxActionNodeSchema>\n | z.infer<typeof EndNodeSchema>;\n\nexport const JourneyNodeSchema: z.ZodType<JourneyNode> = z.union([\n NavigateNodeSchema,\n SwitchRoleNodeSchema,\n ActionNodeSchema,\n AssertionNodeSchema,\n SeedNodeSchema,\n SetupNodeSchema,\n WaitNodeSchema,\n ConditionNodeSchema,\n NotificationNodeSchema,\n AudioPlayNodeSchema,\n AudioAssertionNodeSchema,\n ApiSequenceNodeSchema,\n SandboxActionNodeSchema,\n EndNodeSchema,\n]);\n\n/* ── Whole-file AST ──────────────────────────────────────────────────── */\n\nexport const SpecAstSchema = z.object({\n frontmatter: FrontmatterSchema,\n spirit: z.string().optional(),\n preflight: z.string().optional(),\n cleanup: z.string().optional(),\n inputs: z.array(InputDeclSchema).default([]),\n scenarios: z.array(ScenarioSchema).default([]),\n attachments: z.array(AttachmentDeclSchema).default([]),\n declaredOutputs: z.array(DeclaredOutputSchema).default([]),\n journey: z.array(JourneyNodeSchema),\n});\nexport type SpecAst = z.infer<typeof SpecAstSchema>;\n\n/** Surface for lint/parse errors. */\nexport type SpecIssue = {\n severity: 'error' | 'warn';\n message: string;\n line?: number;\n hint?: string;\n};\n\n","/**\n * Semantic lint rules for a parsed SpecAst. Pure (no I/O) — runs offline.\n *\n * @module spec/lint\n */\n\nimport type { JourneyNode, SpecAst, SpecIssue } from './grammar.js';\n\n// Keep in sync with the runtime macro registry\n// (apps/api/src/workflows/macros/registry.ts). `$CREDENTIAL` is a reserved\n// reference token, not a registry macro.\nconst RESERVED_MACROS = new Set([\n 'EMAIL',\n 'UUID',\n 'NOW',\n 'RANDOM_STRING',\n 'RANDOM_INT',\n 'DATE',\n 'TODAY',\n 'TIMESTAMP',\n 'SEQUENCE',\n 'FIRST_NAME',\n 'LAST_NAME',\n 'PHONE',\n 'CREDENTIAL',\n]);\n\nexport function lintSpec(ast: SpecAst): SpecIssue[] {\n const issues: SpecIssue[] = [];\n\n // R1 — at least one run-failing (fail or fatal) assertion somewhere in the journey.\n const isRunFailing = (severity: string) => severity === 'fail' || severity === 'fatal';\n const hasFailAssertion = anyNode(ast.journey, (n) => {\n if (n.kind === 'action') return n.assertions.some((a) => isRunFailing(a.severity));\n if (n.kind === 'assertion') return isRunFailing(n.severity);\n if (n.kind === 'audioAssertion') return isRunFailing(n.severity);\n return false;\n });\n if (!hasFailAssertion) {\n issues.push({\n severity: 'warn',\n message:\n 'Spec has no fail- or fatal-severity assertions — the case will pass even if the feature is broken.',\n hint: 'Add `- assert (fail): …` (or `(fatal)` for must-stop preconditions) under at least one action.',\n });\n }\n\n // R2 — requirementRef present.\n if (!ast.frontmatter.requirementRef) {\n issues.push({\n severity: 'warn',\n message: '`requirementRef` is missing from frontmatter — untraceable specs rot.',\n });\n }\n\n // R3 — non-empty Spirit/Preflight/Cleanup if present (parser drops empties to undefined,\n // so this is mostly a no-op; left for future strictness).\n\n // R4 — input macros declared.\n const declaredInputs = new Set(ast.inputs.map((i) => i.name));\n // Names resolvable as `$var.<name>`: workflow inputs, explicit DOM captures,\n // plus action field names — an action's input values auto-promote to\n // `$var.<name>` downstream (see Canary inputs-vs-outputs semantics).\n const promotedVars = new Set<string>();\n declaredInputs.forEach((input) => promotedVars.add(input));\n walkNodes(ast.journey, (n) => {\n if (n.kind === 'action') {\n n.capture.forEach((c) => promotedVars.add(c));\n n.fields.forEach((f) => promotedVars.add(f.name));\n }\n });\n\n // Walk every string in the AST to collect $-references.\n walkStrings(ast.journey, (s, ctx) => {\n for (const ref of extractMacroRefs(s)) {\n if (RESERVED_MACROS.has(ref.split('(')[0])) continue;\n if (ref.startsWith('var.')) {\n const name = ref.slice('var.'.length);\n if (!promotedVars.has(name)) {\n // Warn, not error: a `$var.<name>` can legitimately be produced by a\n // recorded playbook step (e.g. an `extract`/`capture` action) that\n // the spec grammar doesn't surface, so it isn't always declarable as\n // a `- capture:`. Still flag it as a likely-typo signal.\n issues.push({\n severity: 'warn',\n message: `\\`$var.${name}\\` referenced in ${ctx} but not declared in \\`## Inputs\\`, via \\`- capture:\\`, or as a field.`,\n hint: 'If this is authored data, add `- capture: ' + name + '` to the action that produces it.',\n });\n }\n } else if (!declaredInputs.has(ref)) {\n issues.push({\n severity: 'error',\n message: `\\`$${ref}\\` referenced in ${ctx} but not declared in \\`## Inputs\\`.`,\n });\n }\n }\n });\n\n // R5 — at most one default scenario.\n const defaults = ast.scenarios.filter((s) => s.isDefault);\n if (defaults.length > 1) {\n issues.push({\n severity: 'error',\n message: `Multiple scenarios marked default: ${defaults.map((s) => s.name).join(', ')}.`,\n });\n }\n\n // R6 — skipped scenarios cite a reason.\n for (const s of ast.scenarios) {\n if (!s.includeInSuite && !s.skipReason) {\n issues.push({\n severity: 'warn',\n message: `Scenario \"${s.name}\" is skipped without a reason. Use *(skip: <ref>)*.`,\n });\n }\n }\n\n // R7 — scenario values reference declared inputs.\n for (const s of ast.scenarios) {\n for (const key of Object.keys(s.values)) {\n if (!declaredInputs.has(key)) {\n issues.push({\n severity: 'warn',\n message: `Scenario \"${s.name}\" overrides input \"${key}\" which is not declared in \\`## Inputs\\`.`,\n });\n }\n }\n }\n\n // R8 — attachments referenced in the journey/notifications must be declared.\n const declaredAttachments = new Set(ast.attachments.map((a) => a.ref));\n walkNodes(ast.journey, (n) => {\n if (n.kind === 'audio' && !declaredAttachments.has(n.attachmentRef)) {\n issues.push({\n severity: 'error',\n message: `Play audio references unknown attachment \"${n.attachmentRef}\".`,\n });\n }\n if (n.kind === 'audioAssertion' && n.reference && !declaredAttachments.has(n.reference)) {\n issues.push({\n severity: 'error',\n message: `Audio assertion references unknown attachment \"${n.reference}\".`,\n });\n }\n if (n.kind === 'notification' && n.attach && !declaredAttachments.has(n.attach)) {\n issues.push({\n severity: 'error',\n message: `Notification attaches unknown attachment \"${n.attach}\".`,\n });\n }\n });\n\n // R9 — click-by-click language (warn).\n walkNodes(ast.journey, (n) => {\n if (n.kind !== 'action') return;\n const text = (n.description ?? '') + ' ' + n.title;\n if (/\\bclick\\s+(?:the\\s+)?[\"']?\\w+/i.test(text) && /,\\s*then\\s+click/i.test(text)) {\n issues.push({\n severity: 'warn',\n message: `Action \"${n.title}\" reads as click-by-click UI mechanics — prefer human intent.`,\n });\n }\n });\n\n return issues;\n}\n\n/* ── helpers ─────────────────────────────────────────────────────────── */\n\nfunction anyNode(nodes: JourneyNode[], pred: (n: JourneyNode) => boolean): boolean {\n for (const n of nodes) {\n if (pred(n)) return true;\n if (n.kind === 'condition') {\n if (anyNode(n.thenBranch, pred) || anyNode(n.elseBranch, pred)) return true;\n }\n }\n return false;\n}\n\nfunction walkNodes(nodes: JourneyNode[], visit: (n: JourneyNode) => void): void {\n for (const n of nodes) {\n visit(n);\n if (n.kind === 'condition') {\n walkNodes(n.thenBranch, visit);\n walkNodes(n.elseBranch, visit);\n }\n }\n}\n\nfunction walkStrings(nodes: JourneyNode[], visit: (s: string, ctx: string) => void): void {\n walkNodes(nodes, (n) => {\n const ctx = nodeCtx(n);\n if (n.description) visit(n.description, ctx);\n if (n.kind === 'navigate') visit(n.pageUrl, ctx);\n if (n.kind === 'action') {\n visit(n.title, ctx);\n n.fields.forEach((f) => visit(f.value, ctx));\n n.assertions.forEach((a) => visit(a.condition, ctx));\n }\n if (n.kind === 'assertion') visit(n.condition, ctx);\n if (n.kind === 'audioAssertion' && n.prompt) visit(n.prompt, ctx);\n if (n.kind === 'notification') {\n visit(n.to, ctx);\n visit(n.body, ctx);\n if (n.subject) visit(n.subject, ctx);\n }\n if (n.kind === 'condition') visit(n.expression, ctx);\n });\n}\n\nfunction nodeCtx(n: JourneyNode): string {\n if (n.kind === 'action') return `action \"${n.title}\"`;\n if (n.kind === 'assertion') return `assertion`;\n if (n.kind === 'navigate') return `navigate`;\n if (n.kind === 'condition') return `condition`;\n if (n.kind === 'notification') return `notification`;\n if (n.kind === 'seed') return `seed \"${n.specName}\"`;\n if (n.kind === 'setup') return `setup \"${n.specName}\"`;\n return n.kind;\n}\n\n/**\n * Pull every `$<token>` reference out of a string. Recognizes:\n * $foo, $foo.bar, $foo_bar, $RANDOM_STRING(8), $var.captured\n * Excludes false positives like prices ($5).\n */\nfunction extractMacroRefs(s: string): string[] {\n const out: string[] = [];\n const re = /\\$([A-Za-z_][A-Za-z0-9_.]*)/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(s))) {\n // Drop trailing dots — they're sentence punctuation after a token like\n // `$var.foo.`, not part of the variable name.\n out.push(m[1].replace(/\\.+$/, ''));\n }\n return out;\n}\n","/**\n * Helpers for keeping workflow-input references canonical in emitted specs.\n *\n * The runtime resolves workflow inputs through the same variable registry as\n * captures and field values, so stored config should use `$var.<inputName>`.\n * Older/planner-authored specs may contain bare `$inputName`; normalize those\n * at spec boundaries instead of teaching the runner another reference syntax.\n */\n\n/** Normalize bare declared workflow-input references to `$var.<inputName>`. */\nexport function normalizeDeclaredInputReferences(\n value: string,\n inputNames: ReadonlySet<string>\n): string {\n if (inputNames.size === 0 || !value.includes('$')) return value;\n\n return value.replace(\n /(^|[^\\\\])\\$([A-Za-z_][A-Za-z0-9_-]*)/g,\n (match: string, prefix: string, name: string, offset: number, full: string) => {\n if (!inputNames.has(name)) return match;\n\n const next = full[offset + match.length];\n const afterDot = full[offset + match.length + 1];\n if (next === '.' && afterDot !== undefined && /[A-Za-z0-9_-]/.test(afterDot)) {\n return match;\n }\n\n return `${prefix}$var.${name}`;\n }\n );\n}\n","/**\n * Emit a SpecAst as a `WorkflowCreateInput`-shaped JSON payload that the\n * server's `/workflows/create-with-nodes` endpoint accepts.\n *\n * @module spec/emit\n */\n\nimport type { CredentialRef, JourneyNode, SpecAst } from './grammar.js';\nimport { normalizeDeclaredInputReferences } from './input-refs.js';\n\nexport type EmittedWorkflow = {\n name: string;\n description: string | null;\n preflight: string | null;\n cleanup: string | null;\n status?: 'draft' | 'approved';\n flowType?: 'standard' | 'setup' | 'seed' | 'teardown';\n apiOnly?: boolean;\n /** Tag names (no color/id) — diff resolves names → ids against the live tag list. */\n tags?: string[];\n /**\n * Environment eligibility, normalized to the discriminated union the API\n * accepts as `environmentConstraints` on `PUT /workflows/:id`.\n */\n environmentConstraints?:\n | { mode: 'only'; environmentNames: string[] }\n | { mode: 'envTypes'; types: Array<'permanent' | 'ephemeral' | 'local' | 'sandbox'> };\n /** Sandbox template name (not id) — resolved against the org's templates on compile. */\n sandboxTemplate?: string;\n /**\n * Teardown linkage for seed workflows. Stored as canonical fields the API\n * (and the diff layer) understand. `teardownSpec` is a workflow name that\n * sync.ts resolves to a `teardownWorkflowId` before PUT.\n */\n teardownSpec?: string;\n /** Pinned snapshot version, or `'latest'` (default) for \"always use latest\". */\n teardownSnapshotVersion?: 'latest' | number;\n /** Whether the linked teardown should actually run (defaults to true when set). */\n teardownEnabled?: boolean;\n /**\n * Declared outputs for seed workflows. Each entry carries spec-author intent\n * (dataKey, label, description, propertyName); sync.ts resolves propertyName\n * → propertyId and maps to the live `seedOutputsJson` row shape.\n * `credentialOutput` configs are preserved opaquely by the diff layer\n * (sidecar grammar lands in a follow-up).\n */\n seedOutputs?: Array<{\n dataKey: string;\n label?: string;\n description?: string;\n propertyName?: string;\n }>;\n inputsJson: Array<{ kind: 'value' | 'credential'; name: string; defaultValue: string }>;\n scenariosJson: Array<{\n id: string;\n name: string;\n description?: string;\n isDefault?: boolean;\n includeInSuite?: boolean;\n skipReason?: string;\n values?: Record<string, string>;\n credentials?: Record<string, string>;\n }>;\n attachments: Array<{ ref: string; source: string }>;\n nodes: Array<{\n nodeType: string;\n configJson: Record<string, unknown>;\n /** Workflow-node UUID from `<!-- @id <uuid> -->` on the lead-in (if any). */\n nodeId?: string;\n /** Source line of the lead-in in the .canary.md (for write-back). */\n sourceLine?: number;\n }>;\n /** Workflow UUID this spec is bound to, when known. */\n workflowId?: string;\n /**\n * Optional ApiSequenceConfig loaded from the sidecar YAML referenced by an\n * api_sequence node. Sync.ts POSTs it to `/api-sequences/save` after the\n * node + workflow-field sync, so the workflow gets a fresh row keyed by\n * (workflowId, …). Multiple api_sequence nodes share one sidecar (DB\n * uniqueness on workflow_id); the CLI loader picks the first non-null path\n * and ignores duplicates as long as they're identical.\n */\n apiSequenceConfig?: unknown;\n};\n\nexport interface EmitOptions {\n /**\n * Append a default `end` node when the journey doesn't end in one. On by\n * default for fresh creates; the recompile/diff/pull paths pass `false` so\n * pulling a workflow that has no explicit end node doesn't spuriously add\n * one (which would show as a phantom `+1 create` on every round-trip).\n */\n appendDefaultEnd?: boolean;\n}\n\nexport function emitSpec(ast: SpecAst, opts: EmitOptions = {}): EmittedWorkflow {\n const { appendDefaultEnd = true } = opts;\n const nodes: EmittedWorkflow['nodes'] = [];\n const inputNames = new Set(ast.inputs.map((i) => i.name));\n\n for (const n of ast.journey) emitNode(n, nodes, inputNames);\n\n // Compile-time login: an authenticated spec gets a login node. When an actor\n // is declared it binds that credential; without one (e.g. a pulled workflow\n // whose login resolves its credential at run/suite level) it emits a bare\n // login so the node still round-trips. The login is inserted *after* any\n // leading seed/setup nodes — those provision data before authentication, so\n // the auth login follows them rather than jumping to the very front.\n if (ast.frontmatter.authenticated) {\n let insertAt = 0;\n while (\n insertAt < nodes.length &&\n (nodes[insertAt].nodeType === 'seed' || nodes[insertAt].nodeType === 'setup')\n ) {\n insertAt++;\n }\n nodes.splice(\n insertAt,\n 0,\n ast.frontmatter.actor ? loginNode(ast.frontmatter.actor) : bareLoginNode()\n );\n }\n\n // If the last node isn't `end`, add a default end node (fresh create only).\n const last = nodes[nodes.length - 1];\n if (appendDefaultEnd && (!last || last.nodeType !== 'end')) {\n nodes.push({\n nodeType: 'end',\n configJson: { title: 'End', description: 'Journey complete', outcome: 'pass' },\n });\n }\n\n return {\n name: ast.frontmatter.name,\n description: ast.spirit ?? null,\n preflight: ast.preflight ?? null,\n cleanup: ast.cleanup ?? null,\n status: ast.frontmatter.status,\n flowType: ast.frontmatter.flowType,\n apiOnly: ast.frontmatter.apiOnly,\n // Optional fields are emitted as `undefined` when absent so the diff can\n // tell \"spec doesn't constrain this\" (no field-update op) from \"spec\n // explicitly wants the field cleared\" (handled per-field in diff.ts).\n tags: ast.frontmatter.tags,\n environmentConstraints: toEnvironmentConstraints(ast.frontmatter.environments),\n sandboxTemplate: ast.frontmatter.sandboxTemplate,\n ...normalizeTeardown(ast.frontmatter.teardown),\n seedOutputs:\n ast.declaredOutputs.length > 0\n ? ast.declaredOutputs.map((o) => ({\n dataKey: o.dataKey,\n ...(o.label ? { label: o.label } : {}),\n ...(o.description ? { description: o.description } : {}),\n ...(o.propertyName ? { propertyName: o.propertyName } : {}),\n }))\n : undefined,\n inputsJson: ast.inputs.map((i) => ({\n kind: i.kind,\n name: i.name,\n defaultValue: i.defaultValue,\n })),\n scenariosJson: ast.scenarios.map((s) => ({\n id: crypto.randomUUID(),\n name: s.name,\n description: s.description,\n isDefault: s.isDefault || undefined,\n includeInSuite: s.includeInSuite,\n // `skipReason` is a spec-source-only field (no DB column). Emit it so the\n // round-trip diff doesn't flag it as drift, but sync.ts strips it before\n // PUT — the API doesn't accept it.\n ...(s.skipReason ? { skipReason: s.skipReason } : {}),\n values: Object.keys(s.values).length > 0 ? s.values : undefined,\n credentials: Object.keys(s.credentials).length > 0 ? s.credentials : undefined,\n })),\n attachments: ast.attachments,\n nodes,\n workflowId: ast.frontmatter.workflowId,\n };\n}\n\n/**\n * Translate spec `environments:` (which uses `only: [<names>]`) to the API's\n * `environmentConstraints` discriminated union (which uses\n * `environmentNames` here; sync.ts later resolves names → IDs against the\n * property's environments before PUT).\n */\nfunction toEnvironmentConstraints(\n envs: SpecAst['frontmatter']['environments']\n): EmittedWorkflow['environmentConstraints'] {\n if (!envs) return undefined;\n if ('only' in envs) return { mode: 'only', environmentNames: envs.only };\n return { mode: 'envTypes', types: envs.types };\n}\n\n/**\n * Normalize the two `teardown:` surface forms (string shorthand vs nested\n * object) to the canonical `teardownSpec`/`teardownSnapshotVersion`/\n * `teardownEnabled` triple. Shorthand string is sugar for \"default behavior\":\n * latest snapshot, enabled. The nested form lets the author pin a snapshot or\n * disable execution without removing the link.\n */\nfunction normalizeTeardown(\n teardown: SpecAst['frontmatter']['teardown']\n): Pick<EmittedWorkflow, 'teardownSpec' | 'teardownSnapshotVersion' | 'teardownEnabled'> {\n if (!teardown) return {};\n if (typeof teardown === 'string') {\n return { teardownSpec: teardown, teardownSnapshotVersion: 'latest', teardownEnabled: true };\n }\n return {\n teardownSpec: teardown.spec,\n teardownSnapshotVersion: teardown.snapshotVersion ?? 'latest',\n teardownEnabled: teardown.enabled ?? true,\n };\n}\n\n/** Login node with no bound credential — credential resolved at run/suite level. */\nfunction bareLoginNode(): EmittedWorkflow['nodes'][number] {\n return {\n nodeType: 'login',\n configJson: { title: 'Log in', description: 'Authenticate the session', performLogin: true },\n };\n}\n\nfunction loginNode(\n actor: NonNullable<SpecAst['frontmatter']['actor']>\n): EmittedWorkflow['nodes'][number] {\n return {\n nodeType: 'login',\n configJson: loginConfig(actor, { titlePrefix: 'Log in as' }),\n };\n}\n\n/**\n * Build the configJson for a login node from a CredentialRef. Shared by the\n * leading login (emitted from `actor:`) and mid-journey switch-role nodes so\n * both surfaces produce identical config field sets for a given identity.\n */\nfunction loginConfig(\n ref: CredentialRef,\n opts: { titlePrefix: string; description?: string; performLogin?: boolean }\n): Record<string, unknown> {\n const performLogin = opts.performLogin ?? false;\n if (ref.kind === 'credential') {\n return {\n title: `${opts.titlePrefix} ${ref.name}`,\n description: opts.description ?? `Authenticate using credential \"${ref.name}\"`,\n credentialName: ref.name,\n credentialSource: 'static',\n ...(performLogin ? { performLogin: true } : {}),\n };\n }\n if (ref.kind === 'seedOutput') {\n return {\n title: `${opts.titlePrefix} seed-provisioned ${ref.ref}`,\n description:\n opts.description ?? `Authenticate using credential from seed output \"${ref.ref}\"`,\n credentialSource: 'from_seed',\n // The runtime expects an object ref; sync.ts can enrich with the seed\n // workflow id once the binding context is known. dataKey is the stable\n // identifier (matches the seed's declared output key); name mirrors it.\n seedCredentialRef: { dataKey: ref.ref, name: ref.ref },\n // from_seed mid-journey switches always perform login; leading login\n // also performs login on session bootstrap.\n performLogin: true,\n };\n }\n return {\n title: `${opts.titlePrefix} ${ref.role}`,\n description: opts.description ?? `Authenticate using credential template \"${ref.role}\"`,\n credentialSource: 'from_template',\n credentialTemplateName: ref.role,\n ...(performLogin ? { performLogin: true } : {}),\n };\n}\n\nfunction emitNode(\n n: JourneyNode,\n out: EmittedWorkflow['nodes'],\n inputNames: ReadonlySet<string>\n): void {\n const inputRef = (value: string): string => normalizeDeclaredInputReferences(value, inputNames);\n // Propagate node identity from parser → emitter → diff. nodeId is the\n // workflow-node UUID (present when the spec already has `<!-- @id ... -->`\n // on this lead-in); sourceLine is the source-file line of the lead-in,\n // captured by the parser so the writeback step can find the line again\n // without re-parsing.\n const meta: { nodeId?: string; sourceLine?: number } = {\n ...(n.nodeId ? { nodeId: n.nodeId } : {}),\n ...(n.sourceLine !== undefined ? { sourceLine: n.sourceLine } : {}),\n };\n switch (n.kind) {\n case 'navigate': {\n const pageUrl = inputRef(n.pageUrl);\n out.push({\n ...meta,\n nodeType: 'navigate',\n configJson: {\n title: `Go to ${shortPath(pageUrl)}`,\n description: inputRef(n.description ?? `Navigate to ${pageUrl}`),\n pageUrl,\n ...(n.openInNewTab ? { openInNewTab: true } : {}),\n },\n });\n return;\n }\n case 'switchRole': {\n const ref = n.credentialRef;\n // Cover all three CredentialRef variants explicitly — the `seedOutput`\n // variant was added in #689 but the switchRole fallback (introduced by\n // #679) wasn't updated, leaving `ref.role` accessed on a union that\n // includes `{ kind: 'seedOutput'; ref: string }`. tsc caught it, Bun's\n // test runner didn't, so the broken state landed on main.\n const fallbackDesc =\n ref.kind === 'credential'\n ? `Re-authenticate as ${ref.name}`\n : ref.kind === 'seedOutput'\n ? `Re-authenticate as seed-provisioned ${ref.ref}`\n : `Re-authenticate as ${ref.role}`;\n out.push({\n ...meta,\n nodeType: 'login',\n configJson: loginConfig(ref, {\n titlePrefix: 'Switch role to',\n description: inputRef(n.description ?? fallbackDesc),\n performLogin: true,\n }),\n });\n return;\n }\n case 'action': {\n const fieldEntries = n.fields.map((f) => ({\n name: f.name,\n label: humanizeLabel(f.name),\n type: (f.type ?? 'text') as string,\n value: inputRef(f.value),\n }));\n const inputValues =\n fieldEntries.length > 0\n ? Object.fromEntries(\n fieldEntries\n .filter((f) => f.value !== undefined && f.value !== '')\n .map((f) => [f.name, f.value])\n )\n : undefined;\n out.push({\n ...meta,\n nodeType: 'action',\n configJson: {\n customActionTitle: inputRef(n.title),\n actionDescription: inputRef(n.description ?? n.title),\n ...(fieldEntries.length > 0\n ? {\n formFields: fieldEntries,\n dataRequirements: fieldEntries.map(({ name, label, type }) => ({\n name,\n label,\n type,\n required: true,\n })),\n ...(inputValues && Object.keys(inputValues).length > 0 ? { inputValues } : {}),\n }\n : {}),\n ...(n.capture.length > 0 ? { declaredOutputs: n.capture } : {}),\n ...(n.assertions.length > 0\n ? {\n inlineAssertions: n.assertions.map((a) => ({\n condition: inputRef(a.condition),\n severity: a.severity,\n ...(a.agentic ? { agentic: true } : {}),\n })),\n }\n : {}),\n ...(n.captureAudio\n ? {\n captureAudio: true,\n ...(n.captureLabel ? { captureLabel: n.captureLabel } : {}),\n ...(n.captureExtraMs !== undefined ? { captureExtraMs: n.captureExtraMs } : {}),\n }\n : {}),\n ...(n.alwaysUseAgent ? { alwaysUseAgent: true } : {}),\n },\n });\n return;\n }\n case 'assertion':\n out.push({\n ...meta,\n nodeType: 'assertion',\n configJson: {\n title: 'Assert',\n description: inputRef(n.description ?? n.condition),\n condition: inputRef(n.condition),\n severity: n.severity,\n ...(n.expectedOutcome ? { expectedOutcome: n.expectedOutcome } : {}),\n ...(n.alwaysUseAgent ? { alwaysUseAgent: true } : {}),\n },\n });\n return;\n case 'seed':\n out.push({\n ...meta,\n nodeType: 'seed',\n configJson: {\n title: `Seed: ${n.specName}`,\n description: n.description ?? `Run seed workflow \"${n.specName}\"`,\n // Compiler resolves spec-name → seedWorkflowId; placeholder until then.\n seedWorkflowName: n.specName,\n // Emit the canonical SeedNodeConfig keys the runtime + UI actually\n // read (seed-deps.ts, SeedNodeConfig.tsx). The `seed`-prefixed names\n // are only for the AI builder-tool input schemas, which remap them;\n // here configJson is stored verbatim, so prefixed keys silently\n // revert to defaults.\n ...(n.version === 'latest' || n.version === undefined\n ? { snapshotVersion: null }\n : { snapshotVersion: n.version }),\n ...(n.onFailure ? { onFailure: n.onFailure } : {}),\n ...(n.mode ? { executionMode: n.mode } : {}),\n ...(n.apiTimeoutSeconds ? { apiTimeoutSeconds: n.apiTimeoutSeconds } : {}),\n ...(n.scope ? { scope: n.scope } : {}),\n ...(n.runTeardown !== undefined ? { runTeardown: n.runTeardown } : {}),\n // Spec `inputs` → runtime config key `inputValues` (same remap\n // convention as the other canonical-key mappings above).\n ...(n.inputs && Object.keys(n.inputs).length > 0 ? { inputValues: n.inputs } : {}),\n },\n });\n return;\n case 'setup':\n out.push({\n ...meta,\n nodeType: 'setup',\n configJson: {\n title: `Setup: ${n.specName}`,\n description: n.description ?? `Run setup workflow \"${n.specName}\"`,\n setupFlowName: n.specName,\n ...(n.version === 'latest' || n.version === undefined\n ? { snapshotVersion: null }\n : { snapshotVersion: n.version }),\n ...(n.mode ? { executionMode: n.mode } : {}),\n },\n });\n return;\n case 'wait':\n out.push({\n ...meta,\n nodeType: 'wait',\n configJson: {\n title: `Wait ${n.durationSeconds}s`,\n description: n.description ?? `Pause for ${n.durationSeconds} seconds`,\n waitDuration: n.durationSeconds,\n mode: 'delay',\n delaySeconds: n.durationSeconds,\n },\n });\n return;\n case 'condition':\n // Emit the condition node itself, then BOTH branches as inline siblings.\n // Real condition_true/condition_false edge wiring requires runtime work on\n // the create-with-nodes route (sequential auto-linking only today); until\n // that lands, treating branches as fallthrough is harmless — the runtime\n // walks the linear chain and a condition that doesn't branch is a no-op.\n //\n // We dropped the legacy `__specBranches` stash: both branches are now real\n // sibling nodes (the parser already produced them that way), so there's no\n // round-trip data to preserve. Diff still treats the condition node as\n // authored-by-expression only; branch identity flows through the\n // per-node @id stamps the writeback step persists.\n out.push({\n ...meta,\n nodeType: 'condition',\n configJson: {\n title: 'If',\n description: inputRef(n.description ?? n.expression),\n // Canonical runtime key is `conditionDescription`.\n conditionDescription: inputRef(n.expression),\n ...(n.hints ? { evaluationHints: inputRef(n.hints) } : {}),\n },\n });\n // Materialize both branches as fallthrough nodes after the condition.\n // Critically this PR fixes the silent-drop bug for `elseBranch` — the\n // prior implementation only emitted `thenBranch`, silently losing every\n // node the author wrote under the `Else:` block.\n n.thenBranch.forEach((c) => emitNode(c, out, inputNames));\n n.elseBranch.forEach((c) => emitNode(c, out, inputNames));\n return;\n case 'notification':\n out.push({\n ...meta,\n nodeType: 'notification',\n configJson: {\n title: `Notify ${inputRef(n.to)}`,\n description: inputRef(n.description ?? n.body),\n channel: n.channel,\n to: inputRef(n.to),\n body: inputRef(n.body),\n ...(n.subject ? { subject: inputRef(n.subject) } : {}),\n ...(n.attach ? { attachmentRef: n.attach } : {}),\n },\n });\n return;\n case 'audio':\n out.push({\n ...meta,\n nodeType: 'audio',\n configJson: {\n title: n.label ?? `Play ${n.attachmentRef}`,\n description: n.description ?? `Play audio \"${n.attachmentRef}\"`,\n attachmentRef: n.attachmentRef,\n ...(n.loop !== undefined ? { loop: n.loop } : {}),\n ...(n.waitForCompletion !== undefined ? { waitForCompletion: n.waitForCompletion } : {}),\n ...(n.label ? { label: n.label } : {}),\n },\n });\n return;\n case 'audioAssertion':\n out.push({\n ...meta,\n nodeType: 'audio-assertion',\n configJson: {\n title: `Assert audio: ${n.label}`,\n description: inputRef(n.description ?? n.label),\n label: n.label,\n severity: n.severity,\n ...(n.prompt\n ? {\n naturalLanguage: {\n prompt: inputRef(n.prompt),\n ...(n.model ? { model: n.model } : {}),\n },\n }\n : {}),\n ...(hasDeterministicAudioAssertion(n)\n ? {\n deterministic: {\n ...(n.minDurationMs !== undefined ? { minDurationMs: n.minDurationMs } : {}),\n ...(n.maxDurationMs !== undefined ? { maxDurationMs: n.maxDurationMs } : {}),\n ...(n.minRmsDb !== undefined ? { minRmsDb: n.minRmsDb } : {}),\n ...(n.silenceFractionMax !== undefined\n ? { silenceFractionMax: n.silenceFractionMax }\n : {}),\n ...(n.envelopeCorrelationMin !== undefined\n ? { envelopeCorrelationMin: n.envelopeCorrelationMin }\n : {}),\n },\n }\n : {}),\n ...(n.reference ? { referenceAttachmentRef: n.reference } : {}),\n },\n });\n return;\n case 'apiSequence':\n out.push({\n ...meta,\n nodeType: 'api_sequence',\n configJson: {\n customActionTitle: inputRef(n.title),\n description: inputRef(n.description ?? n.title),\n apiEndpointContext: inputRef(n.apiEndpointContext),\n ...(n.credentialInputName ? { credentialInputName: n.credentialInputName } : {}),\n // Sidecar reference is metadata for the CLI sync layer — runtime\n // ignores unknown configJson keys, and the node-hash projection\n // drops it (api_sequence stays opaque at node level; the actual DSL\n // config is diffed via the sidecar load below).\n ...(n.sidecar ? { __apiSequenceSidecar: n.sidecar } : {}),\n },\n });\n return;\n case 'sandboxAction':\n out.push({\n ...meta,\n nodeType: 'sandbox_action',\n configJson: {\n title: n.label ?? `Sandbox action: ${n.actionSlug}`,\n description: inputRef(n.description ?? n.label ?? n.actionSlug),\n actionSlug: n.actionSlug,\n ...(n.label ? { actionLabel: n.label } : {}),\n // Param values pass through verbatim — $var.* / macro tokens resolve\n // at run time against the execution state.\n ...(n.params && Object.keys(n.params).length > 0 ? { params: n.params } : {}),\n ...(n.outputs && n.outputs.length > 0 ? { outputKeys: n.outputs } : {}),\n },\n });\n return;\n case 'end':\n out.push({\n ...meta,\n nodeType: 'end',\n configJson: {\n title: n.outcome === 'fail' ? 'End: fail' : 'End',\n description: n.description ?? 'Journey complete',\n outcome: n.outcome,\n },\n });\n return;\n }\n}\n\nfunction hasDeterministicAudioAssertion(\n n: Extract<JourneyNode, { kind: 'audioAssertion' }>\n): boolean {\n return (\n n.minDurationMs !== undefined ||\n n.maxDurationMs !== undefined ||\n n.minRmsDb !== undefined ||\n n.silenceFractionMax !== undefined ||\n n.reference !== undefined ||\n n.envelopeCorrelationMin !== undefined\n );\n}\n\nfunction shortPath(url: string): string {\n if (url.startsWith('/')) return url;\n try {\n return new URL(url).pathname || url;\n } catch {\n return url;\n }\n}\n\nfunction humanizeLabel(name: string): string {\n return name.replace(/[_-]+/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n// `describeNode` was previously used to stash branch summaries in the legacy\n// `__specBranches` marker on condition nodes. That marker is gone now that\n// both branches are materialized as real sibling nodes (see the 'condition'\n// case above); the helper isn't referenced anymore and was removed to keep\n// the file clean.\n","/**\n * Authored-identity hash for workflow nodes.\n *\n * The `.canary.md` grammar is deliberately a *human-intent* format: it can\n * express what a node is trying to do (titles, descriptions, fields,\n * assertions, navigation targets) but NOT the runtime artifacts a node\n * accumulates — `playbookSteps` (the recorded click-by-click replay), the\n * live `pageUrl` an action ran against, agent guidance, cache metadata. Those\n * are generated/recorded server-side and have no spec syntax.\n *\n * `authoredNodeHash` fingerprints only the *authorable* slice of a node's\n * `configJson` — the part a `.canary.md` author actually controls. The\n * recompile diff compares this hash (spec vs live) instead of the whole\n * `configJson`, so a node that round-tripped through `pull` → edit → `compile`\n * is reported as **changed only when its authored intent changed**. Untouched\n * nodes hash-match, the diff skips them, and their recorded playbook + cache\n * survive (see `sync.ts`, which only PUTs a node when `configChanged`).\n *\n * This is the spec-side sibling of the cache's node hash\n * (`apps/api/src/workflows/helpers/node-hash.ts` — in particular its\n * `hashNodeContextLegacy`, the playbook-excluded variant). It is reimplemented\n * here, not imported, because packages must not depend on `apps/*`.\n *\n * @module spec/node-hash\n */\n\nimport { createHash } from 'node:crypto';\n\n/** Minimal node shape both `EmittedWorkflow.nodes` and `LiveNode` satisfy. */\nexport interface HashableNode {\n nodeType: string;\n configJson: Record<string, unknown> | null;\n}\n\n/**\n * Deterministic hash of a node's authored identity. Applied identically to a\n * spec-emitted node and to a live workflow node — equal hashes mean \"same\n * authored intent\", regardless of runtime fields or key ordering.\n */\nexport function authoredNodeHash(node: HashableNode): string {\n const projection = {\n nodeType: node.nodeType,\n ...authoredProjection(node.nodeType, node.configJson),\n };\n const stable = JSON.stringify(sortObjectKeys(projection));\n return createHash('sha256').update(stable).digest('hex').slice(0, 16);\n}\n\n/**\n * Extract the authorable slice of a node's config, normalized so that a live\n * node and its round-tripped (`pull` → parse → `emit`) form project to the\n * same object. Per-type, mirroring what `emit.ts` writes and what `parse.ts`\n * can read back — anything the grammar can't express is dropped.\n */\nfunction authoredProjection(\n nodeType: string,\n raw: Record<string, unknown> | null\n): Record<string, unknown> {\n const c = raw ?? {};\n switch (nodeType) {\n case 'login':\n // Identity is the credential being assumed, across all binding modes:\n // static (credentialName/Id), from_template (credentialTemplateName/Id),\n // and from_seed (seedCredentialRef name/dataKey). `performLogin` is\n // excluded — the injected leading login omits it while a live login may\n // set it, and login nodes are never cached.\n return { credential: canon(loginCredentialRef(c)) };\n case 'navigate':\n return {\n pageUrl: canon(str(c.pageUrl)),\n openInNewTab: c.openInNewTab === true,\n };\n case 'action':\n return {\n title: authoredActionTitle(c),\n // emit falls back actionDescription → title; trim because the blockquote\n // round-trip can't preserve leading/trailing whitespace.\n description:\n trimText(str(c.actionDescription) ?? str(c.description)) ?? authoredActionTitle(c),\n // Authorable name/type/value triples — server-assigned labels are\n // dropped, and value is sourced from inputValues/formFields alike.\n fields: authoredActionFields(c),\n captures: arr(c.declaredOutputs).filter((x): x is string => typeof x === 'string'),\n // Drop assertion `id` (random UUID) — only the semantic content matters.\n assertions: arr(c.inlineAssertions).map((a) => ({\n condition: str(prop(a, 'condition')) ?? '',\n severity: str(prop(a, 'severity')) ?? 'fail',\n agentic: prop(a, 'agentic') === true,\n })),\n captureAudio: c.captureAudio === true,\n captureLabel: str(c.captureLabel) ?? null,\n captureExtraMs: num(c.captureExtraMs) ?? null,\n alwaysUseAgent: c.alwaysUseAgent === true,\n };\n case 'assertion':\n return {\n condition: canon(str(c.condition)),\n description: canon(str(c.description) ?? str(c.condition)),\n // Legacy `strict:true` is equivalent to severity 'fail' at runtime; map\n // it so a strict assertion doesn't silently weaken to 'warn'.\n severity: str(c.severity) ?? (c.strict === true ? 'fail' : 'warn'),\n expectedOutcome: str(c.expectedOutcome) ?? null,\n alwaysUseAgent: c.alwaysUseAgent === true,\n };\n case 'seed':\n // Canonical keys are snapshotVersion/onFailure/executionMode; the seed*-\n // prefixed names are deprecated tool-input aliases. Read canonical first,\n // fall back to alias so emitted (alias) and live (canonical) both resolve.\n return {\n specName: canon(str(c.seedWorkflowName)),\n snapshotVersion: c.snapshotVersion ?? c.seedSnapshotVersion ?? null,\n onFailure: str(c.onFailure) ?? str(c.seedOnFailure) ?? null,\n executionMode: str(c.executionMode) ?? str(c.seedExecutionMode) ?? null,\n scope: str(c.scope) ?? null,\n runTeardown: typeof c.runTeardown === 'boolean' ? c.runTeardown : null,\n // Input overrides change what the seed provisions — authored identity.\n inputValues: seedInputValues(c),\n };\n case 'setup':\n return {\n specName: canon(str(c.setupFlowName)),\n snapshotVersion: c.snapshotVersion ?? null,\n mode: str(c.executionMode) ?? null,\n };\n case 'wait':\n return { delaySeconds: num(c.delaySeconds) ?? num(c.waitDuration) ?? null };\n case 'condition':\n // `__specBranches` is a documentation marker (runtime ignores it); the\n // real branch nodes are flat siblings keyed by their own @id.\n // Runtime + UI store the expression in `conditionDescription`;\n // `conditionExpression` is a deprecated tool-input alias.\n return {\n expression: canon(\n str(c.conditionDescription) ?? str(c.conditionExpression) ?? str(c.description)\n ),\n hints: str(c.evaluationHints) ?? null,\n };\n case 'notification':\n return {\n channel: str(c.channel) ?? null,\n to: str(c.to) ?? null,\n subject: str(c.subject) ?? null,\n body: str(c.body) ?? null,\n attach: str(c.attachmentRef) ?? null,\n };\n case 'audio':\n // parse only recognizes `loop: true` and `waitForCompletion: false`, so\n // normalize to those defaults (absent loop ≡ false, absent wait ≡ true).\n return {\n attachmentRef: str(c.attachmentRef) ?? null,\n loop: c.loop === true,\n waitForCompletion: c.waitForCompletion !== false,\n label: str(c.label) ?? null,\n };\n case 'audio-assertion': {\n const det = obj(c.deterministic);\n const nl = obj(c.naturalLanguage);\n return {\n label: str(c.label) ?? null,\n severity: str(c.severity) ?? 'fail',\n prompt: str(nl?.prompt) ?? str(c.prompt) ?? null,\n model: str(nl?.model) ?? str(c.model) ?? null,\n minDurationMs: num(det?.minDurationMs) ?? num(c.minDurationMs) ?? null,\n maxDurationMs: num(det?.maxDurationMs) ?? num(c.maxDurationMs) ?? null,\n minRmsDb: num(det?.minRmsDb) ?? num(c.minRmsDb) ?? null,\n silenceFractionMax: num(det?.silenceFractionMax) ?? num(c.silenceFractionMax) ?? null,\n reference: str(c.referenceAttachmentRef) ?? null,\n envelopeCorrelationMin:\n num(det?.envelopeCorrelationMin) ?? num(c.envelopeCorrelationMin) ?? null,\n };\n }\n case 'api_sequence':\n // Opaque: the real config is an API-request-sequence DSL (steps, exports,\n // stopOnFailure) that the `.canary.md` grammar can't yet express. Hash to\n // a constant so the node is never reported changed — the round-trip\n // leaves the server config untouched rather than overwriting it with a\n // lossy spec form. Full DSL round-trip is a follow-up.\n return {};\n case 'sandbox_action': {\n const params = obj(c.params) ?? {};\n const paramEntries: Record<string, string | null> = {};\n for (const key of Object.keys(params).sort()) {\n paramEntries[key] = str(params[key]) ?? null;\n }\n const outputKeys = Array.isArray(c.outputKeys)\n ? c.outputKeys.filter((k): k is string => typeof k === 'string').sort()\n : [];\n return {\n actionSlug: str(c.actionSlug) ?? null,\n label: str(c.actionLabel) ?? null,\n params: paramEntries,\n outputs: outputKeys,\n };\n }\n case 'end':\n return { outcome: str(c.outcome) ?? 'pass' };\n default:\n // Unknown node type — hash on type alone so a config change can't\n // silently masquerade as unchanged.\n return {};\n }\n}\n\n/**\n * The lead-in title for an action. Prefers the authored `customActionTitle`;\n * for agent-authored actions that carry only a description, derives a stable,\n * single-line title from the first sentence (the `.canary.md` grammar requires\n * a title in `**Action — …**`). Shared by the hash and the `pull` serializer\n * so a title-less action round-trips without inventing a new title each time.\n */\nexport function authoredActionTitle(raw: Record<string, unknown> | null): string {\n const c = raw ?? {};\n const explicit = str(c.customActionTitle) ?? str(c.title);\n if (explicit && explicit.trim()) return explicit.trim();\n const desc = (str(c.actionDescription) ?? '').replace(/\\*/g, '').replace(/\\s+/g, ' ').trim();\n if (!desc) return 'Action';\n const sentence = desc.split(/(?<=[.!?])\\s/)[0] ?? desc;\n return sentence.slice(0, 80).trim() || 'Action';\n}\n\n/**\n * The authorable form fields of an action, as `.canary.md` `- field` lines\n * express them. An action carries its fields across up to three keys:\n * - `dataRequirements` — the field schema (name, type, label, required);\n * - `inputValues` — pre-filled values, keyed by field name;\n * - `formFields` — the legacy combined shape (name, label, type, value).\n * `emit` writes all three; a UI/agent-built node may carry only some. We key\n * off dataRequirements when present (else formFields) for name/type, and read\n * the value from inputValues first, falling back to formFields. Shared by the\n * hash and the `pull` serializer so both agree on the round-trip.\n */\nexport function authoredActionFields(\n raw: Record<string, unknown> | null\n): Array<{ name: string; type: string; value: string }> {\n const c = raw ?? {};\n const inputValues =\n c.inputValues && typeof c.inputValues === 'object'\n ? (c.inputValues as Record<string, unknown>)\n : {};\n const formFields = arr(c.formFields);\n const formByName = new Map<string, unknown>();\n for (const f of formFields) {\n const n = str(prop(f, 'name'));\n if (n) formByName.set(n, f);\n }\n const reqs = arr(c.dataRequirements);\n const source = reqs.length > 0 ? reqs : formFields;\n const out: Array<{ name: string; type: string; value: string }> = [];\n for (const s of source) {\n const name = str(prop(s, 'name'));\n if (!name) continue;\n const value = str(inputValues[name]) ?? str(prop(formByName.get(name), 'value')) ?? '';\n out.push({ name, type: str(prop(s, 'type')) ?? 'text', value });\n }\n return out;\n}\n\n/**\n * The credential a login assumes, as a single display string, across every\n * binding mode. Shared by the hash and the `pull` serializer so a login\n * round-trips without churn regardless of how its credential is bound.\n */\nexport function loginCredentialRef(raw: Record<string, unknown> | null): string | undefined {\n const c = raw ?? {};\n const seedRef = c.seedCredentialRef;\n return (\n str(c.credentialTemplateName) ??\n str(c.credentialName) ??\n str(c.credentialId) ??\n str(c.credentialTemplateId) ??\n // For from_seed bindings, `dataKey` is the stable identifier (matches the\n // seed's declared-output key); `name` is a display label that can drift.\n // Prefer dataKey so spec round-trip (which uses `seed-output <dataKey>`)\n // hash-matches the live row regardless of label.\n str(prop(seedRef, 'dataKey')) ??\n str(prop(seedRef, 'name'))\n );\n}\n\n/** Recursively sort object keys for order-independent serialization. */\nexport function sortObjectKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortObjectKeys);\n if (value !== null && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n return Object.keys(obj)\n .sort()\n .reduce<Record<string, unknown>>((acc, k) => {\n acc[k] = sortObjectKeys(obj[k]);\n return acc;\n }, {});\n }\n return value;\n}\n\n/**\n * Canonicalize a value the way the parser's `stripPunctuation` does (drops\n * surrounding backticks/quotes and a single trailing period). Fields read\n * back through that path — assertion/condition text, navigate URLs, seed/setup\n * names — must hash post-strip so a live value ending in '.' still matches its\n * round-tripped form. Returns null for absent input.\n */\nfunction canon(v: string | undefined): string | null {\n if (v === undefined) return null;\n return v.replace(/[`\"]/g, '').replace(/\\.$/, '').trim();\n}\n\n/** Trim surrounding whitespace; null for absent input. */\nfunction trimText(v: string | undefined): string | null {\n return v === undefined ? null : v.trim();\n}\n\nfunction str(v: unknown): string | undefined {\n return typeof v === 'string' ? v : undefined;\n}\n\n/**\n * Seed node input overrides as a string-valued record; null when absent or\n * empty so a missing map and `{}` hash identically.\n */\nfunction seedInputValues(c: Record<string, unknown>): Record<string, string> | null {\n if (!c.inputValues || typeof c.inputValues !== 'object') return null;\n const entries = Object.entries(c.inputValues as Record<string, unknown>).filter(\n (e): e is [string, string] => typeof e[1] === 'string'\n );\n return entries.length > 0 ? Object.fromEntries(entries) : null;\n}\n\nfunction num(v: unknown): number | undefined {\n return typeof v === 'number' && Number.isFinite(v) ? v : undefined;\n}\n\nfunction arr(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n}\n\nfunction prop(v: unknown, key: string): unknown {\n return v && typeof v === 'object' ? (v as Record<string, unknown>)[key] : undefined;\n}\n\nfunction obj(v: unknown): Record<string, unknown> | null {\n return v && typeof v === 'object' && !Array.isArray(v) ? (v as Record<string, unknown>) : null;\n}\n","/**\n * Pure diff algorithm for spec recompile.\n *\n * Given an EmittedWorkflow (from the current spec) and a LiveWorkflow\n * snapshot (from `GET /workflows/:id/with-details`), produce an ordered\n * list of operations that, when applied via the per-node/per-edge REST\n * endpoints, makes the live workflow match the spec.\n *\n * No HTTP, no fs — `sync.ts` applies the operations.\n *\n * @module spec/diff\n */\n\nimport type { EmittedWorkflow } from './emit.js';\nimport { authoredNodeHash } from './node-hash.js';\n\n/* ── Live workflow shape — minimum the diff needs from the API response. */\n\nexport type LiveNode = {\n id: string;\n nodeType: string;\n configJson: Record<string, unknown> | null;\n orderIndex: number;\n};\n\nexport type LiveEdge = {\n id: string;\n sourceNodeId: string;\n targetNodeId: string;\n edgeType: string;\n};\n\nexport type LiveWorkflow = {\n id: string;\n name: string;\n description: string | null;\n preflight: string | null;\n cleanup: string | null;\n status: string;\n /** Suite-inclusion axis: 'promoted' | 'paused' | null (never promoted). */\n promotion?: string | null;\n flowType: string;\n apiOnly?: boolean;\n /**\n * Live tag rows attached to this workflow. Diff treats `tags` as a name-set\n * (no ids on the spec side), so the comparison projects to sorted names.\n */\n tags?: Array<{ name: string }>;\n /**\n * Live environment constraints. Diff projects to a name-set, mirroring how\n * the spec author writes them (the API expects ids on write, which sync.ts\n * resolves from the property's environments).\n */\n environmentConstraints?: LiveEnvironmentConstraints | null;\n /** Sandbox template name (already resolved id→name on the GET response). */\n sandboxTemplate?: { id: string; name: string } | null;\n /**\n * Teardown linkage on seed workflows. The DB row has these directly; the GET\n * response carries the resolved teardown workflow name when the FK is set,\n * so pull can emit by-name without an extra lookup.\n */\n teardownWorkflowId?: string | null;\n teardownWorkflowName?: string | null;\n teardownSnapshotVersion?: number | null;\n teardownEnabled?: boolean | null;\n /**\n * Declared seed outputs from `seedOutputsJson`. The GET response should\n * resolve `propertyId` → `propertyName` for round-trip cleanliness; when it\n * doesn't, the diff falls back to id-form comparison (which won't match\n * spec-side names — surfaces as \"changed\" — but won't silently clobber the\n * data either).\n */\n seedOutputs?: Array<{\n dataKey: string;\n name?: string;\n displayLabel?: string;\n description?: string;\n propertyId?: string;\n propertyName?: string;\n /** Opaque preserved data — credentialOutput, attributes — sidecar PR will surface. */\n credentialOutput?: unknown;\n attributes?: unknown;\n }>;\n inputsJson: unknown;\n scenariosJson: unknown;\n nodes: LiveNode[];\n /** Edges are optional for back-compat with diff callers; sync needs them for reconcile. */\n edges?: LiveEdge[];\n};\n\nexport type LiveEnvironmentConstraints =\n | { mode: 'only'; environmentIds: string[]; environmentNames?: string[] }\n | { mode: 'envTypes'; types: Array<'permanent' | 'ephemeral' | 'local' | 'sandbox'> };\n\n/* ── Operation list ───────────────────────────────────────────────────── */\n\nexport type SpecOp =\n | {\n kind: 'create';\n /** Position of the corresponding spec node in EmittedWorkflow.nodes. */\n specIndex: number;\n nodeType: string;\n configJson: Record<string, unknown>;\n /** Final orderIndex this node should land at (post-diff). */\n orderIndex: number;\n /** Source line of the spec lead-in, so writeback knows where to inject `@id`. */\n sourceLine?: number;\n }\n | {\n kind: 'update';\n nodeId: string;\n /** Same `specIndex` semantics as `create`. */\n specIndex: number;\n nodeType: string;\n /** Full replacement configJson (the route merges, so this overrides). */\n configJson: Record<string, unknown>;\n orderIndex: number;\n /** What changed — for the human summary printout. */\n changes: {\n configChanged: boolean;\n orderChanged: boolean;\n fromOrderIndex: number;\n };\n }\n | { kind: 'delete'; nodeId: string; nodeType: string; orderIndex: number };\n\nexport type WorkflowFieldChanges = {\n description?: string | null;\n preflight?: string | null;\n cleanup?: string | null;\n inputsJson?: unknown;\n scenariosJson?: unknown;\n name?: string;\n status?: 'draft' | 'approved';\n flowType?: 'standard' | 'setup' | 'seed' | 'teardown';\n apiOnly?: boolean;\n /** Tag names — sync.ts resolves to ids and calls the bulk-tags endpoint. */\n tags?: string[];\n /**\n * Environment constraints (name-form). sync.ts resolves environmentNames →\n * environmentIds before PUT. `null` clears constraints.\n */\n environmentConstraints?:\n | { mode: 'only'; environmentNames: string[] }\n | { mode: 'envTypes'; types: Array<'permanent' | 'ephemeral' | 'local' | 'sandbox'> }\n | null;\n /** Sandbox template name; sync.ts resolves to id. `null` clears the template. */\n sandboxTemplate?: string | null;\n /**\n * Teardown linkage (seed workflows only). Spec carries the teardown spec\n * NAME; sync.ts resolves to the teardown workflow id and PATCHes the seed.\n * `null` on `teardownSpec` clears the link. `enabled`/`snapshotVersion`\n * surface independently so a snapshot pin or disable doesn't require\n * renaming the link.\n */\n teardownSpec?: string | null;\n teardownSnapshotVersion?: 'latest' | number | null;\n teardownEnabled?: boolean;\n /**\n * Spec-form declared outputs. Names → ids resolved by sync.ts. The diff\n * preserves `credentialOutput`/`attributes` from the live row 1:1 — the spec\n * doesn't author those yet, so we never want to clear them by accident.\n */\n seedOutputs?: Array<{\n dataKey: string;\n label?: string;\n description?: string;\n propertyName?: string;\n /** When a live entry carries this, sync.ts preserves it on the wire. */\n credentialOutput?: unknown;\n attributes?: unknown;\n }>;\n};\n\nexport type DiffResult = {\n ops: SpecOp[];\n workflowFieldChanges: WorkflowFieldChanges;\n /** Spec names a different name than the live workflow (we'll update to match). */\n nameDrift: { from: string; to: string } | null;\n /** Spec has two nodes claiming the same `@id` — second one is treated as new. */\n duplicateSpecIds: string[];\n /** Spec node references an `@id` that doesn't exist on the live workflow. */\n orphanedSpecIds: string[];\n};\n\n/* ── Errors ───────────────────────────────────────────────────────────── */\n\nexport class NodeTypeMutationError extends Error {\n constructor(public readonly nodeId: string, fromType: string, toType: string) {\n super(\n `Node ${nodeId} cannot change type from \"${fromType}\" to \"${toType}\". ` +\n `Remove the @id from the spec and let the diff CREATE a fresh node.`,\n );\n this.name = 'NodeTypeMutationError';\n }\n}\n\n/* ── Main entry point ─────────────────────────────────────────────────── */\n\nexport function diffWorkflow(spec: EmittedWorkflow, live: LiveWorkflow): DiffResult {\n const ops: SpecOp[] = [];\n const duplicateSpecIds: string[] = [];\n const orphanedSpecIds: string[] = [];\n\n // Build a lookup from live node ID → live node.\n const liveById = new Map<string, LiveNode>();\n for (const n of live.nodes) liveById.set(n.id, n);\n\n // Track which live IDs the spec consumes so the leftovers become DELETEs.\n const consumedLiveIds = new Set<string>();\n // Track spec IDs we've already paired so duplicates trigger a fresh CREATE.\n const seenSpecIds = new Set<string>();\n // Live orderIndexes of paired nodes, in spec order — used after the pass to\n // decide whether any genuine reorder happened (see below).\n const pairedOrderIndexes: number[] = [];\n\n spec.nodes.forEach((specNode, specIndex) => {\n let pairedLive: LiveNode | undefined;\n\n if (specNode.nodeId) {\n if (seenSpecIds.has(specNode.nodeId)) {\n // Duplicate `@id` from copy-paste — treat as a brand-new node.\n duplicateSpecIds.push(specNode.nodeId);\n } else {\n seenSpecIds.add(specNode.nodeId);\n const candidate = liveById.get(specNode.nodeId);\n if (candidate && !consumedLiveIds.has(candidate.id)) {\n pairedLive = candidate;\n consumedLiveIds.add(candidate.id);\n } else {\n // The spec carries an ID that doesn't exist on the live workflow\n // (orphan — workflow was rebuilt, ID stale). Treat as CREATE; the\n // writeback step will replace the stale ID with the fresh UUID.\n orphanedSpecIds.push(specNode.nodeId);\n }\n }\n } else if (specNode.nodeType === 'login') {\n // The leading login node is synthesized by `emit` from the `actor`\n // frontmatter, so it never carries an `@id`. Pair it positionally with\n // the first unconsumed live login so an unedited pull round-trips clean\n // (login nodes are never cached — a config change is harmless).\n const liveLogin = live.nodes.find(\n (n) => n.nodeType === 'login' && !consumedLiveIds.has(n.id),\n );\n if (liveLogin) {\n pairedLive = liveLogin;\n consumedLiveIds.add(liveLogin.id);\n }\n }\n\n if (pairedLive) {\n if (pairedLive.nodeType !== specNode.nodeType) {\n throw new NodeTypeMutationError(pairedLive.id, pairedLive.nodeType, specNode.nodeType);\n }\n // Compare authored identity, not raw configJson: a live node carries\n // runtime-only fields (playbookSteps, pageUrl, guidance) the spec can't\n // express, so a raw deep-compare would flag every run node as changed\n // and bust its replay cache on recompile. Hash equality means \"same\n // authored intent\" → no update → cache preserved.\n const configChanged =\n authoredNodeHash(pairedLive) !==\n authoredNodeHash({ nodeType: specNode.nodeType, configJson: specNode.configJson });\n pairedOrderIndexes.push(pairedLive.orderIndex);\n ops.push({\n kind: 'update',\n nodeId: pairedLive.id,\n specIndex,\n nodeType: specNode.nodeType,\n configJson: specNode.configJson,\n orderIndex: specIndex,\n changes: {\n // orderChanged is finalized after the pass (needs the full sequence).\n configChanged,\n orderChanged: false,\n fromOrderIndex: pairedLive.orderIndex,\n },\n });\n } else {\n ops.push({\n kind: 'create',\n specIndex,\n nodeType: specNode.nodeType,\n configJson: specNode.configJson,\n orderIndex: specIndex,\n sourceLine: specNode.sourceLine,\n });\n }\n });\n\n // Finalize orderChanged. If the paired nodes are already in the spec's\n // relative order (strictly ascending live orderIndexes — gaps allowed), no\n // reorder is needed: leave their orderIndex untouched so non-contiguous\n // indexes don't trigger needless PUTs (which would bust caches). Only when a\n // genuine reorder is present do we renumber every moved node to its dense\n // spec position (collision-free, since each gets a distinct specIndex).\n // Non-decreasing (not strictly increasing): live data can carry duplicate\n // orderIndexes (e.g. a seed and login both at 0). Only a genuine decrease\n // indicates a reorder.\n const relativeOrderPreserved = pairedOrderIndexes.every(\n (v, i) => i === 0 || v >= pairedOrderIndexes[i - 1],\n );\n if (!relativeOrderPreserved) {\n for (const op of ops) {\n if (op.kind === 'update') {\n op.changes.orderChanged = op.changes.fromOrderIndex !== op.orderIndex;\n }\n }\n }\n\n // Anything left on the live side is a DELETE.\n for (const liveNode of live.nodes) {\n if (!consumedLiveIds.has(liveNode.id)) {\n ops.push({\n kind: 'delete',\n nodeId: liveNode.id,\n nodeType: liveNode.nodeType,\n orderIndex: liveNode.orderIndex,\n });\n }\n }\n\n /* ── Top-level workflow fields ──────────────────────────────────────── */\n const workflowFieldChanges: WorkflowFieldChanges = {};\n if (spec.description !== live.description) workflowFieldChanges.description = spec.description;\n if (spec.preflight !== live.preflight) workflowFieldChanges.preflight = spec.preflight;\n if (spec.cleanup !== live.cleanup) workflowFieldChanges.cleanup = spec.cleanup;\n\n // Status / flowType: only push when the spec sets a value AND it differs.\n // Live `flowType` defaults to 'standard' when the spec omits it — don't churn.\n if (spec.status !== undefined && spec.status !== live.status) {\n workflowFieldChanges.status = spec.status;\n }\n // flowType: tracking only the explicit change. If spec omits flowType AND\n // live row is non-standard (e.g. seed), don't churn — that's an authoring\n // ambiguity, not a drift.\n if (spec.flowType !== undefined && spec.flowType !== live.flowType) {\n workflowFieldChanges.flowType = spec.flowType;\n }\n\n // apiOnly: spec omitting it = false. Only diff when live differs.\n const specApiOnly = spec.apiOnly === true;\n const liveApiOnly = live.apiOnly === true;\n if (specApiOnly !== liveApiOnly) workflowFieldChanges.apiOnly = specApiOnly;\n\n // Tags: compare sorted name-sets. Spec omitting `tags` = no constraint\n // (don't strip live tags); empty array = explicit \"no tags\" (strip).\n if (spec.tags !== undefined) {\n const specSet = [...spec.tags].sort();\n const liveSet = (live.tags ?? []).map((t) => t.name).sort();\n if (specSet.length !== liveSet.length || specSet.some((v, i) => v !== liveSet[i])) {\n workflowFieldChanges.tags = spec.tags;\n }\n }\n\n // Environment constraints: compare in name-form (the form the spec authors).\n // Spec omitting = no change; spec setting = full replacement.\n if (spec.environmentConstraints !== undefined) {\n if (!sameEnvConstraints(spec.environmentConstraints, live.environmentConstraints)) {\n workflowFieldChanges.environmentConstraints = spec.environmentConstraints;\n }\n }\n\n // Sandbox template: compare by name (live resolves id→name on GET).\n if (spec.sandboxTemplate !== undefined) {\n const liveName = live.sandboxTemplate?.name ?? null;\n if (spec.sandboxTemplate !== liveName) {\n workflowFieldChanges.sandboxTemplate = spec.sandboxTemplate;\n }\n }\n\n // Teardown linkage: only meaningful for seed workflows; for non-seeds the\n // API clears these on flowType change. Compare each axis independently — a\n // snapshot pin or disable shouldn't be conflated with relinking.\n if (spec.teardownSpec !== undefined) {\n const liveName = live.teardownWorkflowName ?? null;\n if (spec.teardownSpec !== liveName) workflowFieldChanges.teardownSpec = spec.teardownSpec;\n }\n if (spec.teardownSnapshotVersion !== undefined) {\n // Normalize: 'latest' equals the DB form `null` (always use latest).\n const specVal: number | null =\n spec.teardownSnapshotVersion === 'latest' ? null : spec.teardownSnapshotVersion;\n const liveVal = live.teardownSnapshotVersion ?? null;\n if (specVal !== liveVal) {\n workflowFieldChanges.teardownSnapshotVersion = spec.teardownSnapshotVersion;\n }\n }\n if (spec.teardownEnabled !== undefined) {\n const liveVal = live.teardownEnabled === true;\n if (spec.teardownEnabled !== liveVal) {\n workflowFieldChanges.teardownEnabled = spec.teardownEnabled;\n }\n }\n\n // Seed declared outputs: compare on the authored slice (dataKey, label,\n // description, propertyName). Merge live `credentialOutput`/`attributes` per\n // dataKey on the merged entries so sync.ts re-sends them intact (the spec\n // doesn't author them yet; clobbering would lose UI-authored configs).\n if (spec.seedOutputs !== undefined) {\n const liveByKey = new Map(\n (live.seedOutputs ?? []).map((o) => [o.dataKey, o] as const),\n );\n const sliced = (live.seedOutputs ?? []).map((o) => ({\n dataKey: o.dataKey,\n label: o.displayLabel,\n description: o.description,\n propertyName: o.propertyName,\n }));\n const specSliced = spec.seedOutputs.map((o) => ({\n dataKey: o.dataKey,\n label: o.label,\n description: o.description,\n propertyName: o.propertyName,\n }));\n if (!seedOutputsEqual(sliced, specSliced)) {\n // Reattach preserved fields per dataKey for the wire payload.\n workflowFieldChanges.seedOutputs = spec.seedOutputs.map((o) => {\n const liveRow = liveByKey.get(o.dataKey);\n return {\n dataKey: o.dataKey,\n label: o.label,\n description: o.description,\n propertyName: o.propertyName,\n ...(liveRow?.credentialOutput !== undefined\n ? { credentialOutput: liveRow.credentialOutput }\n : {}),\n ...(liveRow?.attributes !== undefined ? { attributes: liveRow.attributes } : {}),\n };\n });\n }\n }\n\n // Inputs/scenarios: compare only the authorable slice. The live workflow\n // carries richer definitions (input label/type/required, scenario UUIDs)\n // that the `.canary.md` grammar can't express; `emit` reproduces only\n // name/defaultValue (inputs) and name/values/credentials (scenarios). A raw\n // deep-compare would flag these as changed on every pull and overwrite the\n // rich fields with the lossy spec form. Only flag — and push — when the\n // authored content actually differs.\n if (!deepEquals(authoredInputs(live.inputsJson), authoredInputs(spec.inputsJson))) {\n workflowFieldChanges.inputsJson = spec.inputsJson;\n }\n if (!deepEquals(authoredScenarios(live.scenariosJson), authoredScenarios(spec.scenariosJson))) {\n workflowFieldChanges.scenariosJson = spec.scenariosJson;\n }\n\n const nameDrift = spec.name !== live.name ? { from: live.name, to: spec.name } : null;\n if (nameDrift) workflowFieldChanges.name = spec.name;\n\n return { ops, workflowFieldChanges, nameDrift, duplicateSpecIds, orphanedSpecIds };\n}\n\n/* ── Helpers ──────────────────────────────────────────────────────────── */\n\n/**\n * Authorable slice of `inputsJson` — the (kind, name, defaultValue) triples a\n * `.canary.md` `## Inputs` list can express. Drops label/type/required and\n * normalizes a missing default to '' so live and round-tripped forms match.\n */\nfunction authoredInputs(raw: unknown): Array<{ kind: string; name: string; defaultValue: string }> {\n if (!Array.isArray(raw)) return [];\n const out: Array<{ kind: string; name: string; defaultValue: string }> = [];\n for (const i of raw) {\n if (!i || typeof i !== 'object') continue;\n const rec = i as Record<string, unknown>;\n if (typeof rec.name !== 'string') continue;\n out.push({\n kind: rec.kind === 'credential' ? 'credential' : 'value',\n name: rec.name,\n defaultValue: typeof rec.defaultValue === 'string' ? rec.defaultValue : '',\n });\n }\n return out;\n}\n\n/**\n * Authorable slice of `scenariosJson` — name, description, default/skip flags,\n * and value/credential overrides. Drops the per-scenario UUID (`emit`\n * regenerates it each compile) so an unedited pull doesn't churn scenarios.\n */\nfunction authoredScenarios(raw: unknown): Array<Record<string, unknown>> {\n if (!Array.isArray(raw)) return [];\n const out: Array<Record<string, unknown>> = [];\n for (const s of raw) {\n if (!s || typeof s !== 'object') continue;\n const rec = s as Record<string, unknown>;\n if (typeof rec.name !== 'string') continue;\n out.push({\n name: rec.name,\n description: typeof rec.description === 'string' ? rec.description : '',\n isDefault: rec.isDefault === true,\n includeInSuite: rec.includeInSuite !== false,\n values: strRecord(rec.values),\n credentials: strRecord(rec.credentials),\n });\n }\n return out;\n}\n\n/**\n * True when spec and live environment constraints describe the same set. The\n * spec carries names (which the author writes); the live workflow carries ids\n * plus, when the API resolved them, names. Compare on the field the spec\n * sets — environment names for `only`, types for `envTypes`.\n */\nfunction sameEnvConstraints(\n spec: WorkflowFieldChanges['environmentConstraints'],\n live: LiveEnvironmentConstraints | null | undefined,\n): boolean {\n if (spec === null || spec === undefined) return !live;\n if (!live) return false;\n if (spec.mode !== live.mode) return false;\n if (spec.mode === 'only' && live.mode === 'only') {\n const a = [...spec.environmentNames].sort();\n const b = [...(live.environmentNames ?? [])].sort();\n return a.length === b.length && a.every((v, i) => v === b[i]);\n }\n if (spec.mode === 'envTypes' && live.mode === 'envTypes') {\n const a = [...spec.types].sort();\n const b = [...live.types].sort();\n return a.length === b.length && a.every((v, i) => v === b[i]);\n }\n return false;\n}\n\n/**\n * Order-insensitive compare on the authored slice of seed outputs. Two arrays\n * match when they cover the same set of dataKeys and every per-key (label,\n * description, propertyName) triple agrees.\n */\nfunction seedOutputsEqual(\n a: Array<{ dataKey: string; label?: string; description?: string; propertyName?: string }>,\n b: Array<{ dataKey: string; label?: string; description?: string; propertyName?: string }>,\n): boolean {\n if (a.length !== b.length) return false;\n const sortByKey = (rows: typeof a) => [...rows].sort((x, y) => x.dataKey.localeCompare(y.dataKey));\n const xa = sortByKey(a);\n const xb = sortByKey(b);\n for (let i = 0; i < xa.length; i++) {\n if (xa[i].dataKey !== xb[i].dataKey) return false;\n if ((xa[i].label ?? '') !== (xb[i].label ?? '')) return false;\n if ((xa[i].description ?? '') !== (xb[i].description ?? '')) return false;\n if ((xa[i].propertyName ?? '') !== (xb[i].propertyName ?? '')) return false;\n }\n return true;\n}\n\nfunction strRecord(v: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (v && typeof v === 'object') {\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) {\n if (typeof val === 'string') out[k] = val;\n }\n }\n return out;\n}\n\nfunction deepEquals(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null) return a === b;\n if (typeof a !== typeof b) return false;\n if (typeof a !== 'object') return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!deepEquals(a[i], b[i])) return false;\n }\n return true;\n }\n const ao = a as Record<string, unknown>;\n const bo = b as Record<string, unknown>;\n const ak = Object.keys(ao);\n const bk = Object.keys(bo);\n if (ak.length !== bk.length) return false;\n for (const k of ak) {\n if (!Object.prototype.hasOwnProperty.call(bo, k)) return false;\n if (!deepEquals(ao[k], bo[k])) return false;\n }\n return true;\n}\n\n/* ── Summary printout ─────────────────────────────────────────────────── */\n\nexport type DiffSummary = {\n created: number;\n updated: number;\n deleted: number;\n moved: number;\n unchanged: number;\n};\n\nexport function summarize(diff: DiffResult): DiffSummary {\n let created = 0;\n let updated = 0;\n let deleted = 0;\n let moved = 0;\n let unchanged = 0;\n for (const op of diff.ops) {\n if (op.kind === 'create') created++;\n else if (op.kind === 'delete') deleted++;\n else if (op.kind === 'update') {\n if (op.changes.configChanged) updated++;\n if (op.changes.orderChanged) moved++;\n if (!op.changes.configChanged && !op.changes.orderChanged) unchanged++;\n }\n }\n return { created, updated, deleted, moved, unchanged };\n}\n\nexport function hasAnyChange(diff: DiffResult): boolean {\n if (diff.ops.some((op) => op.kind !== 'update' || op.changes.configChanged || op.changes.orderChanged)) return true;\n return Object.keys(diff.workflowFieldChanges).length > 0;\n}\n\n/* ── Linear edge reconciliation ───────────────────────────────────────── */\n\nexport type EdgeOp =\n | { kind: 'delete'; edgeId: string }\n | { kind: 'create'; sourceNodeId: string; targetNodeId: string };\n\nexport type EdgeReconcileResult = {\n ops: EdgeOp[];\n};\n\n/**\n * Given the final ordered list of node UUIDs (post-diff) and the current edges\n * on the live workflow, compute the minimal DELETE/POST ops to make the live\n * `default` edges form a linear chain through `finalNodeIds` in order.\n *\n * Non-default edges (e.g. condition `then`/`else`) are left alone — the spec\n * compiler doesn't author them today, so we don't touch them.\n */\nexport function reconcileLinearEdges(\n finalNodeIds: string[],\n liveEdges: LiveEdge[],\n): EdgeReconcileResult {\n const desired = new Set<string>();\n for (let i = 0; i < finalNodeIds.length - 1; i++) {\n desired.add(`${finalNodeIds[i]}→${finalNodeIds[i + 1]}`);\n }\n\n const ops: EdgeOp[] = [];\n const haveDefault = new Set<string>();\n\n for (const e of liveEdges) {\n if (e.edgeType !== 'default') continue;\n const key = `${e.sourceNodeId}→${e.targetNodeId}`;\n if (desired.has(key)) {\n haveDefault.add(key);\n } else {\n ops.push({ kind: 'delete', edgeId: e.id });\n }\n }\n\n for (const key of desired) {\n if (haveDefault.has(key)) continue;\n const [sourceNodeId, targetNodeId] = key.split('→');\n ops.push({ kind: 'create', sourceNodeId, targetNodeId });\n }\n\n return { ops };\n}\n","/**\n * Round-trippable reverse-render: a live workflow → `.canary.md` source.\n *\n * Unlike `materialize.ts` (a best-effort, read-only view for agents), this\n * emitter is the inverse of `parse` ∘ `emit` over the *authorable* slice of a\n * workflow. It stamps `workflowId:` into frontmatter and `<!-- @id <uuid> -->`\n * onto every journey node's lead-in, so the file can be edited and pushed back\n * with `canary spec compile`:\n *\n * - node identity is keyed by `@id`, so edits update in place;\n * - unedited nodes hash-match on recompile (see `node-hash.ts`), so the diff\n * skips them and their recorded playbook + cache survive.\n *\n * Runtime-only data (playbookSteps, the live pageUrl an action ran against,\n * agent guidance) has no spec syntax and is intentionally dropped — it lives\n * on the server node and is preserved by the merge-on-update route, not the\n * spec.\n *\n * @module spec/pull\n */\n\nimport type { LiveNode, LiveWorkflow } from './diff.js';\nimport { normalizeDeclaredInputReferences } from './input-refs.js';\nimport { authoredActionFields, authoredActionTitle, loginCredentialRef } from './node-hash.js';\n\n/** A live workflow plus the cosmetic extras the GET response carries. */\nexport type PullWorkflow = LiveWorkflow & {\n tags?: Array<{ name: string }> | null;\n};\n\n// `LiveWorkflow` already carries `teardownWorkflowName` (it's set in the GET\n// workflow route) — re-exporting here would shadow it; consumers reach it via\n// `PullWorkflow.teardownWorkflowName` directly.\n\nexport interface PullOptions {\n /**\n * Force a `requirementRef` value (e.g. a ticket URL). When omitted, the CLI\n * preserves the prior file's value via `preserveFrontmatter`.\n */\n requirementRef?: string;\n /**\n * Per-scenario `skipReason` overrides keyed by scenario name. Spec-source-only;\n * the CLI seeds this from the prior file so re-pull doesn't drop the notes.\n */\n preserveScenarioSkipReasons?: Record<string, string>;\n}\n\nexport function workflowToSpec(workflow: PullWorkflow, opts: PullOptions = {}): string {\n const lines: string[] = [];\n const sorted = [...workflow.nodes].sort((a, b) => a.orderIndex - b.orderIndex);\n const inputs = readInputs(workflow.inputsJson);\n const inputNames = new Set(inputs.map((i) => i.name));\n // The auth login is the first login node, skipping any leading seed/setup\n // nodes that provision data before authentication. It's represented by the\n // `actor`/`authenticated` frontmatter (emit re-injects it at this position),\n // not as a journey node.\n let firstNonSeed = 0;\n while (\n firstNonSeed < sorted.length &&\n (sorted[firstNonSeed].nodeType === 'seed' || sorted[firstNonSeed].nodeType === 'setup')\n ) {\n firstNonSeed++;\n }\n const authLogin = sorted[firstNonSeed]?.nodeType === 'login' ? sorted[firstNonSeed] : undefined;\n\n // ── Frontmatter ─────────────────────────────────────────────────────────\n // An auth login → authenticated, whether or not we can name its credential\n // (an empty/UUID-only login still round-trips via emit's bare login).\n const authenticated = !!authLogin;\n const actor = authLogin ? inferActor(authLogin) : null;\n lines.push('---');\n lines.push(`name: ${yamlScalar(workflow.name)}`);\n lines.push(`workflowId: ${workflow.id}`);\n // Only user-settable approval-axis values round-trip; omit system states\n // (generating/building/…) so re-compile leaves status to the server.\n if (workflow.status === 'draft' || workflow.status === 'approved') {\n lines.push(`status: ${workflow.status}`);\n }\n if (workflow.flowType && workflow.flowType !== 'standard') {\n lines.push(`flowType: ${workflow.flowType}`);\n }\n if (actor) lines.push(`actor: ${yamlScalar(actor)}`);\n lines.push(`authenticated: ${authenticated ? 'true' : 'false'}`);\n if (workflow.apiOnly === true) lines.push('apiOnly: true');\n const tags = (workflow.tags ?? []).map((t) => t.name).filter(Boolean);\n if (tags.length > 0) lines.push(`tags: [${tags.map(yamlScalar).join(', ')}]`);\n const envBlock = renderEnvironments(workflow.environmentConstraints);\n if (envBlock) lines.push(...envBlock);\n if (workflow.sandboxTemplate?.name) {\n lines.push(`sandboxTemplate: ${yamlScalar(workflow.sandboxTemplate.name)}`);\n }\n const teardownLines = renderTeardown(workflow);\n if (teardownLines) lines.push(...teardownLines);\n // `requirementRef` is a spec-source-only field — the live workflow has no\n // column for it, so pull preserves it from the prior file via the CLI's\n // `preserveFrontmatter` merge. `opts.requirementRef` lets the caller force\n // a specific value (e.g. on first pull where no prior file exists).\n if (opts.requirementRef) lines.push(`requirementRef: ${yamlScalar(opts.requirementRef)}`);\n lines.push('---');\n lines.push('');\n\n lines.push(`# ${workflow.name}`);\n lines.push('');\n\n // ── Spirit / Preflight / Cleanup ─────────────────────────────────────────\n if (workflow.description) {\n lines.push('## Spirit');\n lines.push(blockquote(workflow.description));\n lines.push('');\n }\n if (workflow.preflight) {\n lines.push('## Preflight');\n lines.push(workflow.preflight.trim());\n lines.push('');\n }\n if (workflow.cleanup) {\n lines.push('## Cleanup');\n lines.push(workflow.cleanup.trim());\n lines.push('');\n }\n\n // ── Inputs ────────────────────────────────────────────────────────────────\n if (inputs.length > 0) {\n lines.push('## Inputs');\n for (const i of inputs) {\n const prefix = i.kind === 'credential' ? 'credential ' : '';\n lines.push(`- ${prefix}${i.name}: ${inputValue(i.defaultValue)}`);\n }\n lines.push('');\n }\n\n // ── Scenarios ──────────────────────────────────────────────────────────────\n // Per-scenario `skipReason` is a spec-source-only field (no scenariosJson\n // column for it). The caller seeds `opts.preserveScenarioSkipReasons` from\n // the prior file so re-pull doesn't drop the author's notes.\n const scenarios = readScenarios(workflow.scenariosJson);\n const skipReasons = opts.preserveScenarioSkipReasons ?? {};\n if (scenarios.length > 0) {\n lines.push('## Scenarios');\n lines.push('');\n for (const s of scenarios) {\n let heading = `### ${s.name}`;\n const skipReason = skipReasons[s.name];\n if (s.isDefault) heading += ' *(default)*';\n else if (!s.includeInSuite) {\n heading += skipReason ? ` *(skip: ${skipReason})*` : ' *(skip)*';\n }\n lines.push(heading);\n if (s.description) lines.push(`- description: ${s.description}`);\n if (Object.keys(s.values).length > 0) {\n lines.push('- values:');\n for (const [k, v] of Object.entries(s.values)) lines.push(` ${k}: ${yamlScalar(v)}`);\n }\n if (Object.keys(s.credentials).length > 0) {\n lines.push('- credentials:');\n for (const [k, v] of Object.entries(s.credentials))\n lines.push(` ${k}: ${yamlScalar(v)}`);\n }\n lines.push('');\n }\n }\n\n // ── Declared Outputs ─────────────────────────────────────────────────────\n // Seed workflows declare the values they hand off to downstream tests. Pull\n // emits the authored slice (dataKey, label, description, property). When a\n // live entry carries a `credentialOutput` config, pull notes it with a\n // comment so the author isn't surprised that the full credential config is\n // preserved opaquely (sidecar grammar lands in a follow-up).\n const declaredOutputBlock = renderDeclaredOutputs(workflow.seedOutputs);\n if (declaredOutputBlock) {\n lines.push('## Declared Outputs');\n lines.push('');\n lines.push(...declaredOutputBlock);\n lines.push('');\n }\n\n // ── Journey ────────────────────────────────────────────────────────────────\n lines.push('## Journey');\n lines.push('');\n for (const node of sorted) {\n if (node === authLogin) continue; // represented by `actor` frontmatter\n const block = renderNode(node, inputNames);\n if (block.length === 0) continue;\n block[0] = `${block[0]} <!-- @id ${node.id} -->`;\n lines.push(...block);\n lines.push('');\n }\n\n while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop();\n lines.push('');\n return lines.join('\\n');\n}\n\n/* ── Node rendering ───────────────────────────────────────────────────────── */\n\n/** Render a node to its `.canary.md` lines (lead-in first). */\nfunction renderNode(node: LiveNode, inputNames: ReadonlySet<string>): string[] {\n const c = node.configJson ?? {};\n const inputRef = (value: string): string => normalizeDeclaredInputReferences(value, inputNames);\n switch (node.nodeType) {\n case 'login': {\n // A non-leading login is a mid-journey role switch. The credential ref\n // lives inside the bold lead-in. We emit the explicit `credential <name>`\n // prefix when the live node is bound to a static credential, so the\n // parser round-trips it back to `{ kind: 'credential' }`; otherwise we\n // emit the bare template name for backward compatibility.\n return [`**Switch role to ${renderLoginRef(c)}**`];\n }\n case 'navigate':\n return [`**Navigate to** \\`${inputRef(str(c.pageUrl) ?? '/')}\\`.`];\n case 'action': {\n const title = inputRef(authoredActionTitle(c));\n const out = [`**Action — ${title}**`];\n const desc = str(c.actionDescription);\n if (desc && inputRef(desc) !== title) out.push(blockquote(inputRef(desc)));\n for (const f of authoredActionFields(c)) {\n const typeSuffix = f.type && f.type !== 'text' ? ` (${f.type})` : '';\n // Quote field names that aren't bare identifiers (spaces, punctuation).\n const name = /^[A-Za-z0-9_-]+$/.test(f.name) ? f.name : `\"${f.name}\"`;\n out.push(`- field ${name}${typeSuffix}: ${inputValue(inputRef(f.value))}`);\n }\n for (const cap of arr(c.declaredOutputs)) {\n if (typeof cap === 'string') out.push(`- capture: ${cap}`);\n }\n for (const a of arr(c.inlineAssertions)) {\n const cond = str(prop(a, 'condition'));\n if (!cond) continue;\n const sev = str(prop(a, 'severity')) ?? 'fail';\n const flags = prop(a, 'agentic') === true ? `${sev}, agentic` : sev;\n out.push(`- assert (${flags}): ${inputRef(cond)}`);\n }\n if (c.captureAudio === true) {\n out.push('- captureAudio: true');\n if (str(c.captureLabel)) out.push(`- captureLabel: ${str(c.captureLabel)}`);\n if (num(c.captureExtraMs) !== undefined)\n out.push(`- captureExtraMs: ${num(c.captureExtraMs)}`);\n }\n if (c.alwaysUseAgent === true) out.push('- alwaysUseAgent: true');\n return out;\n }\n case 'assertion': {\n const cond = inputRef(str(c.condition) ?? '?');\n const out = [`**Assert** ${cond}`];\n const desc = str(c.description);\n if (desc && inputRef(desc) !== cond) out.push(blockquote(inputRef(desc)));\n // Map legacy strict:true → fail so the severity isn't silently weakened.\n const severity = str(c.severity) ?? (c.strict === true ? 'fail' : 'warn');\n out.push(`- severity: ${severity}`);\n if (str(c.expectedOutcome)) out.push(`- expectedOutcome: ${str(c.expectedOutcome)}`);\n if (c.alwaysUseAgent === true) out.push('- alwaysUseAgent: true');\n return out;\n }\n case 'seed': {\n const name = str(c.seedWorkflowName) ?? '?';\n const out = [`**Seed** \\`${name}\\`.`];\n // Canonical keys (snapshotVersion/onFailure/executionMode), with legacy\n // alias fallback for older nodes.\n const snap = c.snapshotVersion ?? c.seedSnapshotVersion;\n if (typeof snap === 'number') out.push(`- version: ${snap}`);\n const onFailure = str(c.onFailure) ?? str(c.seedOnFailure);\n if (onFailure) out.push(`- onFailure: ${onFailure}`);\n const mode = str(c.executionMode) ?? str(c.seedExecutionMode);\n if (mode) out.push(`- mode: ${mode}`);\n if (str(c.scope)) out.push(`- scope: ${str(c.scope)}`);\n if (typeof c.runTeardown === 'boolean') out.push(`- runTeardown: ${c.runTeardown}`);\n if (c.inputValues && typeof c.inputValues === 'object') {\n for (const [key, value] of Object.entries(c.inputValues as Record<string, unknown>)) {\n if (typeof value === 'string') out.push(`- input.${key}: ${value}`);\n }\n }\n return out;\n }\n case 'setup': {\n const name = str(c.setupFlowName) ?? '?';\n const out = [`**Setup** \\`${name}\\`.`];\n if (typeof c.snapshotVersion === 'number') out.push(`- version: ${c.snapshotVersion}`);\n if (str(c.executionMode)) out.push(`- mode: ${str(c.executionMode)}`);\n return out;\n }\n case 'wait': {\n const secs = num(c.delaySeconds) ?? num(c.waitDuration) ?? 0;\n return [`**Wait** ${secs}s.`];\n }\n case 'condition': {\n // Flat: the real branch nodes are sibling nodes with their own @id.\n // Single-line expression lives inside the bold lead-in (`**If <expr>**`);\n // a multi-line expression goes in a blockquote under a bare `**If**`.\n const expr =\n str(c.conditionDescription) ?? str(c.conditionExpression) ?? str(c.description) ?? '?';\n const normalized = inputRef(expr);\n return normalized.includes('\\n')\n ? ['**If**', blockquote(normalized)]\n : [`**If ${normalized}**`];\n }\n case 'notification': {\n const channel = str(c.channel) ?? 'email';\n const to = inputRef(str(c.to) ?? '?');\n const out = [`**Notify ${channel}: ${to}**`];\n if (str(c.body)) out.push(blockquote(inputRef(str(c.body)!)));\n if (str(c.subject)) out.push(`- subject: ${inputRef(str(c.subject)!)}`);\n if (str(c.attachmentRef)) out.push(`- attach: ${str(c.attachmentRef)}`);\n return out;\n }\n case 'audio': {\n const ref = str(c.attachmentRef) ?? '?';\n const out = [`**Play audio** \\`${ref}\\``];\n if (c.loop === true) out.push('- loop: true');\n if (c.waitForCompletion === false) out.push('- waitForCompletion: false');\n if (str(c.label)) out.push(`- label: ${str(c.label)}`);\n return out;\n }\n case 'audio-assertion': {\n const det = obj(c.deterministic);\n const nl = obj(c.naturalLanguage);\n const prompt = str(nl?.prompt) ?? str(c.prompt);\n const model = str(nl?.model) ?? str(c.model);\n const out = [`**Assert audio** ${str(c.label) ?? '?'}`];\n out.push(`- severity: ${str(c.severity) ?? 'fail'}`);\n if (prompt) out.push(`- prompt: ${inputRef(prompt)}`);\n if (model) out.push(`- model: ${model}`);\n for (const [cfgKey, bulletKey] of [\n ['minDurationMs', 'minDurationMs'],\n ['maxDurationMs', 'maxDurationMs'],\n ['minRmsDb', 'minRmsDb'],\n ['silenceFractionMax', 'silenceFractionMax'],\n ['envelopeCorrelationMin', 'envelopeCorrelationMin'],\n ] as const) {\n const value = num(det?.[cfgKey]) ?? num(c[cfgKey]);\n if (value !== undefined) out.push(`- ${bulletKey}: ${value}`);\n }\n if (str(c.referenceAttachmentRef)) out.push(`- reference: ${str(c.referenceAttachmentRef)}`);\n return out;\n }\n case 'api_sequence': {\n const title = inputRef(str(c.customActionTitle) ?? str(c.title) ?? 'API sequence');\n const out = [`**API sequence — ${title}**`];\n if (str(c.apiEndpointContext)) out.push(blockquote(inputRef(str(c.apiEndpointContext)!)));\n if (str(c.credentialInputName)) out.push(`- credential: ${str(c.credentialInputName)}`);\n // Sidecar reference written by the CLI's pull flow when it fetches the\n // `/api-sequences/by-workflow/:id` config and stages it next to the spec.\n if (str(c.__apiSequenceSidecar)) {\n out.push(`- apiSequence: ${str(c.__apiSequenceSidecar)}`);\n }\n return out;\n }\n case 'sandbox_action': {\n const slug = str(c.actionSlug) ?? '?';\n const out = [`**Sandbox action — ${slug}**`];\n if (str(c.description)) out.push(blockquote(inputRef(str(c.description)!)));\n if (str(c.actionLabel)) out.push(`- label: ${str(c.actionLabel)}`);\n const params = obj(c.params);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (typeof value === 'string') out.push(`- param.${key}: ${value}`);\n }\n }\n const outputKeys = Array.isArray(c.outputKeys)\n ? c.outputKeys.filter((k): k is string => typeof k === 'string')\n : [];\n if (outputKeys.length > 0) out.push(`- outputs: ${outputKeys.join(', ')}`);\n return out;\n }\n case 'end':\n return [str(c.outcome) === 'fail' ? '**End (fail)**.' : '**End**.'];\n default:\n return [];\n }\n}\n\n/**\n * Extract spec-source-only fields from a prior `.canary.md` file the CLI\n * is about to overwrite. The live workflow row has no column for these, so\n * pulling without preservation would silently drop them on re-pull.\n *\n * Lifted as a tiny standalone parser to avoid pulling the full `parseSpec`\n * machinery (with its lint pass) just to read two fields.\n */\nexport function extractPreservedFrontmatter(priorSource: string): {\n requirementRef?: string;\n preserveScenarioSkipReasons?: Record<string, string>;\n} {\n const result: {\n requirementRef?: string;\n preserveScenarioSkipReasons?: Record<string, string>;\n } = {};\n\n // Frontmatter: a single `requirementRef:` key (top-level, no nesting).\n const fmMatch = priorSource.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (fmMatch) {\n const reqMatch = fmMatch[1].match(/^requirementRef:\\s*(.+)$/m);\n if (reqMatch) {\n const raw = reqMatch[1].trim();\n // Strip wrapping quotes (yamlScalar produces JSON.stringify for ambiguous values).\n const unquoted = raw.startsWith('\"') && raw.endsWith('\"') ? JSON.parse(raw) : raw;\n result.requirementRef = unquoted;\n }\n }\n\n // Scenarios: lift any `### <name> *(skip: <reason>)*` heading.\n const skipReasons: Record<string, string> = {};\n const re = /^###\\s+(.+?)\\s+\\*\\(skip:\\s*(.+?)\\)\\*\\s*$/gm;\n let m: RegExpExecArray | null;\n while ((m = re.exec(priorSource)) !== null) {\n const name = m[1].trim();\n const reason = m[2].trim();\n if (name && reason) skipReasons[name] = reason;\n }\n if (Object.keys(skipReasons).length > 0) {\n result.preserveScenarioSkipReasons = skipReasons;\n }\n\n return result;\n}\n\n/**\n * Render the `## Declared Outputs` section from a seed workflow's\n * `seedOutputsJson` rows. Each entry becomes a top-level bullet (the dataKey)\n * with indented sub-bullets for label/property/description. `credentialOutput`\n * configs surface as a \"preserved by server\" HTML comment under the entry so\n * the author knows there's UI-authored config they shouldn't try to\n * round-trip through the spec yet.\n */\nfunction renderDeclaredOutputs(outputs: LiveWorkflow['seedOutputs']): string[] | null {\n if (!outputs || outputs.length === 0) return null;\n const out: string[] = [];\n for (const o of outputs) {\n out.push(`- ${o.dataKey}`);\n const label = o.displayLabel ?? o.name;\n if (label && label !== o.dataKey) out.push(` - label: ${yamlScalar(label)}`);\n if (o.propertyName) out.push(` - property: ${yamlScalar(o.propertyName)}`);\n if (o.description) out.push(` - description: ${o.description}`);\n if (o.credentialOutput !== undefined) {\n out.push(' <!-- credentialOutput config preserved by the server; edit in UI for now -->');\n }\n out.push('');\n }\n // Trim trailing blank.\n while (out.length > 0 && out[out.length - 1] === '') out.pop();\n return out;\n}\n\n/**\n * Render `teardown:` frontmatter for seed workflows. Uses the bare-string\n * shorthand when defaults hold (snapshotVersion=latest, enabled=true); falls\n * back to the nested form when the author has pinned a snapshot or disabled.\n * The teardown name comes from the GET response's resolved `teardownWorkflowName`\n * — pull skips emission when the link is set but the name didn't resolve\n * (graceful, lets the follow-up endpoint enrichment kick in transparently).\n */\nfunction renderTeardown(workflow: LiveWorkflow): string[] | null {\n if (!workflow.teardownWorkflowId) return null;\n const name = workflow.teardownWorkflowName;\n if (!name) return null;\n const snap = workflow.teardownSnapshotVersion;\n const enabled = workflow.teardownEnabled !== false;\n // Shorthand: defaults hold.\n if ((snap === null || snap === undefined) && enabled) {\n return [`teardown: ${yamlScalar(name)}`];\n }\n // Nested form for non-defaults.\n const out = ['teardown:', ` spec: ${yamlScalar(name)}`];\n if (snap !== null && snap !== undefined) out.push(` snapshotVersion: ${snap}`);\n if (!enabled) out.push(' enabled: false');\n return out;\n}\n\n/**\n * Render `environmentConstraints` from the API GET shape (env *ids*, optionally\n * with names) into the spec frontmatter form (names only). Returns the YAML\n * lines for the `environments:` key, or null when no constraints are set.\n *\n * We deliberately omit the constraint when names aren't available — the GET\n * response is the only place to resolve id → name, and emitting bare ids\n * would not round-trip through the spec author's editing flow.\n */\nfunction renderEnvironments(constraints: LiveWorkflow['environmentConstraints']): string[] | null {\n if (!constraints) return null;\n if (constraints.mode === 'only') {\n const names = constraints.environmentNames;\n if (!names || names.length === 0) return null;\n return ['environments:', ` only: [${names.map(yamlScalar).join(', ')}]`];\n }\n return ['environments:', ` types: [${constraints.types.map(yamlScalar).join(', ')}]`];\n}\n\n/* ── Frontmatter / value helpers ──────────────────────────────────────────── */\n\n/**\n * Format a login's identity for the `**Switch role to <ref>**` lead-in.\n * Template-bound logins render as the bare role name (backward compatible);\n * from_seed logins render as `seed-output <dataKey>` so the dedicated syntax\n * round-trips faithfully; static-credential logins render with the explicit\n * `credential <name>` prefix so the parser reads them back correctly.\n */\nfunction renderLoginRef(c: Record<string, unknown>): string {\n if (c.credentialSource === 'from_seed') {\n const seedRef = c.seedCredentialRef as Record<string, unknown> | undefined;\n const ref =\n (typeof seedRef?.dataKey === 'string' && seedRef.dataKey) ||\n (typeof seedRef?.name === 'string' && seedRef.name);\n if (ref) return `seed-output ${ref}`;\n }\n const role = str(c.credentialTemplateName);\n if (role) return role;\n const cred = loginCredentialRef(c);\n if (cred) return `credential ${cred}`;\n return '?';\n}\n\nfunction inferActor(login: LiveNode): string | null {\n const c = login.configJson ?? {};\n // `from_seed` wins first so the dedicated syntax (`seed-output <ref>`)\n // round-trips faithfully instead of being lumped under `credential`.\n if (c.credentialSource === 'from_seed') {\n const seedRef = c.seedCredentialRef as Record<string, unknown> | undefined;\n const ref =\n (typeof seedRef?.dataKey === 'string' && seedRef.dataKey) ||\n (typeof seedRef?.name === 'string' && seedRef.name);\n if (ref) return `seed-output ${ref}`;\n }\n const role = str(c.credentialTemplateName);\n if (role) return role;\n // Static / template-by-id fall back to `credential <ref>` — uses the same\n // identity string as the hash, so it round-trips without churn regardless\n // of which static-binding mode the row stored.\n const cred = loginCredentialRef(c);\n if (cred) return `credential ${cred}`;\n return null;\n}\n\nfunction readInputs(\n raw: unknown\n): Array<{ kind: 'value' | 'credential'; name: string; defaultValue: string }> {\n if (!Array.isArray(raw)) return [];\n const out: Array<{ kind: 'value' | 'credential'; name: string; defaultValue: string }> = [];\n for (const i of raw) {\n if (!i || typeof i !== 'object') continue;\n const rec = i as Record<string, unknown>;\n if (typeof rec.name !== 'string') continue;\n out.push({\n kind: rec.kind === 'credential' ? 'credential' : 'value',\n name: rec.name,\n defaultValue: typeof rec.defaultValue === 'string' ? rec.defaultValue : '',\n });\n }\n return out;\n}\n\nfunction readScenarios(raw: unknown): Array<{\n name: string;\n description?: string;\n isDefault: boolean;\n includeInSuite: boolean;\n values: Record<string, string>;\n credentials: Record<string, string>;\n}> {\n if (!Array.isArray(raw)) return [];\n const out: ReturnType<typeof readScenarios> = [];\n for (const s of raw) {\n if (!s || typeof s !== 'object') continue;\n const rec = s as Record<string, unknown>;\n if (typeof rec.name !== 'string') continue;\n out.push({\n name: rec.name,\n description: typeof rec.description === 'string' ? rec.description : undefined,\n isDefault: rec.isDefault === true,\n includeInSuite: rec.includeInSuite !== false,\n values: strRecord(rec.values),\n credentials: strRecord(rec.credentials),\n });\n }\n return out;\n}\n\n/** Render an input/field value so the parser reads it back verbatim. */\nfunction inputValue(v: string): string {\n return v === '' ? '\"\"' : v;\n}\n\n/** Render `text` as a markdown blockquote, one `> ` per line. */\nfunction blockquote(text: string): string {\n return text\n .trim()\n .split('\\n')\n .map((l) => `> ${l}`)\n .join('\\n');\n}\n\n/** Quote a YAML scalar only when plain rendering would be ambiguous. */\nfunction yamlScalar(s: string): string {\n if (s === '') return '\"\"';\n if (/^[A-Za-z0-9 _\\-./@]+$/.test(s) && !/^\\s|\\s$/.test(s)) return s;\n return JSON.stringify(s);\n}\n\nfunction strRecord(v: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (v && typeof v === 'object') {\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) {\n if (typeof val === 'string') out[k] = val;\n }\n }\n return out;\n}\n\nfunction str(v: unknown): string | undefined {\n return typeof v === 'string' ? v : undefined;\n}\n\nfunction num(v: unknown): number | undefined {\n return typeof v === 'number' && Number.isFinite(v) ? v : undefined;\n}\n\nfunction arr(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n}\n\nfunction prop(v: unknown, key: string): unknown {\n return v && typeof v === 'object' ? (v as Record<string, unknown>)[key] : undefined;\n}\n\nfunction obj(v: unknown): Record<string, unknown> | null {\n return v && typeof v === 'object' && !Array.isArray(v) ? (v as Record<string, unknown>) : null;\n}\n","/**\n * Zod schema for the YAML sidecar that carries an api_sequence's full DSL\n * (steps, exports, validations). Mirrors `ApiSequenceConfig` in\n * `packages/types/src/api-sequence.ts` 1:1 — we mirror rather than import to\n * keep `@chatsdet/canary-spec` dependency-free of the runtime types package.\n *\n * The sidecar is referenced from the spec's api_sequence node via:\n *\n * **API sequence — Provision tenant**\n * - apiSequence: ./sequences/provision-tenant.yaml\n *\n * Multiple api_sequence nodes in the same workflow point at the same sidecar\n * (DB schema enforces one api_sequence row per workflow). For now the file\n * carries ids verbatim (apiRequestId, credentialId) — name → id resolution\n * lands in a follow-up; the round-trip stays clean either way because the\n * ids come straight from the live workflow on pull.\n *\n * @module spec/api-sequence-file\n */\n\nimport { z } from 'zod';\n\nconst ApiSequenceValidationSchema = z\n .object({\n kind: z.string().min(1).optional(),\n })\n .passthrough();\n\nconst ApiSequenceStepSchema = z.object({\n stepId: z.string().min(1).optional(),\n apiRequestId: z.string().min(1),\n credentialId: z.string().nullable().optional(),\n method: z.string().min(1).optional(),\n urlTemplate: z.string().optional(),\n queryParams: z\n .array(z.object({ key: z.string().min(1), value: z.string() }))\n .optional(),\n bodyTemplate: z.string().nullable().optional(),\n headersTemplate: z.record(z.string(), z.string()).nullable().optional(),\n responseVariableName: z.string().min(1).optional(),\n expectedStatusCodes: z.array(z.number().int()).optional(),\n description: z.string().optional(),\n validations: z.array(ApiSequenceValidationSchema).optional(),\n});\n\nconst ApiSequenceExportSchema = z.object({\n variableName: z.string().min(1),\n stepId: z.string().min(1),\n responsePath: z.string().min(1),\n source: z.enum(['request', 'response']).optional(),\n description: z.string().optional(),\n});\n\nexport const ApiSequenceFileSchema = z.object({\n description: z.string().optional(),\n stopOnFailure: z.boolean().optional(),\n steps: z.array(ApiSequenceStepSchema).default([]),\n exports: z.array(ApiSequenceExportSchema).default([]),\n});\n\nexport type ApiSequenceFile = z.infer<typeof ApiSequenceFileSchema>;\n","/**\n * In-place edits to a .canary.md spec file: write the workflow ID into\n * frontmatter on first compile, and write `<!-- @id <uuid> -->` next to\n * newly-created node lead-ins so recompile can key the diff on identity.\n *\n * Pure string transforms — `index.ts` reads/writes the file.\n *\n * @module spec/writeback\n */\n\nconst FRONTMATTER_FENCE = /^---\\s*$/;\n\n/**\n * Insert `workflowId: <uuid>` into the spec's frontmatter, immediately\n * after the `name:` line. If `workflowId:` already exists, returns the\n * source unchanged.\n */\nexport function writeWorkflowId(source: string, workflowId: string): string {\n const lines = source.split(/\\r?\\n/);\n if (!FRONTMATTER_FENCE.test(lines[0] ?? '')) return source;\n const end = findFrontmatterEnd(lines);\n if (end === -1) return source;\n\n // Already present?\n for (let i = 1; i < end; i++) {\n if (/^workflowId\\s*:/.test(lines[i])) return source;\n }\n\n // Insert after the first `name:` line, or fall back to the line before the fence.\n let insertAt = end;\n for (let i = 1; i < end; i++) {\n if (/^name\\s*:/.test(lines[i])) {\n insertAt = i + 1;\n break;\n }\n }\n\n const out = [...lines];\n out.splice(insertAt, 0, `workflowId: ${workflowId}`);\n return out.join('\\n');\n}\n\n/**\n * Insert `<!-- @id <uuid> -->` at the end of each lead-in line for the\n * given (sourceLine → nodeId) pairs. Lines are 0-indexed and refer to\n * line numbers in the **original** source (the same numbers the parser\n * recorded in `node.sourceLine`).\n *\n * Skips any line that already has an `@id` comment (idempotent).\n */\nexport function writeNodeIds(source: string, pairs: Array<{ sourceLine: number; nodeId: string }>): string {\n const lines = source.split(/\\r?\\n/);\n const NODE_ID_RE = /<!--\\s*@id\\s+[0-9a-f-]+\\s*-->/i;\n for (const { sourceLine, nodeId } of pairs) {\n if (sourceLine < 0 || sourceLine >= lines.length) continue;\n const line = lines[sourceLine];\n if (NODE_ID_RE.test(line)) continue;\n // Trim trailing whitespace, append the comment.\n lines[sourceLine] = `${line.trimEnd()} <!-- @id ${nodeId} -->`;\n }\n return lines.join('\\n');\n}\n\nfunction findFrontmatterEnd(lines: string[]): number {\n if (!FRONTMATTER_FENCE.test(lines[0] ?? '')) return -1;\n for (let i = 1; i < lines.length; i++) if (FRONTMATTER_FENCE.test(lines[i])) return i;\n return -1;\n}\n"],"mappings":"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","names":["body","stripped","obj","str","arr","prop","num","obj","strRecord","z","FRONTMATTER_FENCE","findFrontmatterEnd","NODE_ID_RE"]}