@runcofactor/cli 0.13.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/account-62I7FG5G.js +255 -0
  2. package/dist/account-62I7FG5G.js.map +1 -0
  3. package/dist/{api-catalog-7HLEN7C2.js → api-catalog-CAJUASVC.js} +5 -5
  4. package/dist/{attachment-OVNQD6Z2.js → attachment-RL4AZUJE.js} +5 -5
  5. package/dist/augmentor-GAF3MFY6.js +198 -0
  6. package/dist/augmentor-GAF3MFY6.js.map +1 -0
  7. package/dist/{auth-VUHL74FH.js → auth-DURHUZDW.js} +3 -3
  8. package/dist/{chunk-YN763NWQ.js → chunk-26U3DGUM.js} +10 -4
  9. package/dist/chunk-26U3DGUM.js.map +1 -0
  10. package/dist/{chunk-JZMJUPZP.js → chunk-32P26BZT.js} +3 -3
  11. package/dist/chunk-32P26BZT.js.map +1 -0
  12. package/dist/{chunk-QQVWGWPI.js → chunk-5R4HMSNX.js} +8561 -1511
  13. package/dist/chunk-5R4HMSNX.js.map +1 -0
  14. package/dist/{chunk-VGTKUOYS.js → chunk-AQPJQ5AE.js} +2 -2
  15. package/dist/{chunk-CQE46HSM.js → chunk-CFJXYPTF.js} +14 -8
  16. package/dist/chunk-CFJXYPTF.js.map +1 -0
  17. package/dist/{chunk-NL7CVG56.js → chunk-CJEKEW7R.js} +57 -10
  18. package/dist/chunk-CJEKEW7R.js.map +1 -0
  19. package/dist/{chunk-Z5LUTUDN.js → chunk-G5SXUXSU.js} +3 -3
  20. package/dist/{chunk-ZTOE3ND3.js → chunk-HKQ5XQAQ.js} +4 -4
  21. package/dist/{chunk-PZ4LCN6K.js → chunk-IGHDIWZU.js} +2 -2
  22. package/dist/{chunk-QGI4UCJX.js → chunk-IWKJQZJQ.js} +124 -74
  23. package/dist/chunk-IWKJQZJQ.js.map +1 -0
  24. package/dist/{chunk-ZD3KHESI.js → chunk-KRWRUU6R.js} +27 -7
  25. package/dist/chunk-KRWRUU6R.js.map +1 -0
  26. package/dist/{chunk-CRHPDPRS.js → chunk-PXFDH6YL.js} +63 -8
  27. package/dist/{chunk-CRHPDPRS.js.map → chunk-PXFDH6YL.js.map} +1 -1
  28. package/dist/{chunk-EJ4U242G.js → chunk-UZ2ZA5A6.js} +2 -2
  29. package/dist/{chunk-EEN2TZUQ.js → chunk-VKBTI5EF.js} +3 -3
  30. package/dist/{chunk-ENDHMYEJ.js → chunk-ZXRVFFCY.js} +3 -3
  31. package/dist/{credential-LO2SEEHU.js → credential-JGVSEGVH.js} +5 -5
  32. package/dist/{credential-template-ZN7W7734.js → credential-template-CWWMOKB2.js} +5 -5
  33. package/dist/{debug-workflow-R3RYYAXK.js → debug-workflow-BXRU72YZ.js} +5 -5
  34. package/dist/{docs-DIAFBDXQ.js → docs-PVBXPTGR.js} +95 -11
  35. package/dist/docs-PVBXPTGR.js.map +1 -0
  36. package/dist/{doctor-NZPUSCRE.js → doctor-RHMKD4W5.js} +3 -3
  37. package/dist/{environment-RQVU4P5M.js → environment-WZKIO3R3.js} +5 -5
  38. package/dist/{feature-flag-XG26RURR.js → feature-flag-K5REGGDY.js} +98 -12
  39. package/dist/feature-flag-K5REGGDY.js.map +1 -0
  40. package/dist/index.js +107 -51
  41. package/dist/index.js.map +1 -1
  42. package/dist/{init-EDNLKGPT.js → init-FFUZO5D7.js} +5 -5
  43. package/dist/{install-FYZ3HNZK.js → install-XRKEQAFZ.js} +5 -5
  44. package/dist/{issues-NNRVTJ4L.js → issues-I3V6GEXU.js} +5 -5
  45. package/dist/{knobs-A2BOBH22.js → knobs-6WLJMB44.js} +7 -6
  46. package/dist/knobs-6WLJMB44.js.map +1 -0
  47. package/dist/{list-F33VZ4BJ.js → list-PHC7VYNS.js} +5 -5
  48. package/dist/{local-DQDTM3XA.js → local-VGYRSW22.js} +7 -7
  49. package/dist/{login-BUMVIB36.js → login-QPU2BKG2.js} +5 -5
  50. package/dist/{mcp-B5Y5CDMQ.js → mcp-LA452TOA.js} +9 -9
  51. package/dist/{mcp-B5Y5CDMQ.js.map → mcp-LA452TOA.js.map} +1 -1
  52. package/dist/{pdf-extract-ABWV3L5X.js → pdf-extract-YHE54XU4.js} +2 -2
  53. package/dist/product-RSZV5HMB.js +346 -0
  54. package/dist/product-RSZV5HMB.js.map +1 -0
  55. package/dist/{property-NJ4SRXQG.js → property-YP4GHQAR.js} +5 -5
  56. package/dist/{psql-VBZFCMNR.js → psql-XGLBI6T7.js} +3 -3
  57. package/dist/{record-WAO36O7G.js → record-KWKHP2ZY.js} +6 -6
  58. package/dist/{redis-DHZXHL4S.js → redis-VJGCUJPV.js} +3 -3
  59. package/dist/redis-VJGCUJPV.js.map +1 -0
  60. package/dist/{release-STJKUKTE.js → release-NDRHPW6V.js} +5 -5
  61. package/dist/{sandbox-DWSGLY7B.js → sandbox-OOCANWOG.js} +51 -7
  62. package/dist/sandbox-OOCANWOG.js.map +1 -0
  63. package/dist/{scenarios-HCIDY725.js → scenarios-2HRLCGFY.js} +5 -5
  64. package/dist/{session-Y5RHU54D.js → session-M4ULYDYP.js} +8 -9
  65. package/dist/session-M4ULYDYP.js.map +1 -0
  66. package/dist/{skill-23WAHUOB.js → skill-4DGPRDUC.js} +10 -10
  67. package/dist/{skill-23WAHUOB.js.map → skill-4DGPRDUC.js.map} +1 -1
  68. package/dist/skills/debug-run/SKILL.md +7 -1
  69. package/dist/skills/debug-run/history/1.3.1.md +279 -0
  70. package/dist/skills/debug-run/version.json +1 -1
  71. package/dist/skills/optimize-cache/SKILL.md +41 -4
  72. package/dist/{spec-LM5XHOQ5.js → spec-XZ2TKUFZ.js} +5 -5
  73. package/dist/{src-BGDRMOKC.js → src-2FK3JHGW.js} +315 -104
  74. package/dist/src-2FK3JHGW.js.map +1 -0
  75. package/dist/{src-NCJPUAE6.js → src-CV57ZD6I.js} +10 -8
  76. package/dist/{src-22RI5VP2.js → src-HL7HEJIW.js} +2 -2
  77. package/dist/{src-Y3K7UJEF.js → src-OU7544PM.js} +6 -4
  78. package/dist/{start-SWY55CZX.js → start-IYKF3C3X.js} +5 -5
  79. package/dist/{tag-YSU2XXPI.js → tag-T45MMSCH.js} +6 -6
  80. package/dist/{task-NLBKLD7D.js → task-MCUHAVTD.js} +5 -5
  81. package/dist/{test-suite-QCPWZ2LS.js → test-suite-BICBRSBP.js} +10 -8
  82. package/dist/{test-suite-QCPWZ2LS.js.map → test-suite-BICBRSBP.js.map} +1 -1
  83. package/dist/trace-2BAPMYAS.js +16 -0
  84. package/dist/{triage-TT4BMDBU.js → triage-M3RZ2ASB.js} +6 -6
  85. package/dist/{upgrade-6ZUFETKX.js → upgrade-4QCRAUHP.js} +3 -3
  86. package/dist/{workflow-2CX3ZNOQ.js → workflow-4J23FV7K.js} +86 -15
  87. package/dist/workflow-4J23FV7K.js.map +1 -0
  88. package/dist/{workflow-cache-GXNE6SU2.js → workflow-cache-XPSK6KC7.js} +26 -13
  89. package/dist/workflow-cache-XPSK6KC7.js.map +1 -0
  90. package/dist/{workflow-debug-PRX3DWGD.js → workflow-debug-W4USZH35.js} +9 -9
  91. package/dist/{workflow-proposals-BW327WGL.js → workflow-proposals-5E3DTYZB.js} +5 -7
  92. package/dist/workflow-proposals-5E3DTYZB.js.map +1 -0
  93. package/package.json +5 -1
  94. package/dist/chunk-CQE46HSM.js.map +0 -1
  95. package/dist/chunk-JZMJUPZP.js.map +0 -1
  96. package/dist/chunk-NL7CVG56.js.map +0 -1
  97. package/dist/chunk-QGI4UCJX.js.map +0 -1
  98. package/dist/chunk-QQVWGWPI.js.map +0 -1
  99. package/dist/chunk-YN763NWQ.js.map +0 -1
  100. package/dist/chunk-ZD3KHESI.js.map +0 -1
  101. package/dist/docs-DIAFBDXQ.js.map +0 -1
  102. package/dist/feature-flag-XG26RURR.js.map +0 -1
  103. package/dist/knobs-A2BOBH22.js.map +0 -1
  104. package/dist/redis-DHZXHL4S.js.map +0 -1
  105. package/dist/sandbox-DWSGLY7B.js.map +0 -1
  106. package/dist/session-Y5RHU54D.js.map +0 -1
  107. package/dist/src-BGDRMOKC.js.map +0 -1
  108. package/dist/trace-A3ZY6K26.js +0 -16
  109. package/dist/workflow-2CX3ZNOQ.js.map +0 -1
  110. package/dist/workflow-cache-GXNE6SU2.js.map +0 -1
  111. package/dist/workflow-proposals-BW327WGL.js.map +0 -1
  112. /package/dist/{api-catalog-7HLEN7C2.js.map → api-catalog-CAJUASVC.js.map} +0 -0
  113. /package/dist/{attachment-OVNQD6Z2.js.map → attachment-RL4AZUJE.js.map} +0 -0
  114. /package/dist/{auth-VUHL74FH.js.map → auth-DURHUZDW.js.map} +0 -0
  115. /package/dist/{chunk-VGTKUOYS.js.map → chunk-AQPJQ5AE.js.map} +0 -0
  116. /package/dist/{chunk-Z5LUTUDN.js.map → chunk-G5SXUXSU.js.map} +0 -0
  117. /package/dist/{chunk-ZTOE3ND3.js.map → chunk-HKQ5XQAQ.js.map} +0 -0
  118. /package/dist/{chunk-PZ4LCN6K.js.map → chunk-IGHDIWZU.js.map} +0 -0
  119. /package/dist/{chunk-EJ4U242G.js.map → chunk-UZ2ZA5A6.js.map} +0 -0
  120. /package/dist/{chunk-EEN2TZUQ.js.map → chunk-VKBTI5EF.js.map} +0 -0
  121. /package/dist/{chunk-ENDHMYEJ.js.map → chunk-ZXRVFFCY.js.map} +0 -0
  122. /package/dist/{credential-LO2SEEHU.js.map → credential-JGVSEGVH.js.map} +0 -0
  123. /package/dist/{credential-template-ZN7W7734.js.map → credential-template-CWWMOKB2.js.map} +0 -0
  124. /package/dist/{debug-workflow-R3RYYAXK.js.map → debug-workflow-BXRU72YZ.js.map} +0 -0
  125. /package/dist/{doctor-NZPUSCRE.js.map → doctor-RHMKD4W5.js.map} +0 -0
  126. /package/dist/{environment-RQVU4P5M.js.map → environment-WZKIO3R3.js.map} +0 -0
  127. /package/dist/{init-EDNLKGPT.js.map → init-FFUZO5D7.js.map} +0 -0
  128. /package/dist/{install-FYZ3HNZK.js.map → install-XRKEQAFZ.js.map} +0 -0
  129. /package/dist/{issues-NNRVTJ4L.js.map → issues-I3V6GEXU.js.map} +0 -0
  130. /package/dist/{list-F33VZ4BJ.js.map → list-PHC7VYNS.js.map} +0 -0
  131. /package/dist/{local-DQDTM3XA.js.map → local-VGYRSW22.js.map} +0 -0
  132. /package/dist/{login-BUMVIB36.js.map → login-QPU2BKG2.js.map} +0 -0
  133. /package/dist/{pdf-extract-ABWV3L5X.js.map → pdf-extract-YHE54XU4.js.map} +0 -0
  134. /package/dist/{property-NJ4SRXQG.js.map → property-YP4GHQAR.js.map} +0 -0
  135. /package/dist/{psql-VBZFCMNR.js.map → psql-XGLBI6T7.js.map} +0 -0
  136. /package/dist/{record-WAO36O7G.js.map → record-KWKHP2ZY.js.map} +0 -0
  137. /package/dist/{release-STJKUKTE.js.map → release-NDRHPW6V.js.map} +0 -0
  138. /package/dist/{scenarios-HCIDY725.js.map → scenarios-2HRLCGFY.js.map} +0 -0
  139. /package/dist/{spec-LM5XHOQ5.js.map → spec-XZ2TKUFZ.js.map} +0 -0
  140. /package/dist/{src-NCJPUAE6.js.map → src-CV57ZD6I.js.map} +0 -0
  141. /package/dist/{src-22RI5VP2.js.map → src-HL7HEJIW.js.map} +0 -0
  142. /package/dist/{src-Y3K7UJEF.js.map → src-OU7544PM.js.map} +0 -0
  143. /package/dist/{start-SWY55CZX.js.map → start-IYKF3C3X.js.map} +0 -0
  144. /package/dist/{tag-YSU2XXPI.js.map → tag-T45MMSCH.js.map} +0 -0
  145. /package/dist/{task-NLBKLD7D.js.map → task-MCUHAVTD.js.map} +0 -0
  146. /package/dist/{trace-A3ZY6K26.js.map → trace-2BAPMYAS.js.map} +0 -0
  147. /package/dist/{triage-TT4BMDBU.js.map → triage-M3RZ2ASB.js.map} +0 -0
  148. /package/dist/{upgrade-6ZUFETKX.js.map → upgrade-4QCRAUHP.js.map} +0 -0
  149. /package/dist/{workflow-debug-PRX3DWGD.js.map → workflow-debug-W4USZH35.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/workflow.ts","../src/workflow-create.ts","../src/workflow-run.ts","../src/cli-format.ts","../src/workflow-runs.ts","../src/workflow-sync.ts","../src/workflow-api-sequence.ts","../src/workflow-api-sequence-cmds.ts","../src/workflow-seed-create.ts","../../content/src/workflow-guide/overview.txt","../../content/src/workflow-guide/node-types.txt","../../content/src/workflow-guide/playbook.txt","../../content/src/workflow-guide/best-practices.txt","../../content/src/workflow-guide/macros.txt","../../content/src/workflow-guide/seed-workflows.txt","../../content/src/workflow-guide/data-lifecycle.txt","../../content/src/workflow-guide/assertions.txt","../../content/src/workflow-guide/api-sequences.txt","../../content/src/workflow-guide/cli-seeds.txt","../../content/src/workflow-guide/cli-api-sequences.txt","../../content/src/workflow-guide/index.ts"],"sourcesContent":["/**\n * CLI Workflow Management\n *\n * Inspect workflow definitions and steps from the terminal.\n */\n\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { resolveConfig, resolveAppUrl, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest, renderWorkflowUserError } from './cli-helpers.js';\nimport { apiFetch, exitOnFailure, fetchOrExit } from './api-fetch.js';\nimport { applyWorkflowTagFlags } from './tag.js';\nimport { specExtension } from './brand.js';\nimport { handleWorkflowCreate } from './workflow-create.js';\nimport { handleWorkflowRun } from './workflow-run.js';\nimport { runWorkflowRuns } from './workflow-runs.js';\nimport { handleWorkflowSync } from './workflow-sync.js';\nimport { handleWorkflowGenerateApiSequence } from './workflow-api-sequence.js';\nimport { handleWorkflowApiSequence } from './workflow-api-sequence-cmds.js';\nimport { handleWorkflowSeedCreate } from './workflow-seed-create.js';\nimport { WORKFLOW_GUIDE_SECTIONS } from '@chatsdet/content/workflow-guide';\nimport { NODE_TYPE_LABEL } from '@chatsdet/types';\nimport { printGuide } from '@chatsdet/content';\nimport { USER_SETTABLE_WORKFLOW_STATUSES } from '@chatsdet/types';\nimport { workflowToSpec, type PullWorkflow } from '@chatsdet/canary-spec';\n\nconst WORKFLOW_STATUS_DESCRIPTIONS: Record<\n (typeof USER_SETTABLE_WORKFLOW_STATUSES)[number],\n string\n> = {\n draft: 'not yet approved — no human has signed off on the spec',\n approved: 'a human verified the test checks the right thing',\n};\n\nconst formatWorkflowStatusList = (): string =>\n USER_SETTABLE_WORKFLOW_STATUSES.map(\n (s) => `${s} (${WORKFLOW_STATUS_DESCRIPTIONS[s]})`\n ).join(', ');\n\n/* ── Types ────────────────────────────────────────────────────────────── */\n\ntype SeedOutput = {\n dataKey: string;\n name: string;\n description?: string;\n displayLabel: string;\n propertyId: string;\n attributes?: Record<string, unknown>;\n credentialOutput?: Record<string, unknown>;\n};\n\ntype WorkflowSummary = PullWorkflow & {\n seedOutputsJson?: SeedOutput[] | null;\n};\n\ntype Pagination = {\n page: number;\n pageSize: number;\n totalItems: number;\n totalPages: number;\n};\n\ntype WorkflowListItem = {\n id: string;\n name: string;\n status: string;\n flowType: string;\n nodeCount?: number;\n};\n\ntype WorkflowListResponse = {\n ok: boolean;\n error?: string;\n data: WorkflowListItem[];\n pagination: Pagination;\n};\n\ntype WorkflowDetailResponse = {\n ok?: boolean;\n error?: string;\n workflow?: WorkflowSummary;\n targetOrgId?: string;\n targetOrgName?: string;\n};\n\n/* ── Node Helpers ─────────────────────────────────────────────────────── */\n\nfunction truncate(text: string, max: number): string {\n if (text.length <= max) return text;\n return text.slice(0, max - 1) + '…';\n}\n\nfunction getNodeTitle(node: PullWorkflow['nodes'][number]): string {\n const c = node.configJson ?? {};\n switch (node.nodeType) {\n case 'login':\n return (c.credentialName as string) || NODE_TYPE_LABEL.login;\n case 'navigate':\n return (c.pageTitle as string) || truncate((c.pageUrl as string) || 'Navigate', 40);\n case 'action':\n return (\n (c.customActionTitle as string) || truncate((c.actionDescription as string) || 'Action', 50)\n );\n case 'assertion':\n return truncate((c.condition as string) || 'Assertion', 50);\n case 'setup':\n return (c.setupFlowName as string) || 'Setup';\n case 'seed':\n return (c.seedWorkflowName as string) || 'Seed';\n case 'wait':\n return 'Wait';\n case 'condition':\n return truncate((c.conditionDescription as string) || 'Condition', 50);\n case 'end':\n return 'End';\n case 'api_sequence':\n return 'API Sequence';\n default:\n return node.nodeType;\n }\n}\n\nfunction getCleanConfig(node: PullWorkflow['nodes'][number]): Record<string, unknown> {\n const c = node.configJson ?? {};\n switch (node.nodeType) {\n case 'login':\n return pick(c, ['credentialName', 'performLogin']);\n case 'navigate':\n return {\n ...pick(c, ['pageUrl', 'pageTitle']),\n ...(c.openInNewTab ? { openInNewTab: true } : {}),\n };\n case 'action':\n return pick(c, [\n 'actionDescription',\n 'customActionInstructions',\n 'playbookSteps',\n 'inputValues',\n 'declaredOutputs',\n 'capturedVariableKeys',\n 'dataRequirements',\n 'alwaysUseAgent',\n ]);\n case 'assertion':\n return pick(c, ['condition', 'expectedOutcome', 'strict', 'alwaysUseAgent']);\n case 'setup':\n return pick(c, ['setupFlowId', 'setupFlowName']);\n case 'seed':\n return pick(c, ['seedWorkflowId', 'seedWorkflowName', 'snapshotVersion']);\n case 'end':\n return pick(c, ['outcome']);\n case 'wait':\n case 'condition':\n case 'api_sequence':\n return c;\n default:\n return c;\n }\n}\n\nfunction pick(obj: Record<string, unknown>, keys: string[]): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of keys) {\n if (obj[key] !== undefined && obj[key] !== null) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/* ── Markdown Formatter ───────────────────────────────────────────────── */\n\nfunction formatWorkflowMarkdown(workflow: WorkflowSummary): string {\n const seedOutputs = workflow.seedOutputsJson ?? workflow.seedOutputs;\n return workflowToSpec({ ...workflow, seedOutputs });\n}\n\n/* ── JSON Formatter ───────────────────────────────────────────────────── */\n\nfunction formatWorkflowJson(workflow: WorkflowSummary): object {\n const sorted = [...workflow.nodes].sort((a, b) => a.orderIndex - b.orderIndex);\n const seedOutputs = workflow.seedOutputsJson;\n\n return {\n workflow: {\n id: workflow.id,\n name: workflow.name,\n description: workflow.description,\n status: workflow.status,\n flowType: workflow.flowType,\n ...(seedOutputs && seedOutputs.length > 0 ? { seedOutputs } : {}),\n },\n steps: sorted.map((node, i) => ({\n index: i + 1,\n nodeId: node.id,\n nodeType: node.nodeType,\n title: getNodeTitle(node),\n config: getCleanConfig(node),\n })),\n };\n}\n\n/* ── Sub-command Handlers ─────────────────────────────────────────────── */\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n\n const params = new URLSearchParams();\n const search = getArgValue(argv, '--search');\n const flowType = getArgValue(argv, '--flow-type');\n const status = getArgValue(argv, '--status');\n const page = getArgValue(argv, '--page');\n const pageSize = getArgValue(argv, '--page-size');\n\n if (search) params.set('search', search);\n if (flowType) params.set('flowType', flowType);\n if (status) params.set('status', status);\n if (page) params.set('page', page);\n if (pageSize) params.set('pageSize', pageSize);\n\n const qs = params.toString();\n const path = `/workflows${qs ? `?${qs}` : ''}`;\n\n const result = await apiRequest<WorkflowListResponse>(apiUrl, token, 'GET', path);\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify({ data: result.data, pagination: result.pagination }, null, 2));\n return;\n }\n\n // Default table output\n const { data, pagination } = result;\n console.log(\n `Workflows: ${pagination.totalItems} total (page ${pagination.page}/${pagination.totalPages})\\n`\n );\n\n if (data.length === 0) {\n console.log('No workflows found.');\n return;\n }\n\n // Column widths\n const idW = 36;\n const nameW = 30;\n const statusW = 12;\n const typeW = 10;\n\n const header = [\n 'ID'.padEnd(idW),\n 'Name'.padEnd(nameW),\n 'Status'.padEnd(statusW),\n 'Type'.padEnd(typeW),\n ].join(' ');\n\n console.log(header);\n\n for (const w of data) {\n const row = [\n w.id.padEnd(idW),\n truncate(w.name, nameW).padEnd(nameW),\n w.status.padEnd(statusW),\n w.flowType.padEnd(typeW),\n ].join(' ');\n console.log(row);\n }\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv[0];\n if (!workflowId || workflowId.startsWith('--')) {\n console.error('Error: Missing workflow ID.');\n console.error('Usage: canary workflow get <workflowId>');\n process.exit(1);\n }\n\n const _jsonOutput = hasFlag(argv, '--json') || getArgValue(argv, '--format') === 'json';\n const markdownOutput =\n hasFlag(argv, '--markdown') ||\n getArgValue(argv, '--format') === 'markdown' ||\n getArgValue(argv, '--format') === 'spec';\n const outputFile = getArgValue(argv, '--output');\n\n const apiRes = await apiFetch(`${apiUrl}/workflows/${workflowId}`, {\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n token,\n });\n if (!apiRes.ok) exitOnFailure(apiRes.failure);\n const result = (await apiRes.response.json()) as WorkflowDetailResponse;\n\n if (result.error === 'WORKFLOW_NOT_FOUND') {\n console.error('Error: Workflow not found.');\n process.exit(1);\n }\n if (result.error === 'WORKFLOW_WRONG_ORG') {\n console.error(\n `Error: Workflow belongs to another org: ${result.targetOrgName ?? result.targetOrgId}`\n );\n process.exit(1);\n }\n if (!result.workflow) {\n console.error(`Error: ${result.error ?? 'Unexpected response'}`);\n process.exit(1);\n }\n\n const workflow = result.workflow;\n let output: string;\n\n if (markdownOutput) {\n output = formatWorkflowMarkdown(workflow);\n } else {\n // Default to JSON for agent-friendly output\n output = JSON.stringify(formatWorkflowJson(workflow), null, 2);\n }\n\n if (outputFile) {\n try {\n await fs.writeFile(outputFile, output, 'utf-8');\n console.log(`Written to ${outputFile}`);\n } catch (err) {\n console.error(\n `Error writing to ${outputFile}: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n return;\n }\n\n console.log(output);\n\n if (!markdownOutput) {\n const appUrl = resolveAppUrl(apiUrl);\n console.log(`\\nURL: ${appUrl}/flows/${workflowId}`);\n }\n}\n\n/* ── Patch Handler ───────────────────────────────────────────────────── */\n\ntype WorkflowUpdateResponse = {\n ok: boolean;\n error?: string;\n workflow?: { id: string; name: string; status: string; flowType: string };\n};\n\nasync function handlePatch(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n console.error('Usage: canary workflow patch <workflowId> [--name ...] [--description ...] [--status ...] [--flow-type ...]');\n process.exit(1);\n }\n\n const name = getArgValue(argv, '--name');\n const description = getArgValue(argv, '--description');\n const status = getArgValue(argv, '--status');\n const flowType = getArgValue(argv, '--flow-type');\n const seedOutputsJsonRaw = getArgValue(argv, '--seed-outputs-json');\n const seedOutputsFile = getArgValue(argv, '--seed-outputs-file');\n const jsonOutput = hasFlag(argv, '--json');\n\n const hasTagFlag =\n getArgValue(argv, '--tags') !== undefined ||\n getArgValue(argv, '--tags-add') !== undefined ||\n getArgValue(argv, '--tags-remove') !== undefined ||\n getArgValue(argv, '--tag-id') !== undefined;\n\n if (\n !name &&\n !description &&\n !status &&\n !flowType &&\n !seedOutputsJsonRaw &&\n !seedOutputsFile &&\n !hasTagFlag\n ) {\n console.error(\n 'Error: No fields to update. Provide at least one of: --name, --description, --status, --flow-type, --seed-outputs-json, --seed-outputs-file, --tags, --tags-add, --tags-remove, --tag-id'\n );\n process.exit(1);\n }\n\n if (\n status &&\n !(USER_SETTABLE_WORKFLOW_STATUSES as readonly string[]).includes(status)\n ) {\n console.error(`Error: Invalid status \"${status}\". Valid: ${formatWorkflowStatusList()}`);\n process.exit(1);\n }\n\n const validFlowTypes = ['standard', 'setup', 'seed', 'teardown'];\n if (flowType && !validFlowTypes.includes(flowType)) {\n console.error(`Error: Invalid flow type \"${flowType}\". Must be one of: ${validFlowTypes.join(', ')}`);\n process.exit(1);\n }\n\n const body: Record<string, unknown> = {};\n if (name) body.name = name;\n if (description) body.description = description;\n if (status) body.status = status;\n if (flowType) body.flowType = flowType;\n\n if (seedOutputsJsonRaw || seedOutputsFile) {\n let raw: string;\n if (seedOutputsFile) {\n try {\n raw = await fs.readFile(seedOutputsFile, 'utf-8');\n } catch (err) {\n console.error(\n `Error reading ${seedOutputsFile}: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n } else {\n raw = seedOutputsJsonRaw!;\n }\n try {\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) {\n throw new Error('seedOutputsJson must be a JSON array');\n }\n body.seedOutputsJson = parsed;\n } catch (err) {\n console.error(\n `Error: Invalid --seed-outputs-json: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n }\n\n let tagResult: Awaited<ReturnType<typeof applyWorkflowTagFlags>> = null;\n\n if (Object.keys(body).length > 0) {\n const result = await apiRequest<WorkflowUpdateResponse>(\n apiUrl,\n token,\n 'PUT',\n `/workflows/${workflowId}`,\n body\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: result.error ?? 'Unknown error' }, null, 2));\n } else {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n }\n process.exit(1);\n }\n }\n\n if (hasTagFlag) {\n try {\n tagResult = await applyWorkflowTagFlags({ apiUrl, token, argv, workflowId });\n } catch (err) {\n if (jsonOutput) {\n console.log(\n JSON.stringify(\n { ok: false, error: err instanceof Error ? err.message : String(err) },\n null,\n 2\n )\n );\n } else {\n console.error(`Error applying tags:\\n${err instanceof Error ? err.message : String(err)}`);\n }\n process.exit(1);\n }\n }\n\n if (jsonOutput) {\n console.log(\n JSON.stringify(\n { ok: true, workflowId, updated: body, tags: tagResult?.tagIds ?? null },\n null,\n 2\n )\n );\n return;\n }\n\n const updatedKeys = Object.keys(body);\n if (updatedKeys.length > 0) {\n console.log(`Workflow ${workflowId} updated (${updatedKeys.join(', ')}).`);\n }\n if (tagResult) {\n console.log(`Tags: ${tagResult.tagIds.length} assigned.`);\n }\n}\n\n/* ── Archive / Unarchive Handlers ────────────────────────────────────── */\n\nasync function handleArchive(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n console.error('Usage: canary workflow archive <workflowId> [--yes] [--json]');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const skipConfirm = hasFlag(argv, '--yes', '-y');\n\n if (!skipConfirm) {\n if (!process.stdin.isTTY) {\n console.error(\n 'Error: Archiving requires confirmation. Pass --yes (or -y) for non-interactive use.'\n );\n process.exit(1);\n }\n process.stdout.write(\n `Archive workflow ${workflowId}? It will be hidden from lists and skipped by test suites. [y/N] `\n );\n const answer = await new Promise<string>((resolve) => {\n process.stdin.setEncoding('utf-8');\n process.stdin.once('data', (chunk) => resolve(String(chunk).trim().toLowerCase()));\n });\n if (answer !== 'y' && answer !== 'yes') {\n console.error('Aborted.');\n process.exit(1);\n }\n }\n\n type ArchiveResult = { ok: boolean; success?: boolean; archived?: boolean; error?: string };\n const result = await apiRequest<ArchiveResult>(\n apiUrl,\n token,\n 'DELETE',\n `/workflows/${workflowId}`\n );\n\n if (result.error) {\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n renderWorkflowUserError(result);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(`Archived workflow ${workflowId}. Use 'canary workflow unarchive ${workflowId}' to restore.`);\n }\n}\n\nasync function handleUnarchive(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n console.error('Usage: canary workflow unarchive <workflowId> [--json]');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n\n type UnarchiveResult = { ok: boolean; error?: string };\n const result = await apiRequest<UnarchiveResult>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/unarchive`,\n {}\n );\n\n if (result.error) {\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n renderWorkflowUserError(result);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(`Restored workflow ${workflowId}.`);\n }\n}\n\n/* ── Approve / Promote / Pause Handlers ──────────────────────────────── */\n\nconst APPROVAL_GUIDANCE = [\n 'Approving a test asserts that a HUMAN has verified it tests the right thing.',\n '',\n 'If you are an agent running this command on behalf of a user:',\n ' - Describe to the user what this test does and what approval means.',\n ' - Confirm the user has personally verified the test is correct.',\n ' - Only re-run with --yes after the user explicitly confirms.',\n '',\n 'Approval does NOT put the test into suites — use `canary workflow promote` for that.',\n].join('\\n');\n\nasync function handleApprove(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n console.error('Usage: canary workflow approve <workflowId> [--yes] [--json]');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n\n if (!hasFlag(argv, '--yes')) {\n console.error(APPROVAL_GUIDANCE);\n console.error(`\\nRe-run with --yes to approve: canary workflow approve ${workflowId} --yes`);\n process.exit(1);\n }\n\n type ApproveResult = {\n ok: boolean;\n error?: string;\n code?: string;\n workflow?: { id: string; name: string; status: string; approvedAt: string | null };\n };\n const result = await apiRequest<ApproveResult>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/approve`,\n {}\n );\n\n if (result.error) {\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.error(`Error: ${result.error}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(\n JSON.stringify({ ok: true, workflowId, workflow: result.workflow ?? null }, null, 2)\n );\n return;\n }\n console.log(`Workflow ${workflowId} approved.`);\n console.log(`Promote it into suites with: canary workflow promote ${workflowId}`);\n}\n\nasync function handlePromote(\n argv: string[],\n apiUrl: string,\n token: string,\n options?: { deprecatedAlias?: string }\n): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n console.error('Usage: canary workflow promote <workflowId> [--force] [--json]');\n process.exit(1);\n }\n\n const force = hasFlag(argv, '--force');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (options?.deprecatedAlias && !jsonOutput) {\n console.error(\n `Note: \\`canary workflow ${options.deprecatedAlias}\\` is deprecated — use \\`canary workflow promote\\`.`\n );\n }\n\n type PromoteResult = {\n ok: boolean;\n error?: string;\n code?: string;\n workflow?: { id: string; name: string; promotion: string | null };\n };\n const result = await apiRequest<PromoteResult>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/promote`,\n force ? { force: true } : {}\n );\n\n if (result.error) {\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n const hint =\n result.code === 'FLOW_NOT_READY_TO_PUBLISH'\n ? '\\n Trigger a successful run first (canary workflow run <id>), or pass --force.'\n : result.code === 'PROMOTION_REQUIRES_APPROVAL'\n ? `\\n Approve the test first: canary workflow approve ${workflowId} --yes\\n (Approval asserts a human verified the test checks the right thing — it cannot be forced.)`\n : '';\n console.error(`Error: ${result.error}${hint}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(\n JSON.stringify({ ok: true, workflowId, workflow: result.workflow ?? null }, null, 2)\n );\n return;\n }\n console.log(`Workflow ${workflowId} promoted — it will run when test suites run.`);\n}\n\nasync function handlePause(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n console.error('Usage: canary workflow pause <workflowId> [--json]');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n\n type PauseResult = {\n ok: boolean;\n error?: string;\n code?: string;\n workflow?: { id: string; name: string; promotion: string | null };\n };\n const result = await apiRequest<PauseResult>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/pause`,\n {}\n );\n\n if (result.error) {\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.error(`Error: ${result.error}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(\n JSON.stringify({ ok: true, workflowId, workflow: result.workflow ?? null }, null, 2)\n );\n return;\n }\n const promotion = result.workflow?.promotion ?? null;\n if (promotion === 'paused') {\n console.log(`Workflow ${workflowId} paused — excluded from suite runs until re-promoted.`);\n } else {\n console.log(`Workflow ${workflowId} was not promoted; nothing to pause.`);\n }\n}\n\n/* ── Node Patch Handler ──────────────────────────────────────────────── */\n\nfunction getAllArgValues(argv: string[], flag: string): string[] {\n const values: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n if (argv[i] === flag && i + 1 < argv.length) {\n values.push(argv[i + 1]!);\n i++;\n }\n }\n return values;\n}\n\nasync function handleNodePatch(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const workflowId = positional[0];\n const nodeId = positional[1];\n\n if (!workflowId || !nodeId) {\n console.error('Error: Missing workflow ID and/or node ID.');\n console.error(\n 'Usage: canary workflow node patch <workflowId> <nodeId> --set-input key=value [--config \\'{\"...\"}\\'] [--json]'\n );\n process.exit(1);\n }\n\n const configArg = getArgValue(argv, '--config');\n const setInputArgs = getAllArgValues(argv, '--set-input');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (!configArg && setInputArgs.length === 0) {\n console.error('Error: No changes specified. Provide --set-input key=value and/or --config \\'{\"...\"}\\'');\n process.exit(1);\n }\n\n // Build configJson from flags\n let configJson: Record<string, unknown> = {};\n\n if (configArg) {\n try {\n configJson = JSON.parse(configArg) as Record<string, unknown>;\n } catch (e) {\n console.error(`Error: Invalid JSON in --config: ${e instanceof Error ? e.message : String(e)}`);\n process.exit(1);\n }\n }\n\n if (setInputArgs.length > 0) {\n const inputValues: Record<string, string> = (configJson.inputValues as Record<string, string>) ?? {};\n for (const arg of setInputArgs) {\n const eqIdx = arg.indexOf('=');\n if (eqIdx === -1) {\n console.error(`Error: --set-input must be key=value, got: \"${arg}\"`);\n process.exit(1);\n }\n inputValues[arg.slice(0, eqIdx)] = arg.slice(eqIdx + 1);\n }\n configJson.inputValues = inputValues;\n }\n\n // Fetch current state for before/after diff\n const getRes = await fetchOrExit(`${apiUrl}/workflows/${workflowId}`, {\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n token,\n });\n const getResult = (await getRes.json()) as WorkflowDetailResponse;\n if (!getResult.workflow) {\n console.error(`Error: Workflow not found.`);\n process.exit(1);\n }\n\n const existingNode = getResult.workflow.nodes.find((n) => n.id === nodeId);\n if (!existingNode) {\n console.error(`Error: Node ${nodeId} not found in workflow ${workflowId}.`);\n console.error('\\nAvailable nodes:');\n for (const n of getResult.workflow.nodes.sort((a, b) => a.orderIndex - b.orderIndex)) {\n console.error(` ${n.id} [${n.nodeType}] ${getNodeTitle(n)}`);\n }\n process.exit(1);\n }\n\n // Apply the patch\n const patchRes = await fetchOrExit(`${apiUrl}/workflows/${workflowId}/nodes/${nodeId}`, {\n method: 'PUT',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n token,\n body: JSON.stringify({ configJson }),\n });\n\n if (!patchRes.ok) {\n const errBody = await patchRes.text();\n if (jsonOutput) {\n console.log(errBody || JSON.stringify({ ok: false, status: patchRes.status }, null, 2));\n } else {\n let rendered: string | null = null;\n try {\n const parsed = JSON.parse(errBody) as Record<string, unknown>;\n rendered = renderWorkflowUserError(parsed);\n } catch {\n rendered = null;\n }\n console.error(rendered ?? `Error (${patchRes.status}): ${errBody.slice(0, 500)}`);\n }\n process.exit(1);\n }\n\n const patchResult = (await patchRes.json()) as { node: PullWorkflow['nodes'][number] };\n\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: true, node: patchResult.node }, null, 2));\n return;\n }\n\n // Show before/after diff\n const title = getNodeTitle(existingNode);\n console.log(`Updated node [${existingNode.nodeType}] \"${title}\" (${nodeId}):\\n`);\n\n const oldConfig = existingNode.configJson ?? {};\n for (const [key, newVal] of Object.entries(configJson)) {\n if (typeof newVal === 'object' && newVal !== null && typeof oldConfig[key] === 'object' && oldConfig[key] !== null) {\n // Diff nested objects (e.g. inputValues)\n const oldObj = oldConfig[key] as Record<string, unknown>;\n const newObj = newVal as Record<string, unknown>;\n for (const [subKey, subVal] of Object.entries(newObj)) {\n const oldVal = oldObj[subKey];\n if (oldVal !== subVal) {\n console.log(` ${key}.${subKey}: ${JSON.stringify(oldVal ?? null)} -> ${JSON.stringify(subVal)}`);\n }\n }\n } else {\n const oldVal = oldConfig[key];\n if (oldVal !== newVal) {\n console.log(` ${key}: ${JSON.stringify(oldVal ?? null)} -> ${JSON.stringify(newVal)}`);\n }\n }\n }\n}\n\n/* ── Help & Entry Point ───────────────────────────────────────────────── */\n\nfunction printWorkflowHelp(): void {\n console.log(\n [\n 'Usage: canary workflow <sub-command> [options]',\n '',\n ' Tip: Run \"canary workflow guide\" for the full authoring reference',\n ' (node types, playbooks, macros, seeds, assertions, best practices)',\n '',\n 'Sub-commands:',\n ' guide [section] [--json] Authoring guide (node-types, macros, etc.)',\n ' list [options] List workflows',\n ' get <workflowId> [options] Get workflow definition with steps',\n ' create [options] Create workflow from JSON',\n ' sync <workflowId> [options] Replace all nodes (same format as create)',\n ' patch <workflowId> [options] Update workflow properties',\n ' approve <workflowId> [--yes] [--json] Mark the test as human-verified (spec is right)',\n ' promote <workflowId> [--force] [--json] Include the test in suite runs (requires approval)',\n ' pause <workflowId> [--json] Exclude a promoted test from suite runs',\n ' publish <workflowId> [--force] [--json] (deprecated alias for promote)',\n ' archive <workflowId> [--yes] [--json] Soft-delete: hide from lists, skip in test suites (reversible)',\n ' unarchive <workflowId> [--json] Restore a previously archived workflow',\n ' run <workflowId> [options] Trigger a workflow execution',\n ' api-sequence <verb> <workflowId> Manage the API sequence attached to a workflow',\n ' generate-api-sequence <workflowId> [opts] (deprecated alias for `api-sequence generate`)',\n ' seed <sub-command> Create seed workflows',\n ' node <sub-command> Manage individual nodes',\n ' runs <sub-command> Query workflow run results',\n ' debug <runId|sub-command> Debug a run (overview/steps/cache/thoughts/logs/trace)',\n '',\n 'List options:',\n ' --search <query> Search by name',\n ' --flow-type <type> Filter: standard, setup, seed, teardown',\n ' --status <status> Filter: draft, approved',\n ' --page <n> Page number (default: 1)',\n ' --page-size <n> Page size (default: 25)',\n ' --json Output raw JSON',\n '',\n 'Get options:',\n ' --format json|markdown|spec Output format (default: json)',\n ' --json Shorthand for --format json',\n ` --markdown Shorthand for editable ${specExtension} spec output`,\n ' --output <file> Write output to file',\n '',\n 'Create options:',\n ' --from-stdin Read workflow JSON from stdin (default)',\n ' --from-file <path> Read workflow JSON from file',\n ' --api-only Create an API-only workflow with a backing ApiSequence',\n ' Requires: --name <name>',\n ' Optional: --credential <id>, --guidance <text>,',\n ' --sequence-from-file <path> or --sequence-from-stdin',\n ' Input shape: { steps, description?, stopOnFailure?, exports? }',\n ' Returns: { workflowId, apiSequenceId, nodeId }',\n ' --tags <names> Comma-separated tag names to assign (names, not IDs)',\n ' --tag-id <ids> Comma-separated raw tag IDs (escape hatch)',\n '',\n ' Input: { name, nodes: [{ nodeType, configJson }] }',\n ' Run \"canary workflow guide node-types\" for available node types.',\n ' Run \"canary workflow guide macros\" for dynamic test data ($EMAIL, $RANDOM_STRING, etc.)',\n '',\n 'Sync options:',\n ' --from-file <path> Read nodes JSON from file',\n ' --from-stdin Read nodes JSON from stdin',\n ' --no-snapshot Skip creating a draft snapshot before sync',\n ' --propose Create a proposal instead of applying directly',\n ' --title <title> Proposal title (with --propose)',\n ' --description <desc> Proposal description (with --propose)',\n ' --json Output raw JSON',\n '',\n ' Sync accepts the same minimal node format as create.',\n ' Edges, IDs, positions, and ordering are auto-generated when omitted.',\n ' Input: { nodes: [{ nodeType, configJson }] }',\n '',\n ' When using --propose on an existing workflow, run `canary workflow get',\n ' <id>` first and reuse each node\\'s existing `id` for steps you intend',\n ' to keep. Only omit `id` for genuinely new steps. Without ID reuse the',\n ' proposal will diff as a full remove-everything/add-everything rewrite.',\n '',\n 'Patch options:',\n ' --name <name> Update workflow name',\n ' --description <desc> Update description',\n ' --status <status> Set status (approval axis). Valid:',\n ' draft — not yet approved',\n ' approved — a human verified the test checks the right thing',\n ' (suite inclusion is the separate promote/pause axis;',\n ' reliability is tracked automatically by health)',\n ' --flow-type <type> Set type: standard, setup, seed, teardown',\n ' --seed-outputs-json <json> Replace seedOutputsJson (array) — seed flows only',\n ' --seed-outputs-file <path> Replace seedOutputsJson from a JSON file',\n ' --tags <names> Replace tags with these names (comma-separated)',\n ' --tags-add <names> Add these tag names to the existing set',\n ' --tags-remove <names> Remove these tag names from the existing set',\n ' --tag-id <ids> Raw tag IDs (comma-separated)',\n ' --json Output raw JSON',\n '',\n 'Approve options:',\n ' --yes Confirm approval (required non-interactively)',\n ' --json Output raw JSON',\n '',\n ' Approval asserts a human verified the test checks the right thing.',\n ' Agents: describe the test to the user and confirm they personally',\n ' verified it before re-running with --yes.',\n '',\n 'Promote options:',\n ' --force Promote without requiring a successful run (skips the',\n ' run gate; the approval gate can never be forced)',\n ' --json Output raw JSON',\n '',\n ' Promote includes the test in suite runs. Suites always execute the',\n ' live definition — edits take effect immediately. Requires the test',\n ' to be approved, and (without --force) a passing run.',\n '',\n 'Run options:',\n ' --stream Follow execution until completion',\n ' --json Output raw JSON',\n '',\n 'API Sequence sub-commands:',\n ' api-sequence get <wf> Show config + steps',\n ' api-sequence update <wf> --from-file <f> Replace config',\n ' api-sequence execute <wf> Run the sequence',\n ' api-sequence delete <wf> Delete the sequence',\n ' api-sequence set-api-only <wf> [--off] Toggle workflow apiOnly flag',\n ' api-sequence generate <wf> [--prompt ...] AI-generate a config (streams)',\n '',\n ' Run \"canary workflow guide api-sequences\" for step shape and template syntax.',\n '',\n 'Seed sub-commands:',\n ' seed create [options] Create a seed workflow with outputs',\n '',\n 'Seed create options:',\n ' --name <name> Seed workflow name (required unless JSON input)',\n ' --description <desc> Description',\n ' --output <key:name[:desc]> Declare an output (repeatable)',\n ' --outputs-json <json> Full outputs array as inline JSON',\n ' --from-stdin Read full config from stdin',\n ' --from-file <path> Read full config from file',\n ' --no-teardown Skip creating paired teardown workflow',\n ' --status <status> Initial status (default: draft)',\n ' --json Output raw JSON',\n '',\n 'Node sub-commands:',\n ' node patch <workflowId> <nodeId> [options] Update a node\\'s config',\n '',\n 'Node patch options:',\n ' --set-input key=value Set an inputValue (repeatable)',\n ' --config \\'{\"...\"}\\' Merge arbitrary configJson (partial update)',\n ' --json Output raw JSON',\n '',\n 'Runs sub-commands:',\n ' runs list <workflowId> List runs for a workflow',\n ' runs get <workflowId> <runId> Get run detail with steps',\n ' runs diagnostics <workflowId> <runId> Get failure diagnostic',\n '',\n 'Cache sub-commands:',\n ' cache status <workflowId> Show per-node cache version, health, recent failures',\n ' cache clear <workflowId> [--node <id>] [--below-version <n>] [--stale-only] [--mode all]',\n ' Targeted cache invalidation (rows kept, isValid=false)',\n ' cache clear <workflowId> --mode hard --yes DESTRUCTIVE: delete cache rows, strip playbookSteps,',\n ' null lastRunId. Same as the UI \"Reset flow\" button',\n ' cache optimize <workflowId> [--run <runId>] Enqueue the async cache-optimizer job',\n '',\n 'Common options:',\n ' --env <env> Target environment (prod, dev, local)',\n ' --api-url <url> API URL override',\n ' --token <key> API token override',\n ].join('\\n')\n );\n}\n\nexport async function runWorkflow(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help') {\n printWorkflowHelp();\n return;\n }\n\n if (subCommand === 'debug' && hasFlag(rest, '--help', '-h')) {\n const { handleWorkflowDebug } = await import('./workflow-debug.js');\n await handleWorkflowDebug(rest, '', '');\n return;\n }\n\n if (hasFlag(argv, '--help', '-h')) {\n printWorkflowHelp();\n return;\n }\n\n if (subCommand === 'guide') {\n const sectionSlug = rest.find((a) => !a.startsWith('-'));\n const jsonOutput = hasFlag(rest, '--json');\n printGuide(WORKFLOW_GUIDE_SECTIONS, sectionSlug, jsonOutput);\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case 'list':\n await handleList(rest, apiUrl, token);\n break;\n case 'get':\n await handleGet(rest, apiUrl, token);\n break;\n case 'create':\n await handleWorkflowCreate(rest, apiUrl, token);\n break;\n case 'patch':\n await handlePatch(rest, apiUrl, token);\n break;\n case 'approve':\n await handleApprove(rest, apiUrl, token);\n break;\n case 'promote':\n await handlePromote(rest, apiUrl, token);\n break;\n case 'pause':\n await handlePause(rest, apiUrl, token);\n break;\n case 'publish':\n // Deprecated alias for promote.\n await handlePromote(rest, apiUrl, token, { deprecatedAlias: 'publish' });\n break;\n case 'archive':\n await handleArchive(rest, apiUrl, token);\n break;\n case 'unarchive':\n await handleUnarchive(rest, apiUrl, token);\n break;\n case 'run':\n await handleWorkflowRun(rest, apiUrl, token);\n break;\n case 'runs':\n await runWorkflowRuns(rest, apiUrl, token);\n break;\n case 'node': {\n const [nodeSub, ...nodeRest] = rest;\n if (nodeSub === 'patch') {\n await handleNodePatch(nodeRest, apiUrl, token);\n } else {\n console.error(`Unknown node sub-command: ${nodeSub ?? '(none)'}`);\n printWorkflowHelp();\n process.exit(1);\n }\n break;\n }\n case 'seed': {\n const [seedSub, ...seedRest] = rest;\n if (seedSub === 'create') {\n await handleWorkflowSeedCreate(seedRest, apiUrl, token);\n } else {\n console.error(`Unknown seed sub-command: ${seedSub ?? '(none)'}`);\n printWorkflowHelp();\n process.exit(1);\n }\n break;\n }\n case 'sync':\n await handleWorkflowSync(rest, apiUrl, token);\n break;\n case 'proposals': {\n const { handleWorkflowProposals } = await import('./workflow-proposals.js');\n await handleWorkflowProposals(rest, apiUrl, token);\n break;\n }\n case 'generate-api-sequence':\n // Deprecated alias — forwards to `api-sequence generate`.\n await handleWorkflowGenerateApiSequence(rest, apiUrl, token);\n break;\n case 'api-sequence':\n await handleWorkflowApiSequence(rest, apiUrl, token);\n break;\n case 'cache': {\n const { handleWorkflowCache } = await import('./workflow-cache.js');\n await handleWorkflowCache(rest, apiUrl, token);\n break;\n }\n case 'debug': {\n const { handleWorkflowDebug } = await import('./workflow-debug.js');\n await handleWorkflowDebug(rest, apiUrl, token);\n break;\n }\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printWorkflowHelp();\n process.exit(1);\n }\n}\n","/**\n * CLI Workflow Creation\n *\n * Creates a workflow with nodes and edges atomically via the API.\n * Supports reading workflow JSON from stdin or file.\n *\n * @module workflow-create\n */\n\nimport fs from \"node:fs/promises\";\nimport process from \"node:process\";\nimport { getArgValue, hasFlag, resolveAppUrl } from \"./auth.js\";\nimport type { CredentialListItem } from \"./cli-helpers.js\";\nimport { fetchOrExit } from \"./api-fetch.js\";\nimport { applyWorkflowTagFlags } from \"./tag.js\";\nimport { normalizeNodeType } from \"@chatsdet/types\";\n\n/* ── Types ────────────────────────────────────────────────────────────── */\n\ntype WorkflowNodeInput = {\n nodeType: string;\n configJson?: Record<string, unknown>;\n};\n\ntype WorkflowCreateInput = {\n name: string;\n description?: string;\n status?: \"draft\" | \"published\";\n flowType?: \"standard\" | \"setup\" | \"seed\" | \"teardown\";\n createdVia?: string;\n propertyId?: string;\n credentialId?: string;\n nodes: WorkflowNodeInput[];\n};\n\ntype CreateResponse = {\n ok: boolean;\n error?: string;\n warnings?: string[];\n workflow?: {\n id: string;\n name: string;\n status: string;\n flowType: string;\n createdVia: string | null;\n };\n nodes?: Array<{ id: string; nodeType: string; orderIndex: number }>;\n edges?: Array<{ id: string; sourceNodeId: string; targetNodeId: string }>;\n};\n\n/* ── Input Reading ───────────────────────────────────────────────────── */\n\nasync function readFromStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n const stdin = process.stdin;\n\n if (stdin.isTTY) {\n throw new Error(\"No input on stdin. Pipe workflow JSON or use --from-file.\");\n }\n\n return new Promise((resolve, reject) => {\n stdin.on(\"data\", (chunk) => {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n });\n stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n stdin.on(\"error\", reject);\n });\n}\n\nasync function readWorkflowInput(argv: string[]): Promise<WorkflowCreateInput> {\n let raw: string;\n\n const fromFile = getArgValue(argv, \"--from-file\");\n if (fromFile) {\n try {\n raw = await fs.readFile(fromFile, \"utf-8\");\n } catch (err) {\n throw new Error(`Failed to read file ${fromFile}: ${err instanceof Error ? err.message : String(err)}`);\n }\n } else {\n raw = await readFromStdin();\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error(\"Invalid JSON input. Please provide valid workflow JSON.\");\n }\n\n const input = parsed as WorkflowCreateInput;\n\n if (!input.name || typeof input.name !== \"string\") {\n throw new Error('Workflow JSON must include a \"name\" string field.');\n }\n\n if (!Array.isArray(input.nodes) || input.nodes.length === 0) {\n throw new Error('Workflow JSON must include a non-empty \"nodes\" array.');\n }\n\n const validNodeTypes = [\"login\", \"navigate\", \"action\", \"assertion\", \"end\", \"setup\", \"seed\", \"wait\", \"condition\", \"api_sequence\", \"notification\"];\n for (const node of input.nodes) {\n // Accept \"acting-as\" as an alias for \"login\" — keep persisted type canonical.\n if (typeof node.nodeType === \"string\") {\n node.nodeType = normalizeNodeType(node.nodeType);\n }\n if (!node.nodeType || !validNodeTypes.includes(node.nodeType)) {\n throw new Error(\n `Invalid nodeType \"${node.nodeType}\". Valid types: ${validNodeTypes.join(\", \")}`\n );\n }\n }\n\n return input;\n}\n\n/* ── Credential Resolution ──────────────────────────────────────────── */\n\nasync function fetchOrgCredentials(\n apiUrl: string,\n token: string\n): Promise<CredentialListItem[]> {\n const res = await fetch(`${apiUrl}/org/credentials`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n if (!res.ok) return [];\n const data = (await res.json()) as { ok: boolean; items: CredentialListItem[] };\n return (data.items ?? []).filter((c) => !c.isEphemeral);\n}\n\n/**\n * Resolve a credential for login nodes that are missing credentialId.\n * Resolution order:\n * 1. Match by credentialName (if provided)\n * 2. Pick the default credential (isDefault: true)\n * 3. Pick the only non-local credential (if exactly one)\n * 4. Error with available credentials listed so the caller can retry\n */\nasync function resolveCredential(\n apiUrl: string,\n token: string,\n credentialName?: string\n): Promise<{ credentialId: string; credentialName: string; propertyId?: string }> {\n const credentials = await fetchOrgCredentials(apiUrl, token);\n\n if (credentials.length === 0) {\n throw new Error(\n \"No credentials found for this organization. Create one in the web app first.\"\n );\n }\n\n // 1. Match by name if provided\n if (credentialName) {\n const match = credentials.find(\n (c) => c.name.toLowerCase() === credentialName.toLowerCase()\n );\n if (match) {\n const isLocal = /\\blocal\\b/i.test(match.name);\n if (isLocal) {\n console.warn(\n `Warning: Credential \"${match.name}\" appears to be local-only. ` +\n `The workflow may fail in deployed environments. Consider using a non-local credential.`\n );\n }\n return { credentialId: match.id, credentialName: match.name, propertyId: match.propertyId };\n }\n // Name didn't match — fall through to other strategies\n console.warn(`Warning: No credential matching name \"${credentialName}\". Trying other resolution strategies.`);\n }\n\n // 2. Pick the default credential\n const defaults = credentials.filter((c) => c.isDefault);\n if (defaults.length === 1) {\n console.log(`Auto-selected default credential: ${defaults[0].name} (${defaults[0].id})`);\n return { credentialId: defaults[0].id, credentialName: defaults[0].name, propertyId: defaults[0].propertyId };\n }\n\n // 3. Pick the only non-local credential\n const nonLocal = credentials.filter((c) => !/\\blocal\\b/i.test(c.name));\n if (nonLocal.length === 1) {\n console.log(`Auto-selected credential: ${nonLocal[0].name} (${nonLocal[0].id})`);\n return { credentialId: nonLocal[0].id, credentialName: nonLocal[0].name, propertyId: nonLocal[0].propertyId };\n }\n\n // 4. Ambiguous — list credentials and error\n const lines = credentials.map(\n (c) => ` ${c.id} ${c.name}${c.isDefault ? \" (default)\" : \"\"}${c.propertyName ? ` — ${c.propertyName}` : \"\"}`\n );\n throw new Error(\n `Cannot auto-resolve credential. Specify credentialId in the login node configJson.\\n\\n` +\n `Available credentials:\\n${lines.join(\"\\n\")}`\n );\n}\n\n/* ── API-only workflow branch ────────────────────────────────────────── */\n\ntype ApiSequenceConfig = {\n steps: unknown[];\n description?: string;\n stopOnFailure?: boolean;\n exports?: unknown[];\n};\n\nasync function readApiSequenceConfig(argv: string[]): Promise<ApiSequenceConfig> {\n const fromFile = getArgValue(argv, \"--sequence-from-file\");\n const fromStdin = hasFlag(argv, \"--sequence-from-stdin\");\n\n if (!fromFile && !fromStdin) {\n return { steps: [] };\n }\n\n let raw: string;\n if (fromFile) {\n raw = await fs.readFile(fromFile, \"utf-8\");\n } else {\n raw = await readFromStdin();\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error(\"Invalid JSON for sequence config.\");\n }\n\n const cfg = parsed as ApiSequenceConfig;\n if (!cfg || !Array.isArray(cfg.steps)) {\n throw new Error('Sequence config must be { \"steps\": [...] }.');\n }\n return cfg;\n}\n\nasync function handleApiOnlyCreate(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const name = getArgValue(argv, \"--name\");\n if (!name) {\n console.error('Error: --api-only requires --name <workflow name>.');\n process.exit(1);\n }\n\n const credentialId = getArgValue(argv, \"--credential\");\n const guidance = getArgValue(argv, \"--guidance\");\n\n let config: ApiSequenceConfig;\n try {\n config = await readApiSequenceConfig(argv);\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n const body: Record<string, unknown> = { name, config };\n if (credentialId) body.credentialId = credentialId;\n if (guidance) body.guidancePrompt = guidance;\n\n const res = await fetchOrExit(`${apiUrl}/api-sequences/create-with-workflow`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n token,\n body: JSON.stringify(body),\n });\n\n const raw = (await res.json().catch(() => ({}))) as {\n ok: boolean;\n error?: string;\n code?: string;\n issues?: Array<{ path: string; code: string; message: string; hint?: string }>;\n data?: { workflowId: string; apiSequenceId: string; nodeId?: string };\n };\n\n if (!res.ok || !raw.ok || !raw.data) {\n const jsonOutput = hasFlag(argv, \"--json\") || !process.stdout.isTTY;\n if (raw.code === 'API_SEQUENCE_INVALID' && Array.isArray(raw.issues)) {\n if (jsonOutput) {\n console.log(\n JSON.stringify(\n {\n ok: false,\n error: raw.error ?? 'API sequence configuration is invalid',\n code: 'API_SEQUENCE_INVALID',\n issueCount: raw.issues.length,\n issues: raw.issues,\n },\n null,\n 2,\n ),\n );\n } else {\n console.error(`Error: ${raw.error ?? 'API sequence configuration is invalid'}`);\n console.error(`Found ${raw.issues.length} issue${raw.issues.length === 1 ? '' : 's'}:`);\n console.error('');\n for (const issue of raw.issues) {\n console.error(` ${issue.path || '(root)'} [${issue.code}] :: ${issue.message}`);\n if (issue.hint) console.error(` hint: ${issue.hint}`);\n }\n }\n process.exit(1);\n }\n console.error(`Error: ${raw.error ?? `${res.status} ${res.statusText}`}`);\n process.exit(1);\n }\n\n if (hasFlag(argv, \"--json\") || !process.stdout.isTTY) {\n console.log(JSON.stringify({ ok: true, data: raw.data }, null, 2));\n return;\n }\n\n const appUrl = resolveAppUrl(apiUrl);\n console.log(`\\n\\u2713 API-only workflow created: ${name}`);\n console.log(` Workflow ID: ${raw.data.workflowId}`);\n console.log(` API Sequence ID: ${raw.data.apiSequenceId}`);\n if (raw.data.nodeId) console.log(` Node ID: ${raw.data.nodeId}`);\n console.log(` Steps: ${config.steps.length}`);\n console.log(` URL: ${appUrl}/flows/${raw.data.workflowId}`);\n console.log(`\\n Next:`);\n console.log(` canary workflow api-sequence get ${raw.data.workflowId}`);\n console.log(` canary workflow api-sequence update ${raw.data.workflowId} --from-file seq.json`);\n console.log(` canary workflow api-sequence execute ${raw.data.workflowId}`);\n}\n\n/* ── Main Handler ────────────────────────────────────────────────────── */\n\nexport async function handleWorkflowCreate(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n if (hasFlag(argv, \"--api-only\")) {\n await handleApiOnlyCreate(argv, apiUrl, token);\n return;\n }\n\n // Auto-publish was removed with the approval/promotion lifecycle split:\n // a human must approve, then promote, as explicit steps.\n if (hasFlag(argv, \"--run-and-publish\")) {\n console.error(\n \"Error: --run-and-publish was removed. Run the test (canary workflow run <id>), then\\n\" +\n \"approve it (canary workflow approve <id> --yes) and promote it (canary workflow promote <id>).\"\n );\n process.exit(1);\n }\n\n // 1. Read and validate input\n let input: WorkflowCreateInput;\n try {\n input = await readWorkflowInput(argv);\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n // 2. Resolve credentials for login nodes missing credentialId\n const loginNodes = input.nodes.filter((n) => n.nodeType === \"login\");\n for (const loginNode of loginNodes) {\n const config = loginNode.configJson ?? {};\n if (!config.credentialId && !input.credentialId) {\n try {\n const resolved = await resolveCredential(\n apiUrl,\n token,\n config.credentialName as string | undefined\n );\n config.credentialId = resolved.credentialId;\n config.credentialName = resolved.credentialName;\n loginNode.configJson = config;\n if (resolved.propertyId && !input.propertyId) {\n input.propertyId = resolved.propertyId;\n }\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n }\n }\n\n // All flows start as drafts — approval and promotion are explicit follow-up\n // steps (canary workflow approve / promote). Reliability is tracked\n // separately by the workflow's `health` (starts at `unverified`).\n input.createdVia = \"cli\";\n\n // 4. Create workflow via API\n const res = await fetchOrExit(`${apiUrl}/workflows/create-with-nodes`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n token,\n body: JSON.stringify(input),\n });\n\n const result = (await res.json()) as CreateResponse;\n\n if (!result.ok || !result.workflow) {\n console.error(`Error: ${result.error ?? \"Failed to create workflow\"}`);\n process.exit(1);\n }\n\n const { workflow, nodes, edges } = result;\n\n const { warnings } = result;\n\n console.log(`\\n\\u2713 Workflow created: ${workflow.name}`);\n console.log(` ID: ${workflow.id}`);\n console.log(` Status: ${workflow.status}`);\n console.log(` Nodes: ${nodes?.length ?? 0}`);\n console.log(` Edges: ${edges?.length ?? 0}`);\n\n if (warnings && warnings.length > 0) {\n console.log(`\\n Warnings:`);\n for (const w of warnings) {\n console.log(` \\u26A0 ${w}`);\n }\n }\n\n const appUrl = resolveAppUrl(apiUrl);\n console.log(` URL: ${appUrl}/flows/${workflow.id}`);\n\n // 5. Apply --tags / --tag-id if provided.\n try {\n const tagResult = await applyWorkflowTagFlags({\n apiUrl,\n token,\n argv,\n workflowId: workflow.id,\n });\n if (tagResult) {\n console.log(` Tags: ${tagResult.tagIds.length} assigned`);\n }\n } catch (err) {\n console.error(`\\nError applying tags:\\n${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n console.log(\n `\\n Next: run it (canary workflow run ${workflow.id}), approve it ` +\n `(canary workflow approve ${workflow.id} --yes), then promote it into suites ` +\n `(canary workflow promote ${workflow.id}).`\n );\n}\n","/**\n * CLI handler for triggering a workflow execution.\n *\n * Usage:\n * canary workflow run <workflowId> [options]\n *\n * @module WorkflowRunCLI\n */\n\nimport process from 'node:process';\nimport { hasFlag } from './auth.js';\nimport { apiRequest, renderWorkflowUserError } from './cli-helpers.js';\nimport { statusIcon } from './cli-format.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype ExecuteResponse = {\n ok: boolean;\n error?: string;\n runId: string;\n streamId: string;\n};\n\ntype RunStatusResponse = {\n ok: boolean;\n error?: string;\n data: {\n run: {\n id: string;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n errorMessage: string | null;\n };\n };\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ---------------------------------------------------------------------------\n// Handler\n// ---------------------------------------------------------------------------\n\nexport async function handleWorkflowRun(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n console.error(\n 'Usage: canary workflow run <workflowId> [--stream] [--json] [--validation | --no-validation]'\n );\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const stream = hasFlag(argv, '--stream');\n // Validation mode opt-in/opt-out. Server auto-engages validation for tests\n // that have never passed when triggered directly; --validation forces it on,\n // --no-validation forces it off.\n const optInValidation = hasFlag(argv, '--validation');\n const optOutValidation = hasFlag(argv, '--no-validation');\n const validationMode = optInValidation ? true : optOutValidation ? false : undefined;\n\n const requestBody: Record<string, unknown> = {\n triggerSource: 'cli_direct',\n };\n if (validationMode !== undefined) {\n requestBody.validationMode = validationMode;\n }\n\n // Trigger execution\n const result = await apiRequest<ExecuteResponse>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/execute`,\n requestBody\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n const rendered = renderWorkflowUserError(result as unknown as Record<string, unknown>);\n console.error(rendered ?? `Error: ${result.error ?? 'Unknown error'}`);\n }\n process.exit(1);\n }\n\n const { runId } = result;\n\n if (jsonOutput && !stream) {\n console.log(JSON.stringify({ ok: true, runId, streamId: result.streamId }, null, 2));\n return;\n }\n\n if (!stream) {\n console.log(`Run triggered successfully.`);\n console.log(` Run ID: ${runId}`);\n console.log(`\\nCheck status: canary workflow runs get ${workflowId} ${runId}`);\n return;\n }\n\n // Stream mode: poll run status until completion\n console.log(`Run triggered (${runId}). Waiting for completion...\\n`);\n\n const terminalStatuses = new Set([\n 'completed',\n 'success',\n 'passed',\n 'failed',\n 'canceled',\n 'timeout',\n ]);\n let lastStatus = '';\n\n for (;;) {\n await sleep(3000);\n\n const status = await apiRequest<RunStatusResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/runs/${runId}`\n );\n\n if (!status.ok) {\n console.error(`Error polling status: ${status.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n const run = status.data.run;\n\n if (run.status !== lastStatus) {\n console.log(` ${statusIcon(run.status)} ${run.status}`);\n lastStatus = run.status;\n }\n\n if (terminalStatuses.has(run.status)) {\n if (run.errorMessage) {\n console.log(`\\nError: ${run.errorMessage}`);\n }\n console.log(`\\nRun finished: ${run.status}`);\n console.log(`Details: canary workflow runs get ${workflowId} ${runId}`);\n\n if (run.status === 'failed' || run.status === 'timeout' || run.status === 'canceled') {\n process.exit(1);\n }\n return;\n }\n }\n}\n","/**\n * Shared CLI formatting utilities for status display, durations, and timestamps.\n *\n * @module CLIFormat\n */\n\nexport const STATUS_ICONS: Record<string, string> = {\n completed: '\\u2705',\n completed_with_errors: '\\u26A0\\uFE0F',\n success: '\\u2705',\n passed: '\\u2705',\n failed: '\\u274C',\n running: '\\uD83D\\uDD35',\n queued: '\\u23F3',\n canceled: '\\uD83D\\uDEAB',\n timeout: '\\u23F0',\n skipped: '\\u23ED\\uFE0F',\n flaky_success: '\\uD83D\\uDFE1',\n pending: '\\u23F3',\n};\n\nexport function statusIcon(status: string): string {\n return STATUS_ICONS[status] ?? '\\u2753';\n}\n\nexport function formatRelative(iso: string | null): string {\n if (!iso) return '\\u2014';\n const diffMs = Date.now() - new Date(iso).getTime();\n if (diffMs < 0) return 'just now';\n const seconds = Math.floor(diffMs / 1000);\n if (seconds < 60) return 'just now';\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n\nexport function computeDuration(startedAt: string | null, finishedAt: string | null): string {\n if (!startedAt || !finishedAt) return '\\u2014';\n const ms = new Date(finishedAt).getTime() - new Date(startedAt).getTime();\n if (ms < 0) return '\\u2014';\n const totalSeconds = Math.floor(ms / 1000);\n if (totalSeconds < 60) return `${totalSeconds}s`;\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n if (minutes < 60) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n const remainMins = minutes % 60;\n return remainMins > 0 ? `${hours}h ${remainMins}m` : `${hours}h`;\n}\n\nexport function pad(str: string, len: number): string {\n return str.padEnd(len);\n}\n\nexport function readFromStdin(): Promise<string> {\n const stdin = process.stdin;\n\n if (stdin.isTTY) {\n return Promise.reject(\n new Error('No input on stdin. Pipe JSON or use --from-file.')\n );\n }\n\n const chunks: Buffer[] = [];\n return new Promise((resolve, reject) => {\n stdin.on('data', (chunk) => {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);\n });\n stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n stdin.on('error', reject);\n });\n}\n","/**\n * CLI subcommand for querying workflow run results.\n *\n * Usage:\n * canary workflow runs list <workflowId> [options]\n * canary workflow runs get <workflowId> <runId> [options]\n * canary workflow runs diagnostics <workflowId> <runId> [options]\n *\n * @module WorkflowRunsCLI\n */\n\nimport process from 'node:process';\nimport { getArgValue, hasFlag } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\nimport { statusIcon, formatRelative, computeDuration, pad } from './cli-format.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Pagination = {\n page: number;\n pageSize: number;\n totalItems: number;\n totalPages: number;\n};\n\ntype RunSummary = {\n id: string;\n status: string;\n createdAt: string;\n startedAt: string | null;\n finishedAt: string | null;\n errorMessage: string | null;\n browserMode: string | null;\n stepTotals: { total: number; passed: number; failed: number } | null;\n snapshotVersion: number | null;\n};\n\ntype RunListResponse = {\n ok: boolean;\n error?: string;\n data: { runs: RunSummary[] };\n pagination: Pagination;\n};\n\ntype RunStep = {\n id: string;\n runId: string;\n nodeId: string;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n errorMessage: string | null;\n orderIndex: number;\n metadataJson: Record<string, unknown> | null;\n createdAt: string;\n};\n\ntype RunDetail = {\n id: string;\n workflowId: string;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n errorMessage: string | null;\n metadataJson: Record<string, unknown> | null;\n steps: RunStep[];\n draftSnapshot: { id: string; version: string; basePublishedVersion: number } | null;\n};\n\ntype RunDetailResponse = {\n ok: boolean;\n error?: string;\n data: { run: RunDetail };\n};\n\ntype DiagnosticJson = {\n category?: string;\n confidence?: number;\n title?: string;\n analysis?: string;\n recommendation?: string;\n smokingGun?: { type: string; description: string; detail?: string } | null;\n};\n\ntype FailureDiagnosticResponse = {\n ok: boolean;\n error?: string;\n data: {\n id: string;\n status: string;\n diagnostic: DiagnosticJson | null;\n createdAt: string;\n updatedAt: string;\n } | null;\n};\n\ntype RawDiagnosticsResponse = {\n ok: boolean;\n error?: string;\n consoleLogs: Array<{ level: string; text: string; timestamp?: string }>;\n networkRequests: Array<{ method: string; url: string; status: number }>;\n};\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\ntype AnnotatedRun = RunSummary & { side: 'browser' | 'api' };\n\ntype ApiSequenceRunRow = {\n id: string;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n errorMessage: string | null;\n createdAt?: string;\n};\n\ntype ApiSequenceByWorkflow = {\n ok: boolean;\n error?: string;\n data?: { id: string } | null;\n};\n\ntype ApiSequenceRunsResponse = {\n ok: boolean;\n error?: string;\n data: ApiSequenceRunRow[];\n pagination?: Pagination;\n};\n\nasync function fetchBrowserRuns(\n apiUrl: string,\n token: string,\n workflowId: string,\n page: string,\n pageSize: string\n): Promise<{ runs: RunSummary[]; pagination: Pagination } | { error: string }> {\n const params = new URLSearchParams({ page, pageSize });\n const result = await apiRequest<RunListResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/runs?${params}`\n );\n if (!result.ok) return { error: result.error ?? 'Unknown error' };\n return { runs: result.data.runs, pagination: result.pagination };\n}\n\nasync function fetchApiRuns(\n apiUrl: string,\n token: string,\n workflowId: string,\n page: string,\n pageSize: string\n): Promise<\n { runs: RunSummary[]; pagination: Pagination | null } | { error: string; code?: string }\n> {\n const seqRes = await apiRequest<ApiSequenceByWorkflow & { code?: string }>(\n apiUrl,\n token,\n 'GET',\n `/api-sequences/by-workflow/${workflowId}`\n );\n if (!seqRes.ok) {\n return {\n error: seqRes.error ?? 'Unknown error',\n ...(seqRes.code ? { code: seqRes.code } : {}),\n };\n }\n if (!seqRes.data) return { runs: [], pagination: null };\n const params = new URLSearchParams({ page, pageSize });\n const runsRes = await apiRequest<ApiSequenceRunsResponse>(\n apiUrl,\n token,\n 'GET',\n `/api-sequences/${seqRes.data.id}/runs?${params}`\n );\n if (!runsRes.ok) return { error: runsRes.error ?? 'Unknown error' };\n const runs: RunSummary[] = (runsRes.data ?? []).map((r) => ({\n id: r.id,\n status: r.status,\n createdAt: r.createdAt ?? r.startedAt ?? new Date(0).toISOString(),\n startedAt: r.startedAt,\n finishedAt: r.finishedAt,\n errorMessage: r.errorMessage,\n browserMode: null,\n stepTotals: null,\n snapshotVersion: null,\n }));\n return { runs, pagination: runsRes.pagination ?? null };\n}\n\nasync function handleRunsList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID. Usage: canary workflow runs list <workflowId>');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const page = getArgValue(argv, '--page') ?? '1';\n const pageSize = getArgValue(argv, '--page-size') ?? '10';\n const explicitSide = getArgValue(argv, '--side') ?? getArgValue(argv, '--mode');\n const sideArg = (explicitSide ?? 'all').toLowerCase();\n\n if (!['all', 'api', 'browser'].includes(sideArg)) {\n console.error(`Error: --side must be one of: all, api, browser (got \"${sideArg}\")`);\n process.exit(1);\n }\n\n const annotated: AnnotatedRun[] = [];\n let browserPagination: Pagination | null = null;\n let apiPagination: Pagination | null = null;\n\n if (sideArg === 'browser' || sideArg === 'all') {\n const browser = await fetchBrowserRuns(apiUrl, token, workflowId, page, pageSize);\n if ('error' in browser) {\n console.error(`Error: ${browser.error}`);\n process.exit(1);\n }\n browserPagination = browser.pagination;\n for (const r of browser.runs) annotated.push({ ...r, side: 'browser' });\n }\n\n if (sideArg === 'api' || sideArg === 'all') {\n const api = await fetchApiRuns(apiUrl, token, workflowId, page, pageSize);\n if ('error' in api) {\n // When --side wasn't explicit and the workflow simply has no api-sequence,\n // don't hard-fail the whole listing — just skip the api leg.\n const isMissingSequence = api.code === 'API_SEQUENCE_NOT_FOUND';\n if (!explicitSide && isMissingSequence) {\n if (!jsonOutput) {\n console.error('Note: workflow has no api-sequence — showing browser runs only.');\n }\n } else {\n console.error(`Error: ${api.error}`);\n process.exit(1);\n }\n } else {\n apiPagination = api.pagination;\n for (const r of api.runs) annotated.push({ ...r, side: 'api' });\n }\n }\n\n annotated.sort((a, b) => {\n const ta = new Date(a.startedAt ?? a.createdAt).getTime();\n const tb = new Date(b.startedAt ?? b.createdAt).getTime();\n return tb - ta;\n });\n\n if (jsonOutput) {\n console.log(\n JSON.stringify(\n {\n ok: true,\n data: { runs: annotated },\n pagination: { browser: browserPagination, api: apiPagination },\n },\n null,\n 2\n )\n );\n return;\n }\n\n if (annotated.length === 0) {\n console.log('No runs found.');\n return;\n }\n\n console.log(`Runs (${annotated.length} shown, side=${sideArg})\\n`);\n const idW = 36;\n const sideW = 8;\n const statusW = 12;\n const durationW = 10;\n console.log(\n [\n 'ID'.padEnd(idW),\n 'Side'.padEnd(sideW),\n 'Status'.padEnd(statusW),\n 'Duration'.padEnd(durationW),\n 'Started',\n ].join(' ')\n );\n\n for (const run of annotated) {\n const icon = statusIcon(run.status);\n const dur = computeDuration(run.startedAt, run.finishedAt);\n const time = formatRelative(run.startedAt ?? run.createdAt);\n console.log(\n [\n run.id.padEnd(idW),\n pad(run.side, sideW),\n `${icon} ${pad(run.status, statusW - 3)}`,\n pad(dur, durationW),\n time,\n ].join(' ')\n );\n }\n console.log('');\n}\n\nasync function handleRunsGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n if (positional.length < 2) {\n console.error(\n 'Error: Missing arguments. Usage: canary workflow runs get <workflowId> <runId>'\n );\n process.exit(1);\n }\n\n const [workflowId, runId] = positional;\n const jsonOutput = hasFlag(argv, '--json');\n\n const result = await apiRequest<RunDetailResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/runs/${runId}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n const { run } = result.data;\n const duration = computeDuration(run.startedAt, run.finishedAt);\n\n console.log(`Run: ${run.id}`);\n console.log(`Status: ${statusIcon(run.status)} ${run.status}`);\n console.log(`Duration: ${duration}`);\n\n if (run.errorMessage) {\n console.log(`Error: ${run.errorMessage}`);\n }\n\n if (run.draftSnapshot) {\n console.log(`Snapshot: v${run.draftSnapshot.version} (base: v${run.draftSnapshot.basePublishedVersion})`);\n }\n\n const steps = (run.steps ?? []).sort((a, b) => a.orderIndex - b.orderIndex);\n\n if (steps.length === 0) {\n console.log('\\nNo steps recorded.');\n return;\n }\n\n console.log(`\\nSteps (${steps.length}):`);\n for (const step of steps) {\n const idx = String(step.orderIndex + 1).padStart(2);\n const icon = statusIcon(step.status);\n const nodeId = step.nodeId.slice(0, 8);\n const dur = computeDuration(step.startedAt, step.finishedAt);\n\n console.log(` ${idx}. ${icon} ${pad(nodeId, 10)} ${dur}`);\n\n if (step.errorMessage) {\n console.log(` Error: ${step.errorMessage}`);\n }\n }\n\n console.log('');\n}\n\nasync function handleRunsDiagnostics(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n if (positional.length < 2) {\n console.error(\n 'Error: Missing arguments. Usage: canary workflow runs diagnostics <workflowId> <runId>'\n );\n process.exit(1);\n }\n\n const [workflowId, runId] = positional;\n const jsonOutput = hasFlag(argv, '--json');\n\n // Try AI failure diagnostic first\n const result = await apiRequest<FailureDiagnosticResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/runs/${runId}/failure-diagnostic`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (jsonOutput && result.data) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (result.data) {\n const { status, diagnostic } = result.data;\n\n if (status === 'pending' || status === 'running') {\n console.log(`Diagnostic is still in progress (status: ${status}).`);\n return;\n }\n\n if (status === 'failed') {\n console.log('Diagnostic analysis failed.');\n return;\n }\n\n if (diagnostic) {\n console.log('Failure Diagnostic');\n console.log(`Status: ${status}`);\n if (diagnostic.category) {\n const conf =\n diagnostic.confidence !== null && diagnostic.confidence !== undefined\n ? ` (${diagnostic.confidence > 1 ? Math.round(diagnostic.confidence) : Math.round(diagnostic.confidence * 100)}% confidence)`\n : '';\n console.log(`Category: ${diagnostic.category}${conf}`);\n }\n if (diagnostic.title) {\n console.log(`Title: ${diagnostic.title}`);\n }\n\n if (diagnostic.analysis) {\n console.log('');\n console.log('Analysis:');\n console.log(` ${diagnostic.analysis}`);\n }\n\n if (diagnostic.recommendation) {\n console.log('');\n console.log('Recommendation:');\n console.log(` ${diagnostic.recommendation}`);\n }\n\n if (diagnostic.smokingGun) {\n console.log('');\n console.log('Smoking Gun:');\n console.log(` > ${diagnostic.smokingGun.description}`);\n if (diagnostic.smokingGun.detail) {\n console.log(` ${diagnostic.smokingGun.detail}`);\n }\n }\n\n console.log('');\n return;\n }\n }\n\n // Fall back to raw console/network diagnostics\n const rawResult = await apiRequest<RawDiagnosticsResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/runs/${runId}/diagnostics`\n );\n\n if (!rawResult.ok) {\n console.log('No diagnostic available for this run.');\n return;\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(rawResult, null, 2));\n return;\n }\n\n const hasConsole = rawResult.consoleLogs && rawResult.consoleLogs.length > 0;\n const hasNetwork = rawResult.networkRequests && rawResult.networkRequests.length > 0;\n\n if (!hasConsole && !hasNetwork) {\n console.log('No diagnostic data available for this run.');\n return;\n }\n\n if (hasConsole) {\n console.log(`Console Logs (${rawResult.consoleLogs.length}):`);\n for (const log of rawResult.consoleLogs.slice(0, 50)) {\n const level = log.level.toUpperCase().padEnd(7);\n console.log(` [${level}] ${log.text}`);\n }\n if (rawResult.consoleLogs.length > 50) {\n console.log(` ... and ${rawResult.consoleLogs.length - 50} more`);\n }\n console.log('');\n }\n\n if (hasNetwork) {\n console.log(`Network Requests (${rawResult.networkRequests.length}):`);\n for (const req of rawResult.networkRequests.slice(0, 30)) {\n const statusStr = req.status >= 400 ? `${req.status} !!!` : String(req.status);\n console.log(` ${req.method.padEnd(6)} ${statusStr.padEnd(8)} ${req.url}`);\n }\n if (rawResult.networkRequests.length > 30) {\n console.log(` ... and ${rawResult.networkRequests.length - 30} more`);\n }\n console.log('');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Help\n// ---------------------------------------------------------------------------\n\nfunction printRunsHelp(): void {\n console.log(\n [\n 'Usage: canary workflow runs <sub-command> [options]',\n '',\n 'Sub-commands:',\n ' list <workflowId> [options] List runs for a workflow',\n ' get <workflowId> <runId> [options] Get run detail with steps',\n ' diagnostics <workflowId> <runId> [options] Get failure diagnostic',\n '',\n 'List options:',\n ' --page <n> Page number (default: 1)',\n ' --page-size <n> Page size (default: 10)',\n ' --side <side> Filter: browser, api, all (default: all). Alias: --mode',\n '',\n 'Output options:',\n ' --json Output raw JSON',\n '',\n 'Common options:',\n ' --env <env> Target environment (prod, dev, local)',\n ' --api-url <url> API URL override',\n ' --token <key> API token override',\n ].join('\\n')\n );\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nexport async function runWorkflowRuns(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printRunsHelp();\n return;\n }\n\n switch (subCommand) {\n case 'list':\n await handleRunsList(rest, apiUrl, token);\n break;\n case 'get':\n await handleRunsGet(rest, apiUrl, token);\n break;\n case 'diagnostics':\n await handleRunsDiagnostics(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printRunsHelp();\n process.exit(1);\n }\n}\n","/**\n * CLI handler for syncing a workflow's DAG (nodes + edges) atomically.\n *\n * Reads the new state from a JSON file or stdin, creates a draft snapshot\n * of the current state for safety, then replaces all nodes and edges.\n *\n * Input is flexible — the CLI auto-fills missing fields:\n * - Node `id` and `orderIndex` are auto-generated\n * - `edges` array is optional — linear sequential edges are created\n * - Accepts the same minimal format as `canary workflow create`\n *\n * Usage:\n * canary workflow sync <workflowId> --from-file <path>\n * cat state.json | canary workflow sync <workflowId> --from-stdin\n *\n * Minimal input: { \"nodes\": [{ \"nodeType\": \"login\", \"configJson\": {} }, ...] }\n *\n * @module WorkflowSyncCLI\n */\n\nimport crypto from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { alignSnapshotNodeIds, type AlignNode } from '@chatsdet/workflow-diff';\nimport { normalizeNodeType } from '@chatsdet/types';\nimport { getArgValue, hasFlag } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\nimport { readFromStdin } from './cli-format.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype SyncResponse = {\n ok: boolean;\n error?: string;\n snapshotVersion?: string;\n};\n\ntype ProposalResponse = {\n ok: boolean;\n error?: string;\n data?: {\n id: string;\n title: string;\n status: string;\n };\n};\n\n// ---------------------------------------------------------------------------\n// Auto-fill helpers\n// ---------------------------------------------------------------------------\n\ntype RawNode = Record<string, unknown>;\ntype RawEdge = Record<string, unknown>;\n\nfunction normalizeNodesAndEdges(\n rawNodes: RawNode[],\n rawEdges?: RawEdge[]\n): { nodes: RawNode[]; edges: RawEdge[] } {\n // Fill missing node fields with defaults\n const nodes = rawNodes.map((node, i) => ({\n ...node,\n id: (node.id as string) ?? crypto.randomUUID(),\n orderIndex: (node.orderIndex as number) ?? i,\n configJson: (node.configJson as Record<string, unknown>) ?? {},\n }));\n\n // If edges provided, just fill missing IDs\n if (rawEdges && rawEdges.length > 0) {\n const edges = rawEdges.map((edge) => ({\n ...edge,\n id: (edge.id as string) ?? crypto.randomUUID(),\n }));\n return { nodes, edges };\n }\n\n // Auto-generate linear sequential edges\n const edges: RawEdge[] = [];\n for (let i = 0; i < nodes.length - 1; i++) {\n edges.push({\n id: crypto.randomUUID(),\n sourceNodeId: nodes[i].id,\n targetNodeId: nodes[i + 1].id,\n edgeType: 'default',\n });\n }\n\n return { nodes, edges };\n}\n\n// ---------------------------------------------------------------------------\n// Input reading\n// ---------------------------------------------------------------------------\n\nasync function readSyncInput(argv: string[]): Promise<{ nodes: RawNode[]; edges?: RawEdge[] }> {\n const filePath = getArgValue(argv, '--from-file');\n const fromStdin = hasFlag(argv, '--from-stdin');\n\n let raw: string;\n if (filePath) {\n try {\n raw = await fs.readFile(filePath, 'utf-8');\n } catch (err) {\n console.error(`Error reading file: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n } else if (fromStdin) {\n try {\n raw = await readFromStdin();\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n } else {\n console.error('Error: Must provide --from-file <path> or --from-stdin');\n process.exit(1);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n console.error('Error: Invalid JSON input');\n process.exit(1);\n }\n\n const obj = parsed as Record<string, unknown>;\n\n // Normalize \"acting-as\" → \"login\" on user-supplied node entries so callers\n // can use the new spelling without breaking the canonical persisted type.\n const normalizeNodes = (raw: unknown[]): RawNode[] => {\n return raw.map((entry) => {\n if (entry && typeof entry === 'object' && 'nodeType' in entry) {\n const node = entry as RawNode;\n if (typeof node.nodeType === 'string') {\n node.nodeType = normalizeNodeType(node.nodeType);\n }\n }\n return entry as RawNode;\n });\n };\n\n // Direct format: { nodes: [...], edges?: [...] }\n if (Array.isArray(obj.nodes)) {\n return {\n nodes: normalizeNodes(obj.nodes),\n edges: Array.isArray(obj.edges) ? obj.edges : undefined,\n };\n }\n\n // Wrapped format from `canary workflow get`: { workflow: { nodes: [...], edges: [...] } }\n const workflow = obj.workflow as Record<string, unknown> | undefined;\n if (workflow && Array.isArray(workflow.nodes)) {\n return {\n nodes: normalizeNodes(workflow.nodes),\n edges: Array.isArray(workflow.edges) ? workflow.edges : undefined,\n };\n }\n\n console.error('Error: JSON must contain a \"nodes\" array.');\n console.error('Accepted formats:');\n console.error(' { \"nodes\": [{ \"nodeType\": \"login\", \"configJson\": {} }, ...] }');\n console.error(' { \"nodes\": [...], \"edges\": [...] }');\n console.error(' { \"workflow\": { \"nodes\": [...], \"edges\": [...] } }');\n console.error('');\n console.error('Edges, IDs, positions, and ordering are auto-generated when omitted.');\n process.exit(1);\n}\n\n// ---------------------------------------------------------------------------\n// Current-workflow ID alignment (for --propose)\n// ---------------------------------------------------------------------------\n\ntype WorkflowGetResponse = {\n ok: boolean;\n error?: string;\n workflow?: {\n id: string;\n nodes?: Array<{\n id: string;\n nodeType: string;\n orderIndex?: number;\n configJson?: Record<string, unknown> | null;\n }>;\n };\n};\n\nasync function alignWithCurrentWorkflow(\n apiUrl: string,\n token: string,\n workflowId: string,\n nodes: RawNode[],\n edges: RawEdge[],\n): Promise<{ nodes: RawNode[]; edges: RawEdge[] }> {\n // Best-effort: a failed fetch (network blip, 404, permissions) shouldn't\n // block the proposal — the server-side aligner will still run.\n let currentNodes: AlignNode[] = [];\n try {\n const current = await apiRequest<WorkflowGetResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}`,\n );\n if (current.ok && current.workflow?.nodes) {\n currentNodes = current.workflow.nodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n orderIndex: n.orderIndex,\n configJson: n.configJson ?? {},\n }));\n }\n } catch {\n // Swallow — alignment is a best-effort optimization on the client.\n }\n\n if (currentNodes.length === 0) {\n return { nodes, edges };\n }\n\n const proposedSnapshot = {\n nodes: nodes.map((n) => ({\n id: String(n.id),\n nodeType: String(n.nodeType ?? ''),\n orderIndex: typeof n.orderIndex === 'number' ? n.orderIndex : undefined,\n configJson: (n.configJson as Record<string, unknown> | null | undefined) ?? {},\n })),\n edges: edges.map((e) => ({\n id: String(e.id),\n sourceNodeId: String(e.sourceNodeId),\n targetNodeId: String(e.targetNodeId),\n edgeType: (e.edgeType as string | null | undefined) ?? null,\n })),\n };\n\n const { snapshot } = alignSnapshotNodeIds(proposedSnapshot, currentNodes);\n\n // Splice aligned IDs back onto the original raw nodes/edges so any extra\n // fields callers passed through (canonicalPageId, etc.) are preserved.\n const alignedNodes: RawNode[] = nodes.map((n, i) => ({\n ...n,\n id: snapshot.nodes[i]!.id,\n }));\n const alignedEdges: RawEdge[] = edges.map((e, i) => ({\n ...e,\n sourceNodeId: snapshot.edges[i]!.sourceNodeId,\n targetNodeId: snapshot.edges[i]!.targetNodeId,\n }));\n\n return { nodes: alignedNodes, edges: alignedEdges };\n}\n\n// ---------------------------------------------------------------------------\n// Handler\n// ---------------------------------------------------------------------------\n\nexport async function handleWorkflowSync(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n console.error('Usage: canary workflow sync <workflowId> --from-file <path>');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const noSnapshot = hasFlag(argv, '--no-snapshot');\n const propose = hasFlag(argv, '--propose');\n const proposalTitle = getArgValue(argv, '--title');\n const proposalDescription = getArgValue(argv, '--description');\n\n const raw = await readSyncInput(argv);\n const { nodes, edges } = normalizeNodesAndEdges(raw.nodes, raw.edges);\n\n // --propose: create a proposal instead of applying directly\n if (propose) {\n const title = proposalTitle ?? `CLI sync proposal (${nodes.length} nodes)`;\n\n // Reuse existing workflow node IDs whenever a proposed step lines up with\n // a current step (same nodeType + orderIndex). Without this the diff\n // engine — which matches by node.id — sees the proposal as a wholesale\n // rewrite even when only a few configs changed. The server-side aligner\n // is the authoritative pass; doing it here too keeps CLI output sensible\n // and gives agents a clean diff even before they round-trip through the\n // API.\n const aligned = await alignWithCurrentWorkflow(apiUrl, token, workflowId, nodes, edges);\n\n const result = await apiRequest<ProposalResponse>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/proposals`,\n {\n title,\n description: proposalDescription ?? null,\n snapshotJson: { nodes: aligned.nodes, edges: aligned.edges },\n source: 'api',\n }\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: result.error ?? 'Unknown error' }, null, 2));\n } else {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`Proposal created for workflow ${workflowId} (${nodes.length} nodes, ${edges.length} edges).`);\n if (result.data?.id) {\n console.log(`Proposal ID: ${result.data.id}`);\n }\n return;\n }\n\n const result = await apiRequest<SyncResponse>(\n apiUrl,\n token,\n 'PUT',\n `/workflows/${workflowId}/draft-state`,\n { nodes, edges, createSnapshot: !noSnapshot }\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: result.error ?? 'Unknown error' }, null, 2));\n } else {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`Workflow ${workflowId} synced (${nodes.length} nodes, ${edges.length} edges).`);\n if (result.snapshotVersion) {\n console.log(`Draft snapshot created: ${result.snapshotVersion}`);\n }\n}\n","/**\n * CLI handler for generating an API sequence from a workflow.\n *\n * Generates from the latest successful run (default) or from a text prompt.\n * Streams progress events via SSE and outputs the resulting ApiSequenceConfig.\n *\n * Usage:\n * canary workflow generate-api-sequence <workflowId> [--guidance \"text\"] [--json]\n * canary workflow generate-api-sequence --prompt \"Create user\" [--property <id>] [--json]\n *\n * @module WorkflowApiSequenceCLI\n */\n\nimport process from 'node:process';\nimport { createParser, type EventSourceMessage } from 'eventsource-parser';\nimport { getArgValue, hasFlag } from './auth.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype GenerateResponse = {\n ok: boolean;\n error?: string;\n generationId?: string;\n};\n\ntype ApiSequenceEvent = {\n emittedAt: string;\n workflowId: string;\n} & (\n | { eventType: 'progress'; message: string }\n | { eventType: 'tool-call'; toolName: string; args: unknown }\n | { eventType: 'tool-result'; toolName: string; result: unknown; success: boolean }\n | { eventType: 'text'; delta: string }\n | {\n eventType: 'complete';\n config: unknown;\n summary: string;\n propertyId: string | null;\n credentialId: string | null;\n }\n | { eventType: 'error'; message: string }\n);\n\n// ---------------------------------------------------------------------------\n// Handler\n// ---------------------------------------------------------------------------\n\nexport async function handleWorkflowGenerateApiSequence(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n const prompt = getArgValue(argv, '--prompt');\n const guidance = getArgValue(argv, '--guidance');\n const propertyId = getArgValue(argv, '--property');\n const jsonOutput = hasFlag(argv, '--json');\n const verbose = hasFlag(argv, '--verbose', '-v');\n\n if (!workflowId && !prompt) {\n console.error('Error: Provide a workflow ID or --prompt.');\n console.error('');\n console.error('Usage:');\n console.error(' canary workflow generate-api-sequence <workflowId> [--guidance \"text\"]');\n console.error(' canary workflow generate-api-sequence --prompt \"Create user\" [--property <id>]');\n process.exit(1);\n }\n\n // 1. Trigger generation\n let endpoint: string;\n let body: Record<string, unknown>;\n\n if (workflowId && !prompt) {\n // Generate from latest successful run\n endpoint = '/api-sequence-agent/generate-from-run';\n body = { workflowId };\n if (guidance) body.guidancePrompt = guidance;\n if (!jsonOutput) {\n console.error(`Generating API sequence from latest run of workflow ${workflowId}...`);\n }\n } else {\n // Generate from prompt\n endpoint = '/api-sequence-agent/generate';\n body = { prompt: prompt! };\n if (propertyId) body.propertyId = propertyId;\n if (workflowId) body.workflowId = workflowId;\n if (!jsonOutput) {\n console.error(`Generating API sequence from prompt...`);\n }\n }\n\n let triggerRes: Response;\n try {\n triggerRes = await fetch(`${apiUrl}${endpoint}`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n });\n } catch (err) {\n console.error(`Failed to connect to API: ${err}`);\n process.exit(1);\n }\n\n if (triggerRes.status === 403) {\n const data = (await triggerRes.json().catch(() => ({}))) as { error?: string };\n console.error(`Error: ${data.error ?? 'This feature is not enabled for your organization.'}`);\n process.exit(1);\n }\n\n if (!triggerRes.ok) {\n const data = (await triggerRes.json().catch(() => ({}))) as { error?: string };\n console.error(`Error: ${data.error ?? `${triggerRes.status} ${triggerRes.statusText}`}`);\n process.exit(1);\n }\n\n const triggerData = (await triggerRes.json()) as GenerateResponse;\n if (!triggerData.ok || !triggerData.generationId) {\n console.error(`Error: ${triggerData.error ?? 'Failed to start generation'}`);\n process.exit(1);\n }\n\n const { generationId } = triggerData;\n\n // 2. Subscribe to SSE stream\n const streamUrl = `${apiUrl}/api-sequence-agent/stream?generationId=${generationId}`;\n\n let streamRes: Response;\n try {\n streamRes = await fetch(streamUrl, {\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: 'text/event-stream',\n },\n });\n } catch (err) {\n console.error(`Failed to connect to event stream: ${err}`);\n process.exit(1);\n }\n\n if (!streamRes.ok || !streamRes.body) {\n console.error(`Failed to connect to event stream: ${streamRes.status}`);\n process.exit(1);\n }\n\n // 3. Parse SSE events\n let resultConfig: unknown = null;\n let resultSummary = '';\n let hasCompleted = false;\n let exitCode = 0;\n\n const parser = createParser({\n onEvent: (event: EventSourceMessage) => {\n if (!event.data || event.event !== 'api-sequence-generation') return;\n\n try {\n const data = JSON.parse(event.data) as ApiSequenceEvent;\n\n switch (data.eventType) {\n case 'progress':\n if (!jsonOutput) console.error(` ${data.message}`);\n break;\n\n case 'tool-call':\n if (verbose) console.error(` [tool] ${data.toolName}`);\n break;\n\n case 'tool-result':\n if (verbose) {\n const icon = data.success ? '\\u2713' : '\\u2717';\n console.error(` [tool] ${icon} ${data.toolName}`);\n }\n break;\n\n case 'text':\n // Accumulate but don't print deltas in non-verbose mode\n if (verbose) process.stderr.write(data.delta);\n break;\n\n case 'complete':\n resultConfig = data.config;\n resultSummary = data.summary;\n hasCompleted = true;\n break;\n\n case 'error':\n console.error(`\\nError: ${data.message}`);\n exitCode = 1;\n hasCompleted = true;\n break;\n }\n } catch {\n // Ignore parse errors for keepalive etc.\n }\n },\n });\n\n const reader = streamRes.body.getReader();\n const decoder = new TextDecoder();\n\n try {\n while (!hasCompleted) {\n const { done, value } = await reader.read();\n if (done) break;\n parser.feed(decoder.decode(value, { stream: true }));\n }\n } finally {\n reader.releaseLock();\n }\n\n // 4. Output result\n if (exitCode !== 0) {\n process.exit(exitCode);\n }\n\n if (!resultConfig) {\n console.error('Generation completed but no config was returned.');\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: true, config: resultConfig, summary: resultSummary }, null, 2));\n } else {\n if (resultSummary) {\n console.error('');\n console.error(resultSummary);\n }\n console.error('');\n console.log(JSON.stringify(resultConfig, null, 2));\n }\n}\n","/**\n * `canary workflow api-sequence <verb>` — manage the API sequence attached to an\n * api-only workflow.\n *\n * All verbs take a workflowId (not a raw apiSequenceId) to match the agent's\n * mental model: \"the sequence attached to this workflow\". The CLI resolves the\n * apiSequenceId via GET /api-sequences/by-workflow/:workflowId in one extra hop.\n *\n * Output auto-detects JSON (piped) vs text (TTY); --json/--text force either.\n *\n * @module WorkflowApiSequenceCmdsCLI\n */\n\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { getArgValue, hasFlag } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\nimport { handleWorkflowGenerateApiSequence } from './workflow-api-sequence.js';\n\n/* ── Arg helpers ───────────────────────────────────────────────────────── */\n\nfunction getArg(argv: string[], key: string): string | undefined {\n const prefix = `${key}=`;\n const eq = argv.find((a) => a.startsWith(prefix));\n if (eq) return eq.slice(prefix.length);\n return getArgValue(argv, key);\n}\n\nfunction wantsJson(argv: string[]): boolean {\n if (hasFlag(argv, '--json')) return true;\n if (hasFlag(argv, '--text')) return false;\n return !process.stdout.isTTY;\n}\n\nfunction emit(argv: string[], textFallback: string, json: unknown): void {\n if (wantsJson(argv)) {\n console.log(JSON.stringify(json, null, 2));\n } else {\n console.log(textFallback);\n }\n}\n\nasync function readJsonInput(argv: string[]): Promise<unknown> {\n const fromFile = getArg(argv, '--from-file');\n let raw: string;\n if (fromFile) {\n raw = await fs.readFile(fromFile, 'utf-8');\n } else if (hasFlag(argv, '--from-stdin') || !process.stdin.isTTY) {\n raw = await readStdin();\n } else {\n throw new Error('Provide --from-file <path> or pipe JSON on stdin.');\n }\n try {\n return JSON.parse(raw);\n } catch {\n throw new Error('Invalid JSON input.');\n }\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n process.stdin.on('data', (chunk) => {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);\n });\n process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n process.stdin.on('error', reject);\n });\n}\n\n/* ── Types ─────────────────────────────────────────────────────────────── */\n\ninterface ApiSequenceStep {\n id?: string;\n endpointId?: string;\n method?: string;\n path?: string;\n [k: string]: unknown;\n}\n\ninterface ApiSequenceConfig {\n steps: ApiSequenceStep[];\n description?: string;\n stopOnFailure?: boolean;\n exports?: unknown[];\n}\n\ninterface ApiSequenceRecord {\n id: string;\n workflowId: string;\n orgId: string;\n credentialId: string | null;\n config: ApiSequenceConfig;\n status: string;\n guidancePrompt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface ByWorkflowResponse {\n ok: boolean;\n error?: string;\n data?: ApiSequenceRecord | null;\n}\n\ninterface ExecuteResponse {\n ok: boolean;\n error?: string;\n data?: { runId: string; status: string };\n}\n\ninterface ValidationIssue {\n path: string;\n code: string;\n message: string;\n hint?: string;\n}\n\ninterface GenericResponse {\n ok: boolean;\n error?: string;\n code?: string;\n issues?: ValidationIssue[];\n data?: unknown;\n}\n\n/**\n * Handle an error response from an api-sequence mutation. If the server\n * returned API_SEQUENCE_INVALID, emit a dense, machine-parseable report\n * so a coding agent can iterate: JSON mode emits `{ok:false, error, code,\n * issues}` to stdout; text mode writes `path [CODE] :: message` lines to\n * stderr. Always exits 1.\n *\n * Returns without exiting for non-validation errors so the caller can\n * fall back to its own error formatting.\n */\nfunction reportAndMaybeExit(\n argv: string[],\n result: { ok: boolean; error?: string; code?: string; issues?: ValidationIssue[] },\n): void {\n if (result.ok) return;\n\n if (result.code === 'API_SEQUENCE_INVALID' && Array.isArray(result.issues)) {\n if (wantsJson(argv)) {\n // stdout, so agents piping to jq get the full structured payload.\n console.log(\n JSON.stringify(\n {\n ok: false,\n error: result.error ?? 'API sequence configuration is invalid',\n code: 'API_SEQUENCE_INVALID',\n issueCount: result.issues.length,\n issues: result.issues,\n },\n null,\n 2,\n ),\n );\n } else {\n console.error(`Error: ${result.error ?? 'API sequence configuration is invalid'}`);\n console.error(\n `Found ${result.issues.length} issue${result.issues.length === 1 ? '' : 's'}:`,\n );\n console.error('');\n // Dense form: one issue per line, `path [CODE] :: message` — grep/jq-friendly.\n for (const issue of result.issues) {\n console.error(` ${issue.path || '(root)'} [${issue.code}] :: ${issue.message}`);\n if (issue.hint) console.error(` hint: ${issue.hint}`);\n }\n console.error('');\n console.error(\n 'Re-run with --json for machine-readable output, or fix the listed fields and retry.',\n );\n }\n process.exit(1);\n }\n\n // Non-validation error — caller-provided formatting.\n return;\n}\n\n/* ── Dispatcher ────────────────────────────────────────────────────────── */\n\nexport async function handleWorkflowApiSequence(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n const [verb, ...rest] = argv;\n switch (verb) {\n case 'get':\n await handleGet(rest, apiUrl, token);\n break;\n case 'update':\n await handleUpdate(rest, apiUrl, token);\n break;\n case 'execute':\n case 'run':\n await handleExecute(rest, apiUrl, token);\n break;\n case 'delete':\n await handleDelete(rest, apiUrl, token);\n break;\n case 'set-api-only':\n await handleSetApiOnly(rest, apiUrl, token);\n break;\n case 'generate':\n await handleWorkflowGenerateApiSequence(rest, apiUrl, token);\n break;\n default:\n printHelp();\n process.exit(verb ? 1 : 0);\n }\n}\n\nfunction printHelp() {\n console.error(\n [\n 'Usage: canary workflow api-sequence <verb> <workflowId> [options]',\n '',\n 'Verbs:',\n ' get <wf> fetch the sequence attached to the workflow',\n ' update <wf> --from-file <f> replace config (steps, description, exports...)',\n ' update <wf> --from-stdin replace config from piped JSON',\n ' execute <wf> run the sequence; returns { runId, status }',\n ' delete <wf> delete the api-sequence record (keeps workflow)',\n ' set-api-only <wf> [--off] toggle the workflow\\'s apiOnly flag',\n ' generate <wf> [--prompt ...] AI-generate a config (streams progress)',\n '',\n 'Global options:',\n ' --json force JSON output',\n ' --text force pretty-text output (default when stdout is a TTY)',\n '',\n 'Config shape (for update): { steps: [...], description?, stopOnFailure?, exports? }',\n 'Run \"canary workflow guide api-sequences\" for step shape and template syntax.',\n ].join('\\n'),\n );\n}\n\n/* ── Helpers ───────────────────────────────────────────────────────────── */\n\nasync function fetchSequenceByWorkflow(\n apiUrl: string,\n token: string,\n workflowId: string,\n): Promise<ApiSequenceRecord> {\n const res = await apiRequest<ByWorkflowResponse>(\n apiUrl,\n token,\n 'GET',\n `/api-sequences/by-workflow/${workflowId}`,\n );\n if (!res.ok) {\n console.error(`Error: ${res.error ?? 'Failed to fetch sequence'}`);\n process.exit(1);\n }\n if (!res.data) {\n console.error(`Error: Workflow ${workflowId} has no attached API sequence.`);\n console.error('Create one with: canary workflow create --api-only --name <n> --sequence-from-file seq.json');\n process.exit(1);\n }\n return res.data;\n}\n\n/* ── Handlers ──────────────────────────────────────────────────────────── */\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n printHelp();\n process.exit(1);\n }\n const seq = await fetchSequenceByWorkflow(apiUrl, token, workflowId);\n emit(argv, renderSequence(seq), seq);\n}\n\nasync function handleUpdate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n printHelp();\n process.exit(1);\n }\n\n let parsed: unknown;\n try {\n parsed = await readJsonInput(argv);\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n const config = parsed as ApiSequenceConfig;\n if (!config || !Array.isArray(config.steps)) {\n console.error('Error: Input must have a \"steps\" array. Got: ' + JSON.stringify(config));\n process.exit(1);\n }\n\n const seq = await fetchSequenceByWorkflow(apiUrl, token, workflowId);\n\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'PUT',\n `/api-sequences/${seq.id}/config`,\n { config },\n );\n\n reportAndMaybeExit(argv, result);\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Update failed'}`);\n process.exit(1);\n }\n\n emit(\n argv,\n `Updated api-sequence ${seq.id} (workflow ${workflowId}). Steps: ${config.steps.length}.`,\n result,\n );\n}\n\nasync function handleExecute(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n printHelp();\n process.exit(1);\n }\n\n const seq = await fetchSequenceByWorkflow(apiUrl, token, workflowId);\n\n const result = await apiRequest<ExecuteResponse>(\n apiUrl,\n token,\n 'POST',\n `/api-sequences/${seq.id}/execute`,\n );\n\n if (!result.ok || !result.data) {\n console.error(`Error: ${result.error ?? 'Execute failed'}`);\n process.exit(1);\n }\n\n emit(\n argv,\n `Run started: ${result.data.runId} (status: ${result.data.status})\\n` +\n `Inspect: canary workflow runs get ${workflowId} ${result.data.runId}`,\n result,\n );\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n printHelp();\n process.exit(1);\n }\n\n const seq = await fetchSequenceByWorkflow(apiUrl, token, workflowId);\n\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'DELETE',\n `/api-sequences/${seq.id}`,\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Delete failed'}`);\n process.exit(1);\n }\n\n emit(argv, `Deleted api-sequence ${seq.id} (workflow ${workflowId}).`, result);\n}\n\nasync function handleSetApiOnly(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n const workflowId = argv.find((a) => !a.startsWith('-'));\n if (!workflowId) {\n console.error('Error: Missing workflow ID.');\n printHelp();\n process.exit(1);\n }\n\n const apiOnly = !hasFlag(argv, '--off');\n\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'PUT',\n `/workflows/${workflowId}/api-only`,\n { apiOnly },\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Update failed'}`);\n process.exit(1);\n }\n\n emit(argv, `Workflow ${workflowId} apiOnly=${apiOnly}.`, result);\n}\n\n/* ── Rendering ─────────────────────────────────────────────────────────── */\n\nfunction renderSequence(seq: ApiSequenceRecord): string {\n const lines: string[] = [];\n lines.push(`API Sequence ${seq.id}`);\n lines.push(` Workflow: ${seq.workflowId}`);\n lines.push(` Status: ${seq.status}`);\n if (seq.credentialId) lines.push(` Credential: ${seq.credentialId}`);\n if (seq.config.description) lines.push(` Description: ${seq.config.description}`);\n lines.push(` stopOnFailure: ${seq.config.stopOnFailure ?? false}`);\n lines.push('');\n\n const steps = seq.config.steps ?? [];\n if (steps.length === 0) {\n lines.push(' (no steps — use `api-sequence update` to add)');\n } else {\n lines.push(` Steps (${steps.length}):`);\n steps.forEach((step, i) => {\n const method = String(step.method ?? '??').toUpperCase().padEnd(6);\n const path = step.path ?? '(no path)';\n const id = step.id ? ` [${step.id}]` : '';\n lines.push(` ${String(i + 1).padStart(2)}. ${method} ${path}${id}`);\n if (step.endpointId) lines.push(` endpointId: ${step.endpointId}`);\n });\n }\n\n const exports = seq.config.exports ?? [];\n if (exports.length > 0) {\n lines.push('');\n lines.push(` Exports: ${JSON.stringify(exports)}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * CLI Seed Workflow Creation\n *\n * Creates a seed workflow shell with outputs and an optional paired teardown.\n * Supports flag-based and JSON-based input.\n *\n * @module workflow-seed-create\n */\n\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { getArgValue, hasFlag, resolveAppUrl } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\n\n/* ── Types ────────────────────────────────────────────────────────────── */\n\ntype SeedOutput = {\n dataKey: string;\n name: string;\n displayLabel: string;\n description?: string;\n credentialOutput?: Record<string, unknown>;\n};\n\ntype SeedCreateInput = {\n name: string;\n description?: string;\n status?: 'draft' | 'approved';\n outputs?: SeedOutput[];\n};\n\ntype WorkflowResponse = {\n ok: boolean;\n error?: string;\n workflow?: { id: string; name: string; status: string; flowType: string };\n};\n\ntype WorkflowUpdateResponse = {\n ok: boolean;\n error?: string;\n workflow?: { id: string };\n};\n\n/* ── Helpers ──────────────────────────────────────────────────────────── */\n\nfunction getAllArgValues(argv: string[], flag: string): string[] {\n const values: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n if (argv[i] === flag && i + 1 < argv.length) {\n values.push(argv[i + 1]!);\n i++;\n }\n }\n return values;\n}\n\n/**\n * Parse an --output flag value: \"dataKey:Name[:description]\"\n */\nfunction parseOutputFlag(value: string): SeedOutput {\n const parts = value.split(':');\n if (parts.length < 2) {\n throw new Error(\n `Invalid --output format: \"${value}\". Expected \"dataKey:Name\" or \"dataKey:Name:Description\".`\n );\n }\n const [dataKey, name, ...descParts] = parts;\n const description = descParts.length > 0 ? descParts.join(':') : undefined;\n return {\n dataKey: dataKey!.trim(),\n name: name!.trim(),\n displayLabel: name!.trim(),\n description: description?.trim() || undefined,\n };\n}\n\nasync function readFromStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n const stdin = process.stdin;\n\n if (stdin.isTTY) {\n throw new Error('No input on stdin. Pipe JSON or use --from-file.');\n }\n\n return new Promise((resolve, reject) => {\n stdin.on('data', (chunk) => {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);\n });\n stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n stdin.on('error', reject);\n });\n}\n\nasync function readJsonInput(argv: string[]): Promise<SeedCreateInput> {\n let raw: string;\n\n const fromFile = getArgValue(argv, '--from-file');\n if (fromFile) {\n try {\n raw = await fs.readFile(fromFile, 'utf-8');\n } catch (err) {\n throw new Error(`Failed to read file ${fromFile}: ${err instanceof Error ? err.message : String(err)}`);\n }\n } else {\n raw = await readFromStdin();\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error('Invalid JSON input.');\n }\n\n const input = parsed as SeedCreateInput;\n if (!input.name || typeof input.name !== 'string') {\n throw new Error('JSON input must include a \"name\" string field.');\n }\n\n // Normalize outputs: default displayLabel to name if missing\n if (Array.isArray(input.outputs)) {\n for (const out of input.outputs) {\n if (!out.dataKey || !out.name) {\n throw new Error('Each output must have \"dataKey\" and \"name\" fields.');\n }\n if (!out.displayLabel) {\n out.displayLabel = out.name;\n }\n }\n }\n\n return input;\n}\n\nfunction resolveInput(argv: string[]): Promise<SeedCreateInput> | SeedCreateInput {\n const fromFile = getArgValue(argv, '--from-file');\n const fromStdin = hasFlag(argv, '--from-stdin');\n\n // JSON input mode\n if (fromFile || fromStdin) {\n return readJsonInput(argv);\n }\n\n // Flag-based input mode\n const name = getArgValue(argv, '--name');\n if (!name) {\n console.error('Error: --name is required (or use --from-stdin / --from-file for JSON input).');\n console.error('Usage: canary workflow seed create --name <name> [--output key:name[:desc]] ...');\n process.exit(1);\n }\n\n const description = getArgValue(argv, '--description');\n const status = getArgValue(argv, '--status') as 'draft' | 'approved' | undefined;\n\n // Parse --output flags\n const outputFlags = getAllArgValues(argv, '--output');\n const outputs: SeedOutput[] = outputFlags.map(parseOutputFlag);\n\n // Parse --outputs-json for complex outputs (credential configs etc.)\n const outputsJsonRaw = getArgValue(argv, '--outputs-json');\n if (outputsJsonRaw) {\n try {\n const parsed = JSON.parse(outputsJsonRaw) as SeedOutput[];\n if (!Array.isArray(parsed)) throw new Error('not an array');\n for (const out of parsed) {\n if (!out.dataKey || !out.name) {\n throw new Error('Each output must have \"dataKey\" and \"name\" fields.');\n }\n if (!out.displayLabel) out.displayLabel = out.name;\n }\n outputs.push(...parsed);\n } catch (err) {\n console.error(`Error: Invalid --outputs-json: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n }\n\n return { name, description: description || undefined, status, outputs };\n}\n\n/* ── Main Handler ────────────────────────────────────────────────────── */\n\nexport async function handleWorkflowSeedCreate(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n if (hasFlag(argv, '--help', '-h')) {\n printSeedCreateHelp();\n return;\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const noTeardown = hasFlag(argv, '--no-teardown');\n\n let input: SeedCreateInput;\n try {\n input = await resolveInput(argv);\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n // 1. Create seed workflow\n const seedResult = await apiRequest<WorkflowResponse>(\n apiUrl,\n token,\n 'POST',\n '/workflows',\n {\n name: input.name,\n description: input.description,\n status: input.status ?? 'draft',\n flowType: 'seed',\n createdVia: 'cli',\n }\n );\n\n if (!seedResult.ok || !seedResult.workflow) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: seedResult.error ?? 'Failed to create seed workflow' }, null, 2));\n } else {\n console.error(`Error: ${seedResult.error ?? 'Failed to create seed workflow'}`);\n }\n process.exit(1);\n }\n\n const seedId = seedResult.workflow.id;\n const appUrl = resolveAppUrl(apiUrl);\n\n // 2. Set seed outputs if provided\n let outputsSaved = false;\n if (input.outputs && input.outputs.length > 0) {\n const outputsResult = await apiRequest<WorkflowUpdateResponse>(\n apiUrl,\n token,\n 'PUT',\n `/workflows/${seedId}`,\n { seedOutputsJson: input.outputs }\n );\n\n if (outputsResult.ok) {\n outputsSaved = true;\n } else {\n console.warn(`Warning: Seed created but failed to save outputs: ${outputsResult.error ?? 'Unknown error'}`);\n }\n }\n\n // 3. Create paired teardown (unless --no-teardown)\n let teardownId: string | undefined;\n let teardownName: string | undefined;\n if (!noTeardown) {\n const tdName = `Teardown: ${input.name}`;\n const tdResult = await apiRequest<WorkflowResponse>(\n apiUrl,\n token,\n 'POST',\n '/workflows',\n {\n name: tdName,\n description: `Cleans up seed data from \"${input.name}\"`,\n status: 'draft',\n flowType: 'teardown',\n createdVia: 'cli',\n }\n );\n\n if (tdResult.ok && tdResult.workflow) {\n teardownId = tdResult.workflow.id;\n teardownName = tdName;\n\n // 4. Link teardown to seed\n const linkResult = await apiRequest<WorkflowUpdateResponse>(\n apiUrl,\n token,\n 'PUT',\n `/workflows/${seedId}`,\n { teardownWorkflowId: teardownId }\n );\n\n if (!linkResult.ok) {\n console.warn(`Warning: Teardown created but failed to link to seed: ${linkResult.error ?? 'Unknown error'}`);\n }\n } else {\n console.warn(`Warning: Failed to create paired teardown: ${tdResult.error ?? 'Unknown error'}`);\n }\n }\n\n // 5. Output results\n if (jsonOutput) {\n const result: Record<string, unknown> = {\n ok: true,\n seed: {\n id: seedId,\n name: input.name,\n status: input.status ?? 'draft',\n flowType: 'seed',\n outputs: outputsSaved ? input.outputs : [],\n url: `${appUrl}/flows/${seedId}`,\n },\n };\n if (teardownId) {\n result.teardown = {\n id: teardownId,\n name: teardownName,\n status: 'draft',\n flowType: 'teardown',\n url: `${appUrl}/flows/${teardownId}`,\n };\n }\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`\\n\\u2713 Seed workflow created: ${input.name}`);\n console.log(` ID: ${seedId}`);\n console.log(` Status: ${input.status ?? 'draft'}`);\n if (input.outputs && input.outputs.length > 0) {\n const keys = input.outputs.map((o) => o.dataKey).join(', ');\n console.log(` Outputs: ${keys}${!outputsSaved ? ' (save failed)' : ''}`);\n }\n console.log(` URL: ${appUrl}/flows/${seedId}`);\n\n if (teardownId) {\n console.log(`\\n\\u2713 Teardown workflow created: ${teardownName}`);\n console.log(` ID: ${teardownId}`);\n console.log(` URL: ${appUrl}/flows/${teardownId}`);\n }\n}\n\nfunction printSeedCreateHelp(): void {\n console.log(\n [\n 'Usage: canary workflow seed create [options]',\n '',\n 'Create a seed workflow with declared outputs and an optional paired teardown.',\n '',\n 'Flag-based input:',\n ' --name <name> Seed workflow name (required)',\n ' --description <desc> Description',\n ' --output <key:name[:desc]> Declare an output (repeatable)',\n ' --outputs-json <json> Full outputs array as inline JSON (for credential configs)',\n ' --no-teardown Skip creating paired teardown workflow',\n ' --status <status> Initial status (default: draft)',\n ' --json Output raw JSON',\n '',\n 'JSON input:',\n ' --from-stdin Read full config from stdin',\n ' --from-file <path> Read full config from file',\n '',\n 'Examples:',\n ' canary workflow seed create --name \"Create Project\" --output \"project_id:Project ID\"',\n '',\n ' canary workflow seed create --from-stdin <<\\'EOF\\'',\n ' {',\n ' \"name\": \"Create Test User\",',\n ' \"outputs\": [{',\n ' \"dataKey\": \"user_cred\",',\n ' \"name\": \"Test User Credential\",',\n ' \"credentialOutput\": {',\n ' \"fieldMapping\": { \"username\": \"$generate.email\", \"password\": \"Test123!\" },',\n ' \"emailPrefix\": \"testuser\",',\n ' \"createInboxRecipient\": true',\n ' }',\n ' }]',\n ' }',\n ' EOF',\n ].join('\\n')\n );\n}\n","Workflows are visual test sequences that model user journeys through your application. Each workflow is a directed graph of nodes — login, navigate, action, assertion, wait, condition, setup, and more — connected to form a testable path.\n\nWhen to use workflows:\n\n- Critical paths: signup, checkout, billing, onboarding\n- High-risk areas: features that regress often or have complex logic\n- Multi-step journeys: flows spanning multiple pages or user roles\n\nFLOW TYPES\n\n standard The default. Models a single user journey end-to-end.\n Login → Navigate → Actions → Assertions → Cleanup.\n\n setup A prerequisite workflow that runs before other workflows.\n Use for shared data creation or environment preparation.\n Any published workflow can be referenced as a setup step.\n\n seed A data-seeding workflow that generates test data and exports\n variables for downstream workflows. Seed outputs are declared\n in the workflow definition and available as $var.{dataKey}\n in any workflow that references the seed.\n\n teardown A cleanup workflow that runs after a seed workflow completes.\n Automatically invoked to remove data the seed created.\n\nEXECUTION MODEL\n\n 1. Login node provisions an authenticated browser session\n 2. Nodes execute in sequence (or branch at condition nodes)\n 3. Each action node interacts with the live application\n 4. Assertions verify expected outcomes\n 5. Additional login nodes switch to a different user — each starts a\n new segment with a fresh session (great for multi-role testing)\n 6. Wait nodes pause execution (minutes, hours, days) — also creating\n segments. After a wait, a login re-establishes the session.\n 7. On completion, the run is marked success or failure\n\nVERSION HISTORY\n\n Workflows maintain version history. Publishing creates a versioned\n snapshot. Previous versions can be previewed or restored to draft.\n Setup nodes reference a specific published version of another workflow.","Every workflow is built from nodes. Each node has a type, a title, a description,\nand type-specific configuration.\n\nSTARTING NODE — pick the first node in this order\n The first node of a flow follows a strict hierarchy. Getting this wrong is the\n single most common authoring mistake (most often: opening with a navigate node).\n\n 1. SEED first — if the flow depends on pre-existing data, a `seed` node comes\n first. It provisions data in its own isolated context and exports\n $var.{dataKey} outputs the rest of the flow consumes.\n 2. Otherwise LOGIN first — for any authenticated flow, the first node is a\n `login` node that declares the ACTOR (who the journey runs as). This is the\n \"acting as\" step. Do NOT open an authenticated flow with a navigate node.\n 3. Navigate comes AFTER login — a navigate jumps to the test's entry point, but\n it follows the login; it is never the opening node of an authenticated flow.\n\n The only flows that may start with a navigate are UNauthenticated ones — signup,\n password reset, a public/marketing page, or a test of the login experience\n itself. For those, set the login node's `performLogin: false` (or omit the login\n node) and author the steps as the journey.\n\n LOGIN SUBSUMES LOGGING IN. A login node already provisions an authenticated\n session — it IS the act of logging in. Never emit a login node and then a\n \"navigate to /login\" → \"enter email/password\" → \"click Sign in\" sequence. Start\n with the login node and go straight to the first real action. The one exception\n is a flow whose explicit purpose is to test login (start logged out and make the\n login steps the journey).\n\nLOGIN\n Sets the user context. Select a credential to act as that user.\n The login node provisions an authenticated browser session — subsequent\n nodes start with the browser already logged in.\n\n Config:\n credentialId UUID of the credential to log in as. REQUIRED for the\n node to bind to a real credential. Without it the\n Flow Designer shows a red \"Select a credential\"\n warning even if credentialName is set.\n credentialName Human-readable name, used as the node title. Optional\n but recommended alongside credentialId.\n performLogin When true, the browser is authenticated automatically.\n\n Finding the credentialId:\n canary credential list [--env prod|dev]\n → prints \"ID: <uuid>\" under each credential name.\n Pick the ID whose property matches the environment the flow runs in.\n\n Ordering: login nodes should typically follow any seed nodes, not\n precede them. Seeds export variables (e.g. $var.workflow_id) that\n later nodes consume, so a seed-first / login-second order avoids\n wasted browser segments and lets login/navigate URLs reference\n seed outputs. See the SEED node type and the Node Ordering section\n of best-practices.\n\n - Workflows support multiple login nodes for multi-role testing.\n Each login node starts a new segment with a fresh browser session.\n Example: Login as Customer → place order → Login as Sales Rep → verify order.\n Great for two-sided apps, permission checks (member vs admin), and\n cross-role journeys.\n - Login nodes also appear after Wait nodes to re-establish the session.\n - A navigate node after login is optional but useful for jumping\n directly to the test's entry point.\n\nNAVIGATE\n Directs the browser to a specific path.\n\n Prefer relative paths (e.g. \"/flows\", \"/flows/$var.workflow_id\")\n over hard-coded absolute URLs. Relative paths let the same workflow\n run unchanged across environments (prod, dev, local, preview) — the\n base URL comes from the property/environment the run targets. A\n workflow that hard-codes \"https://app.dev.trycanary.ai/...\" will\n silently drive traffic against dev even when run against prod.\n\n Use an absolute URL only when the destination is genuinely off the\n application being tested (external identity provider, third-party\n checkout, docs site, etc.).\n\n - A navigate node after login is a great way to jump straight to the\n page where the test begins.\n - Select from discovered pages or enter a custom URL.\n\nACTION\n Performs a user interaction on the current page. Describe what the user\n should do (\"Create a new ticket\") and optionally provide input data via\n formFields.\n\n Every action node must have a title (customActionTitle). The title shows\n in the canvas, run timeline, failure reports, and issue tickets — an\n untitled action is nearly impossible to reason about after the fact.\n Keep titles short and intent-oriented, e.g. \"Create a ticket\" or\n \"Publish the flow\" — not \"Click the button\".\n\n Keep actions focused on a single user goal:\n Good: \"Create a ticket with required fields\"\n Bad: \"Click the title field\" (too granular)\n Bad: \"Create a ticket, assign it, comment, upload, and verify\" (too stuffed)\n\n Rule of thumb: if an action crosses multiple screens or changes multiple\n entities, split it. If it's a single user goal on a single screen, keep it.\n\n Actions can include:\n - customActionTitle: short intent-oriented title (required)\n - formFields: input data the action needs (name, email, etc.)\n - inlineAssertions: checks verified after the action completes (preferred\n over standalone assertion nodes — see Assertions section)\n - declaredOutputs: values to extract from the page for downstream use\n - customInstructions: additional guidance for the agent executing the step\n\nASSERTION\n Verifies expected outcomes. Define a condition to check.\n What happens on failure depends on the severity.\n\n Prefer inline assertions on action nodes over standalone assertion nodes.\n Inline assertions keep the test on track and produce cleaner failure\n reports. If verifying something requires significant interaction first,\n that's better modeled as an action node with inline assertions.\n\n Use standalone assertion nodes only when the check doesn't belong to\n any action — e.g., verifying a page state after navigation, or\n confirming data absence after a sequence of steps.\n\n Severity levels:\n fatal The test must end now — the run halts at this step.\n Use for preconditions later steps depend on.\n fail The test may continue — the run finishes marked failed,\n but later steps still run and produce signal.\n warn The test should continue — logged as a warning, run passes.\n\n Agentic assertions: for visual/layout checks that can't be mechanically\n validated, enable agent evaluation. These require the AI agent during\n replay and cannot be cached. Use for:\n - Timestamps or dates\n - Real-time data feeds\n - Content that changes between runs\n\nCONDITION\n Branches the workflow based on a runtime condition. Define a condition\n to evaluate, then connect separate paths for true and false outcomes.\n\nWAIT\n Pauses execution for a specified duration (minutes, hours, or days).\n Creates a segmented flow — execution pauses, then resumes automatically.\n Add a Login node after the Wait to re-establish the browser session.\n\nSETUP\n References another published workflow to run as a prerequisite.\n\n Execution modes:\n Inline (default) Runs before each workflow\n Suite-level Runs once per suite, shared across workflows\n\n When to use: creating users, projects, or records that multiple tests\n depend on. Login is handled separately — setup nodes are for data creation.\n\nSEED\n Injects outputs from a seed workflow as variables. Seed workflows\n generate test data and export named values. Downstream workflows\n access these as $var.{dataKey}.\n\n Ordering: seed nodes should almost always come FIRST — before the\n login node. Seeds run in their own isolated context (usually via\n API sequence) and export variables into the workflow. Placing a\n login before the seed wastes a browser session, and any\n login/navigate node that references $var.{seed_output} must come\n after the seed that produces it.\n\n Typical pattern:\n Seed → Login → Navigate → ... action/assertion nodes\n\n Config:\n seedWorkflowId UUID of the seed workflow (required)\n seedWorkflowName Human-readable name (used as the node title)\n\n Seed workflows are the preferred way to provision test data. See the\n Seed Workflows section for details on building and using them.\n\nAPI SEQUENCE\n Executes multiple API calls in sequence without a browser.\n Use for backend-only operations, webhooks, or API testing.\n\n API sequences are also used inside seed workflows — start with a\n browser-based seed to discover the right API calls, then convert\n to an API sequence for speed and reliability.\n\nSANDBOX ACTION\n Executes a sandbox action — a server-side script defined on the\n environment template — directly on the run environment's sandbox\n instance. No browser involved. The action's structured output is\n registered as workflow variables: each output key becomes\n $var.{key} for downstream steps.\n\n Config:\n actionSlug Slug of the action (required; discover via\n list_sandbox_actions)\n params Input values keyed by the action's inputSchema\n property names; values may use $var.{name} / macros\n outputKeys Output variable keys (defaults to the action's\n outputSchema keys)\n\n Output registration is allowlisted by declared intent: the action's\n outputSchema keys, else the node's outputKeys. If neither declares\n anything, NO result keys register — declare outputs explicitly for\n schema-less actions.\n\n Environment constraint: the action runs on the environment's\n backing sandbox instance. On a non-sandbox environment (static\n staging/prod) the node SKIPS with a warning and registers no\n variables — so workflows containing one are effectively\n sandbox-only.\n\n Seeds: a seed workflow whose body is a single sandbox action node\n is the fastest way to provision data — it runs entirely\n server-side (no browser session), and its outputs satisfy the\n seed's declared outputs like any captured value.\n\nNOTIFICATION\n Sends notifications (Slack, email, etc.) at a point in the workflow.\n\nEND\n Explicitly terminates the workflow. Use when a condition branch\n should stop execution rather than continue.","A playbook is a sequence of human-readable steps that describe the actions\ntaken during a workflow node's execution. Playbooks bridge the gap between\nhigh-level node descriptions (\"Create a ticket\") and the low-level browser\ninteractions that fulfill them.\n\nWHAT A PLAYBOOK CONTAINS\n\n Each playbook is an ordered list of PlaybookSteps:\n\n order Step sequence number\n action What to do: click, fill, fill_form, select, navigate,\n wait, scroll, hover, upload, verify, handle_native_dialog,\n toggle, press_key, focus, drag, resize, capture,\n extract_table, python_execute, verify_download,\n verify_download_content, screenshot, agent_loop\n target The element or area being acted on\n params Key-value parameters for the action\n note Human-readable description of the step\n\n Example playbook for \"Create a ticket\":\n 1. click \"New Ticket\" button\n 2. fill_form Title: \"QA Test — Billing Bug\", Priority: \"High\"\n 3. click \"Submit\" button\n 4. verify Success toast appears\n\nHOW PLAYBOOKS ENABLE CACHE REPLAY\n\n When a workflow runs for the first time, the AI agent explores the\n application, performs actions, and generates a playbook for each node.\n The raw browser actions (clicks, keystrokes, waits) are cached alongside\n the playbook steps.\n\n On subsequent runs, the system uses playbook-step-driven replay:\n\n 1. Load the playbook steps from the node config\n 2. For each step, look up the cached browser actions\n 3. Replay the cached actions directly (no AI agent needed)\n 4. If a step's cache misses or fails, the AI agent heals that step\n\n This means most runs execute instantly via cache, with the agent only\n invoked for steps that have changed or broken.\n\nCOMPILED ENTRIES\n\n The cache maps playbook steps to cached action indices:\n\n cached Playbook step has matching cached actions — replayed directly\n gap No cache for this step — agent performs it fresh\n\n A fully cached node replays in seconds. A node with gaps falls back to\n agent execution only for the missing steps.\n\nPLAYBOOK HEALTH\n\n Each cached node tracks playbook health:\n\n verified Cache is working correctly across recent runs\n degraded Some steps have failures — cache still used but monitored\n stale Cache is no longer reliable — full agent re-execution needed\n\n Step-level failure counts track which specific steps break most often,\n guiding targeted cache healing.\n\nWHY PLAYBOOKS MATTER FOR AUTHORING\n\n When you build a workflow, the quality of your node descriptions directly\n affects playbook quality. Clear, intent-focused descriptions produce\n better playbooks, which produce more reliable cache replay.\n\n Good: \"Create a ticket with title 'QA Test' and priority 'High'\"\n → Clean playbook: fill_form with clear fields, click submit\n\n Bad: \"Do the thing on the page\"\n → Vague playbook: agent guesses at actions, cache breaks easily\n\n The playbook is the semantic contract between your intent and the\n execution engine. Write nodes that describe what a human would do,\n and the playbook will faithfully capture and replay it.\n","SCOPE: ONE COHERENT USER JOURNEY\n\n A workflow should test one job-to-be-done, not multiple unrelated tasks.\n Many steps are fine if they're all part of the same flow (creating,\n editing, verifying one entity). Stop when the goal is accomplished.\n\n Good — coherent journey:\n Login → Navigate to projects → Create project → Edit name →\n Assert name updated → Cleanup: delete project\n\n Good — multi-role journey:\n Login as Customer → Place an order →\n Login as Sales Rep → Verify the order appears in the queue\n\n Good — read-only flow:\n Login → Navigate to dashboard → Assert widgets visible\n\n Bad — multiple unrelated journeys:\n Dashboard → Create item → Manage users → Generate report\n (These are separate jobs — create separate workflows)\n\n Rule: \"Is this step dependent on or naturally connected to the previous\n steps?\" If no, you're starting a new journey — stop.\n\nWRITE STEPS AS HUMAN INTENT\n\n A workflow should read like instructions you'd explain to a teammate:\n - \"Create a ticket assigned to Support.\"\n - \"Submit the ticket and confirm it appears in the list.\"\n - \"Change the ticket status to Closed.\"\n\n Capture the \"why\" and the \"what\" — not UI mechanics.\n\nCHOOSE THE RIGHT GRANULARITY\n\n Too granular:\n - \"Click New\"\n - \"Type title\"\n - \"Type description\"\n - \"Click Save\"\n\n Too stuffed:\n - \"Create a ticket, assign it, comment, upload, and verify in three views\"\n\n Good:\n - \"Create a ticket with required fields\"\n - \"Assign the ticket to Support\"\n - \"Verify the ticket appears in the queue\"\n\n If an action crosses multiple screens or changes multiple entities, split it.\n If it's a single user goal on a single screen, keep it as one action.\n\nMAKE EACH TEST SELF-SUFFICIENT\n\n Tests should not depend on what another test created or on long-lived\n shared state. If a workflow needs data, provision it:\n\n - Use a seed workflow (preferred) to generate data and export variables\n - Use a setup node to reference a published workflow for shared data\n - As a last resort, add data creation steps at the start of the workflow\n - Always use macros ($EMAIL, $UUID, etc.) so reruns don't collide\n\n This keeps runs deterministic and prevents cascading failures.\n\nVERIFY EVERY SIGNIFICANT ACTION\n\n Before recording a step, verify it worked:\n\n - Form submissions: confirm acceptance (success message, redirect, new item in list)\n - Data creation: navigate to where the record should appear and confirm\n - Data modification: reload and confirm the change persisted\n - Deletions: confirm the item is gone (a toast alone is not enough)\n - Navigation: confirm the expected page loaded\n\n If verification fails, debug the issue — don't record and move on.\n\nKEEP DESCRIPTIONS CLEAR\n\n Node titles should be short and action-oriented:\n Good: \"Create a support ticket\"\n Bad: \"Step 3 - ticket creation process\"\n\n Node descriptions should add detail the title can't carry:\n Good: \"Fill the form with a QA Test subject and High priority, then submit\"\n Bad: \"Do the thing\"\n\nNODE ORDERING\n\n The start-of-workflow order is a strict hierarchy (see \"STARTING NODE\"\n in the Node Types guide):\n\n Seed (if needed) → Login → Navigate → ...\n\n The first node is the ACTOR, not a navigate: an authenticated flow opens\n with a `login` node (or a `seed`, if it needs data first) — never with a\n navigate node. A navigate jumps to the test's entry point AFTER login.\n Only unauthenticated flows (signup, password reset, public pages, or a\n login test) may start with a navigate.\n\n Seed nodes should come first. Seeds run in their own isolated context\n (usually via API sequence) and export variables the rest of the flow\n consumes. Putting a login before the seed wastes a browser segment,\n and any login/navigate that references $var.{seed_output} must come\n after the seed that produced it.\n\n Only skip the seed-first rule if the seed itself genuinely depends on\n a browser session created earlier in the same workflow (rare — in\n that case, prefer a separate browser-based seed workflow and reference\n it here).\n\nLOGIN BEST PRACTICES\n\n - Most workflows start with a login node. Workflows can also start\n with a seed node or API sequence when no browser session is needed yet.\n - Login SUBSUMES logging in. A login node already provisions an\n authenticated session — it IS the act of logging in. Never follow a\n login node with \"navigate to /login\" / \"enter email + password\" /\n \"click Sign in\" steps. Start with the login node and go straight to\n the first real action. (Only exception: a flow whose purpose is to\n test login — start logged out and make the login steps the journey.)\n - Login nodes require a credentialId (UUID), not just a credentialName.\n Without a credentialId the Flow Designer flags the node as invalid.\n Find credential IDs with: canary credential list [--env prod|dev]\n - Use multiple login nodes for multi-role testing — each login starts\n a new segment with a fresh session as that user\n - Don't test login itself (unless that's the explicit goal)\n - A navigate node after login is a great way to jump directly to the\n test's entry point\n\nPREFER INLINE ASSERTIONS\n\n Attach assertions to action nodes using inlineAssertions rather than\n adding standalone assertion nodes. Inline assertions keep the test\n focused and produce clearer failure reports. See the Assertions section\n for details.","Macros generate fresh, unique data every time a workflow runs. Variables let\nyou reference shared values across nodes. Both use the $ prefix.\n\nAVAILABLE MACROS\n\n $EMAIL() Unique test email test-a1b2@example-test.com\n $FIRST_NAME() Random first name Jordan\n $LAST_NAME() Random last name Chen\n $PHONE() Random US phone +1-555-382-7491\n $UUID() Random UUID v4 a1b2c3d4-e5f6-...\n $NOW() ISO 8601 timestamp 2026-02-19T14:30:00.000Z\n $TODAY() Current date 2026-02-19\n $DATE(N) Date offset by N days $DATE(7) = next week\n $TIMESTAMP() Unix timestamp (ms) 1771520400000\n $RANDOM_INT(min,max) Random integer $RANDOM_INT(1,100) = 42\n $RANDOM_STRING(len) Random alphanumeric $RANDOM_STRING(6) = xK9mQ4\n $SEQUENCE(name) Auto-incrementing $SEQUENCE(order) = 1, 2, 3...\n\nSYNTAX\n\n Macros follow the format $MACRO_NAME() or $MACRO_NAME(args).\n They can appear standalone or inline within a larger string:\n\n Standalone: $EMAIL()\n Inline: user-$UUID()@corp.com\n Escaped: \\$EMAIL() produces the literal text $EMAIL()\n\n Each run resolves macros independently — every execution gets fresh values.\n\nVARIABLES\n\n Variables reference values set during a workflow run. When an action has\n input fields or extracts data, those become $var.{name} references.\n\n Sources:\n Input A value entered in an action's field $var.company\n Macro A macro expression in a field $var.email\n Extracted Data extracted from the page $var.order_id\n Credential Values from the login credential $var.username\n\n Use $var.{name} in subsequent step formFields and descriptions.\n Don't re-hardcode values — reference the variable from the earlier step.\n\nHOW VARIABLES GET BOUND\n\n Two distinct paths create $var.{name} bindings. Picking the wrong one is a\n common foot-gun.\n\n 1. Typed input (auto-promote)\n\n Add an entry to inputValues on an action node:\n\n inputValues: { company: \"$RANDOM_STRING(8)\" }\n\n The key \"company\" auto-promotes to $var.company for every downstream\n node. Do NOT also list it in declaredOutputs — the input itself IS the\n binding.\n\n 2. DOM capture (declaredOutputs + playbook capture)\n\n For values that only exist after the page renders (URL fragment, badge\n text, generated ID in the breadcrumb), declare them upfront and capture\n them inside the playbook:\n\n declaredOutputs: [\"order_id\"]\n playbookSteps: [\n { order: N, action: \"capture\", target: \"<selector or rule>\",\n outputKey: \"order_id\" }\n ]\n\n The capture step writes into $var.order_id at runtime. Without\n declaredOutputs the downstream resolver won't recognize the binding.\n\n Rule of thumb: if you can type the value into a field before the run, it's\n an input. If the value only exists after something happens in the browser,\n it's a captured output.\n\nSEED VARIABLES\n\n When seed workflows are configured, their outputs are available as\n $var.{dataKey} references. If a seed provides data you need (a project ID,\n a user record), use the seed variable — don't create that data again.\n\nCOMMON PATTERNS\n\n Unique user registration:\n Email: $EMAIL()\n Name: $FIRST_NAME() $LAST_NAME()\n\n Numbered items:\n $SEQUENCE(\"orders\") → 1, 2, 3... (resets each run, independent per name)\n\n Date-relative testing:\n $DATE(30) for 30 days out, $DATE(-7) for last week, $TODAY() for now\n\n Unique identifiers:\n $UUID() for globally unique, $RANDOM_STRING(8) for shorter strings\n Combine with text: order-$RANDOM_STRING(6)\n\nBEST PRACTICES\n\n - Use $EMAIL() instead of hardcoded addresses for uniqueness\n - Use $SEQUENCE(\"name\") when you need predictable ordering within a run\n - Prefer $DATE(days) over fixed dates so tests stay valid over time\n - Always include a value for every formField — don't leave fields empty","Seed workflows are the preferred way to provision test data. A seed\nworkflow creates data your test needs and exports named variables that\ndownstream workflows can reference.\n\nWHY USE SEEDS\n\n - Reusable: one seed can serve many test workflows\n - Fast: seeds can use API sequences instead of slow browser interactions\n - Clean: paired teardown workflows handle cleanup automatically\n - Isolated: each run gets its own fresh data via macros\n\nHOW SEEDS WORK\n\n 1. Create a workflow with flowType \"seed\"\n 2. Define seedOutputs — the named values the seed exports\n (e.g., project_id, user_email, order_number)\n 3. The seed creates data and captures those values during execution\n 4. Downstream workflows add a Seed node that references this seed\n 5. The seed's outputs are available as $var.{dataKey} in the test\n\n Example:\n Seed \"Create Test Project\" exports: project_id, project_name\n Test workflow references the seed, then uses:\n Navigate to $var.project_id\n Assert page title contains $var.project_name\n\nCREATING SEEDS\n\n A seed workflow shell needs a name, declared outputs, and usually a paired\n teardown. Outputs are the contract downstream workflows depend on; define\n them before building the seed body so every node captures the right values.\n\n Simple data outputs need:\n - dataKey: stable variable name, used as $var.{dataKey}\n - name: human label\n - description: optional context for builders and reviewers\n\n Credential outputs additionally define credentialOutput, including provider\n type, generated field mapping, inbox behavior, and loginUrl.\n\n After creating the shell, add nodes through the Flow Designer, workflow sync,\n or API, then publish once the seed and paired teardown both pass.\n\n CLI users: see `canary workflow guide cli-seeds` for command usage.\n\nBUILDING A SEED: START WITH THE BROWSER\n\n The easiest way to build a seed is to start with browser-based steps:\n\n 1. Create a seed workflow (flowType: seed)\n 2. Add a login node with credentials that have permission to create data\n 3. Add action nodes that create the data through the UI\n - Use macros for all names and identifiers ($EMAIL, $RANDOM_STRING, etc.)\n 4. Add declaredOutputs on action nodes to capture generated values\n (IDs, URLs, confirmation numbers)\n 5. Define seedOutputs on the workflow to export those captured values\n 6. Test and publish the seed\n\n This approach lets you discover exactly what steps and data are needed\n by interacting with the real application.\n\nCONVERTING TO API SEQUENCES\n\n Once a browser-based seed works reliably, convert it to an API sequence\n for speed and reliability. Canary can do this automatically.\n\n Auto-conversion from a workflow run:\n 1. Open the seed workflow in the Flow Designer\n 2. Add an api_sequence node\n 3. In the node config, choose \"Generate from workflow run\"\n 4. Select a completed run of the browser-based seed\n 5. The AI agent analyzes the network requests captured during\n that run and generates an equivalent API sequence automatically\n 6. The agent tests each step against the live API to verify it works\n 7. Review the generated sequence and publish\n\n The AI agent has access to your application's API catalog and can:\n - Search for endpoints by keyword\n - Inspect request/response schemas\n - Test individual API calls to verify they work\n - Compose a multi-step sequence with variable passing between steps\n - Validate the full sequence end-to-end before finalizing\n\n You can also generate an API sequence from a prompt — describe what\n data to create and the agent will find the right endpoints and build\n the sequence.\n\n API sequences support two kinds of dynamic values:\n - Step references: {{stepId.response.path.to.value}} to pass data\n between steps (e.g., use the project ID from step 1 in step 2)\n - Macros: $EMAIL(), $UUID(), $RANDOM_STRING(), etc. for fresh\n unique data each run\n\n Exports map response fields to seed output variables:\n - stepId: which step to extract from\n - responsePath: dot notation path (e.g., \"data.id\")\n - variableName: the $var.{name} downstream workflows will use\n\nEXECUTION MODES\n\n Seeds automatically choose the best execution mode:\n\n browser Runs through the browser like a normal workflow\n api Runs the API sequence directly — no browser needed\n recommended Uses the API sequence if one exists, otherwise browser\n\n Once you've added an API sequence to a seed, it will automatically\n run via API — faster, cheaper, and more reliable than browser execution.\n\n Not all seeds can be converted — some data creation flows require\n browser interaction (file uploads, complex wizards, third-party\n integrations). Keep those as browser-based seeds.\n\nAPI CALL TIMEOUT\n\n When a seed runs in API mode (executionMode \"api\", or \"recommended\"\n resolving to API), each HTTP call uses a 2-minute (120s) timeout by\n default. Seeds/teardowns that hit slow provisioning endpoints can raise\n this per seed node via apiTimeoutSeconds — it applies to both the seed\n and its paired teardown. Ignored for browser-mode seeds.\n\n Set it three equivalent ways:\n - Flow Designer: the \"API call timeout (seconds)\" field on the Seed node\n - .canary.md: a \"- apiTimeoutSeconds: 300\" bullet under the Seed node\n - workflow JSON (create / sync): on the seed node's configJson, e.g.\n { \"nodeType\": \"seed\",\n \"configJson\": { \"seedExecutionMode\": \"api\", \"apiTimeoutSeconds\": 300 } }\n\n Leave it unset to keep the 120s default; an invalid value falls back to\n the default rather than erroring.\n\nTEARDOWN WORKFLOWS\n\n Every seed can have a paired teardown workflow that cleans up the\n data it created. Teardowns run automatically after the seed's\n downstream workflows complete.\n\n - Set flowType to \"teardown\" and link it to the seed\n - The teardown receives the same $var.{dataKey} variables the seed exported\n - Use those variables to find and delete the created data\n\n Teardowns are the cleanest way to handle cleanup — they keep cleanup\n logic separate from test logic and run automatically.\n\nSANDBOX-ACTION-BACKED SEEDS\n\n When the property has a verified sandbox template with actions, a seed\n workflow can provision data by running a SANDBOX ACTION node instead of\n driving the UI or composing API calls. The seed's body is a single\n sandbox_action node (plus End); the action's outputs register as\n $var.{key} and satisfy the seed's declared outputs directly.\n\n - Fastest seed form: runs entirely server-side, no browser session\n - Discover actions with list_sandbox_actions; outputs come from the\n action's outputSchema\n - Constraint: consuming workflows become sandbox-only — on a\n non-sandbox environment the action node skips with a warning and\n produces no variables\n - Teardown is usually unnecessary: sandbox environments are destroyed\n after the suite, taking provisioned data with them\n\nSEED BEST PRACTICES\n\n - Use macros in all created data ($EMAIL, $RANDOM_STRING, etc.)\n so each run gets unique, non-conflicting data\n - Keep seeds focused — one seed per logical dataset\n (e.g., \"Create Project with Members\" not \"Create Everything\")\n - Export only what downstream workflows need — don't over-export\n - Start with browser-based seeds, then use auto-conversion to generate\n an API sequence from a completed run\n - For sandbox-backed properties, prefer a sandbox-action-backed seed\n (see above) — server-side, fast, and reliable\n - Pair seeds with teardown workflows for automatic cleanup\n - Use suite-level setup nodes to share seed data across multiple\n workflows in the same test suite\n","Test data discipline keeps workflows reliable and concurrent-safe.\n\nPREFER SEED WORKFLOWS FOR DATA\n\n Seed workflows are the best way to provision test data. They run before\n your test workflow, create the data it needs, and export variables that\n downstream workflows can reference as $var.{dataKey}.\n\n Benefits of seeds over inline data creation:\n - Reusable across multiple workflows\n - Faster — can use API sequences instead of browser interactions\n - Cleaner separation of setup and test logic\n - Paired teardown workflows handle cleanup automatically\n\n See the Seed Workflows section for how to build and use them.\n\nTHE DATA OWNERSHIP PRINCIPLE\n\n Own your data:\n - Data you create → clean it up when the workflow finishes\n - Settings you modify → revert them when the workflow finishes\n - Data that was already there → never delete it\n\n It's fine to depend on pre-existing data (existing integrations, org\n settings, reference data). Only create what doesn't already exist or\n what the test specifically needs to own.\n\nCREATING TEST DATA\n\n If the test operates on a record (edit, delete, archive), create that\n record as an early step — unless it already exists and the test is meant\n to operate on it.\n\n Never reference \"any\" resource:\n Bad: \"Pick a project from the list\" (which one? may not exist)\n Good: \"Create a project named 'QA Test — $RANDOM_STRING(6)'\"\n Good: \"Use the seed output $var.project_id\"\n\n Always use macros in names to ensure uniqueness across parallel runs:\n Bad: \"Test Item\" (generic, will collide with other runs)\n Bad: \"QA Test Project\" (still collides if two runs overlap)\n Good: \"QA Test — $RANDOM_STRING(6)\" (unique every run)\n Good: \"QA Test $FIRST_NAME() $LAST_NAME()\" (unique and readable)\n\n After creating data, verify it exists before continuing.\n\nNAMING CONVENTION\n\n All test data should follow this pattern:\n\n Name/Title: \"QA Test $FIRST_NAME() $LAST_NAME()\"\n Email: \"$EMAIL()\"\n Phone: \"$PHONE()\"\n Project/Item: \"QA Test — $RANDOM_STRING(6)\"\n Unique ID: \"QA$TIMESTAMP()\"\n\n The \"QA Test\" prefix makes test data instantly recognizable. The macro\n suffix ensures every run creates unique data that won't collide with\n other runs or leftover data from previous executions.\n\nCLEANING UP (STRONGLY RECOMMENDED)\n\n Workflows that create data should include cleanup steps at the end.\n Workflows that modify settings should revert them.\n\n This isn't strictly required, but it's strongly recommended:\n - Cleanup prevents data accumulation over time\n - It keeps the test environment clean for other workflows\n - The \"QA Test\" naming convention makes orphaned data identifiable\n even when cleanup is skipped or fails\n\n Don't over-engineer cleanup — a simple \"navigate to the item and\n delete it\" is sufficient. For seed workflows, use a paired teardown\n workflow instead.\n\nWHAT NOT TO TOUCH\n\n - Don't create users, roles, or org-level config unless that's the goal\n - Don't modify shared resources (billing, integrations, API keys) as a side effect\n - Don't delete or modify data not owned by this workflow\n\nAVOIDING COLLISIONS WITH MACROS\n\n The best way to avoid data collisions is to use macros for every\n name, email, and identifier. When every run generates unique values,\n there's no risk of conflicting with parallel runs or leftover data:\n\n $EMAIL() Unique email every run\n $RANDOM_STRING(6) Short unique suffix for names\n $UUID() Globally unique identifier\n $TIMESTAMP() Unique-per-millisecond numeric ID\n\n Combined with the \"QA Test\" prefix, this means you never need to\n worry about whether data from a previous run still exists. Each run\n creates its own isolated dataset.\n\nREAD-ONLY FLOWS\n\n Workflows that only read data (verify dashboard loads, check reports)\n don't need creation or cleanup steps. Not every workflow needs to\n create data — only create what the test specifically requires.","Assertions verify that the application behaves as expected. There are two\nways to add assertions: inline on action nodes, or as standalone assertion\nnodes. Inline assertions are strongly preferred.\n\nINLINE ASSERTIONS (PREFERRED)\n\n Attach assertions directly to action nodes using the inlineAssertions\n field. These are verified immediately after the action completes and\n cached for fast replay.\n\n Inline assertions are the best way to verify outcomes because they:\n - Keep the test on track — verification happens right where the action is\n - Produce clean failure reports — each assertion is tied to the step that caused it\n - Are cacheable — fast replay on subsequent runs\n\n Example — after submitting a form:\n Action: \"Submit the support ticket\"\n Inline assertions:\n - \"Success toast appears\" (severity: warn)\n - \"Ticket appears in the ticket list\" (severity: fail)\n - \"Form is no longer visible\" (severity: fatal)\n\n Severity levels — what a failure means for the run:\n fatal The test must end now. The run halts at this step.\n Use when continuing is pointless: login succeeded, the page\n loaded, a precondition every later step depends on.\n Example: \"User is logged in and the dashboard is visible\"\n fail The test may continue. The step is marked failed and the run\n finishes marked failed, but later steps still execute and\n produce signal.\n Use for independent checks: data saved, expected row present,\n error absent.\n Example: \"The new record appears in the table\"\n warn The test should continue. The failure is recorded as a warning\n and the run still passes.\n Use for cosmetic or non-critical checks: toast appeared,\n animation completed.\n Example: \"Success toast appears\"\n\n Choosing a severity: ask \"if this is wrong, is there any value in\n running the rest of the test?\" No → fatal. \"Does this being wrong mean\n the feature is broken?\" Yes → fail. Otherwise → warn. When unsure,\n prefer fatal for preconditions and fail for feature claims. Always set\n a severity explicitly — don't leave it unspecified.\n\n If verifying something requires significant interaction (scrolling,\n navigating, expanding sections), model that as an action node with\n inline assertions — not a detailed standalone assertion node.\n\nSTANDALONE ASSERTION NODES (USE SPARINGLY)\n\n Use dedicated assertion nodes only when the check doesn't belong to\n any action:\n\n - Verifying a final page state after navigation (no action to attach to)\n - Checking that data was NOT modified (absence checks after a sequence)\n - Confirming a state visible only after a wait or page transition\n\n A typical workflow has 0-1 standalone assertion nodes. If you find\n yourself writing a complex assertion node that requires multiple steps\n to verify, consider whether it should be an action node with inline\n assertions instead.\n\nAGENTIC ASSERTIONS\n\n For visual or layout checks that can't be mechanically validated,\n enable agent evaluation. These require the AI agent during replay\n and cannot be cached.\n\n Use for:\n - Screenshots that should \"look correct\"\n - Charts or graphs rendering properly\n - Dynamic content that changes between runs\n - Timestamps or real-time data\n\n Standard assertions are preferred — only use agentic when the\n check is inherently subjective or dynamic.\n\nWRITING GOOD CONDITIONS\n\n Assertions must be specific and observable:\n\n Good:\n - \"The status badge shows 'Active'\"\n - \"The table contains a row with name 'Test Record'\"\n - \"Error message is not visible\"\n - \"The page title is 'Dashboard'\"\n\n Bad:\n - \"The page looks correct\"\n - \"The action was successful\"\n - \"Everything works\"\n\n Start with what's observable: \"The page displays...\", \"The table\n contains...\", \"The field shows...\". Include the specific value\n you expect.\n\nASSERTION PLACEMENT\n\n Place assertions at critical verification points:\n\n 1. After data creation: verify the record exists (inline on the create action)\n 2. After data modification: verify the change persisted (inline on the edit action)\n 3. After deletion: verify the item is gone (inline on the delete action)\n 4. At the goal completion point: verify the journey succeeded\n\n Don't assert everything — focus on the claims that matter.\n A focused assertion that proves the test's core claim is better\n than a dozen checks on every UI element.","API Sequences are the API-only counterpart to browser workflows. Instead of\ndriving a browser node-by-node, an API sequence is a single node\n(nodeType: \"api_sequence\") inside an api-only workflow that executes an\nordered list of HTTP calls, chaining outputs from one step into the inputs\nof the next.\n\nWHEN TO USE\n\n - Exercise an API without a UI (integration tests, fixture setup).\n - Seed or tear down state via API before/after a browser run.\n - Fast, deterministic smoke test of a critical flow.\n\nCONFIG SHAPE (ApiSequenceConfig)\n\n {\n \"steps\": [ ... ], // ordered; required\n \"description\": \"...\", // optional\n \"stopOnFailure\": true, // default: true\n \"exports\": [ ... ] // optional; see below\n }\n\nSTEP SHAPE (ApiSequenceStep)\n\n The authoritative type is in packages/types/src/api-sequence.ts. Key fields:\n\n {\n \"stepId\": \"createProject\", // optional; defaults to \"step{index}\"\n \"apiRequestId\": \"<catalog id>\", // required — points to api_requests row\n \"credentialId\": \"<uuid>\" | null, // null = unauthenticated\n \"method\": \"POST\", // optional; falls back to catalog default\n \"urlTemplate\": \"/projects/{{createProject.response.id}}\",\n \"queryParams\": [ { \"key\": \"limit\", \"value\": \"10\" } ],\n \"bodyTemplate\": \"{\\\"name\\\": \\\"$EMAIL()\\\"}\", // STRING (JSON), not object\n \"headersTemplate\": { \"X-Trace\": \"$UUID()\" }, // optional\n \"responseVariableName\": \"createProject\", // optional alias for stepId\n \"expectedStatusCodes\": [200, 201], // step fails if status is outside\n \"description\": \"...\", // optional UI label\n \"validations\": [ ... ] // assertions against the response\n }\n\n CREDENTIAL ROLES — `credentialId` is overloaded; two distinct uses exist:\n\n - Step-level `credentialId` (and a top-level/default credential on the\n sequence) is AUTH: it's what the api-sequence runner uses to\n authenticate each HTTP call. Editing this changes who is calling.\n\n - `credentialId` appearing INSIDE a step's `bodyTemplate` JSON string is\n DATA: it gets written into the request body and becomes part of the\n provisioned resource (e.g. the credential a created workflow logs in\n with). Editing this changes what the call creates.\n\n The two are independent. Swapping the auth credential won't change what\n the call provisions; swapping the body credential won't change auth.\n Mixing them up silently produces confusing test failures.\n\n `apiRequestId` references a row in the `api_requests` table. Discover IDs\n from the API catalog for the target property. If `urlTemplate`, `method`,\n or `bodyTemplate` are omitted, they are backfilled from the catalog entry's\n defaults at execution time.\n\n `bodyTemplate` is a JSON *string*, not a JSON object — templates and macros\n are interpolated into it as raw text before parsing.\n\nTEMPLATE SYNTAX\n\n Three ways to inject dynamic values. All three can appear in the same\n string (urlTemplate, bodyTemplate, headersTemplate values, or queryParams\n values).\n\n 1. STEP REFERENCES — outputs of prior steps.\n\n {{stepId.response.path.to.value}}\n\n The `.response.` segment is REQUIRED. This is the most common foot-gun:\n\n ✓ {{createProject.response.data.id}}\n ✗ {{createProject.data.id}} — missing .response., will warn at\n runtime and resolve to undefined\n ✗ {{projectId}} — no step reference at all\n\n The executor logs a warning for malformed references but does NOT\n block execution — a malformed template resolves to an empty string and\n the request goes out anyway. Always run once and check the run log.\n\n 2. MACROS — dynamic data generated fresh per run.\n\n $UUID() Random UUID v4\n $NOW() ISO 8601 timestamp (UTC)\n $TODAY() YYYY-MM-DD\n $DATE(N) Date offset by N days\n $TIMESTAMP() Unix ms\n $RANDOM_INT(min,max) Random integer in range\n $RANDOM_STRING(N) Alphanumeric string of length N\n $EMAIL() test-<rand>@example-test.com\n $FIRST_NAME() Random first name\n $LAST_NAME() Random last name\n $PHONE() +1-555-...\n $SEQUENCE(\"name\") Per-run auto-increment counter\n\n Each run resolves macros independently. $SEQUENCE counters persist\n across steps within a single run.\n\n 3. WORKFLOW VARIABLES — values injected by the workflow runtime.\n\n $var.<name>\n\n These come from two places:\n\n a) Upstream credential variables — pre-provisioned before the\n sequence runs. Typical names: `$var.credential.username`,\n `$var.credential.password`, `$var.credential.email`. If the\n workflow has a credential, USE these for the matching fields\n instead of `$EMAIL()` / `$RANDOM_STRING()` — the values must\n match the already-provisioned account.\n\n b) Upstream exports — values exported by earlier nodes in the same\n workflow (e.g. a seed step produced `$var.project_id`).\n\n Naming convention for exported variables: `resource_field` with\n underscores (e.g. `project_id`, `user_email`).\n\nEXPORTS\n\n After all steps finish, the sequence can register values from the final\n state into the workflow variable registry for downstream nodes:\n\n {\n \"exports\": [\n {\n \"variableName\": \"project_id\", // appears as $var.project_id\n \"stepId\": \"createProject\",\n \"responsePath\": \"data.id\",\n \"source\": \"response\", // \"response\" (default) | \"request\"\n \"description\": \"...\" // optional UI label\n }\n ]\n }\n\n Only export fields downstream nodes actually need. Use the\n `resource_field` naming convention.\n\nVALIDATIONS\n\n Per-step assertions against the response. Each validation:\n\n {\n \"left\": \"createProject.response.data.status\", // \"stepId.path\" form\n \"operator\": \"equals\", // see list\n \"right\": \"active\", // omit for is_set/is_not_set\n \"description\": \"...\"\n }\n\n Operators: equals, not_equals, gt, lt, gte, lte, contains, not_contains,\n is_set, is_not_set.\n\nWHAT IS VALIDATED AT COMMIT TIME\n\n Very little. The save endpoint accepts anything matching\n { steps: any[], description?, stopOnFailure?, exports? }. It does NOT\n verify that apiRequestId exists in the catalog, that stepIds are unique,\n that {{stepId.response.path}} references a real step, that exports'\n stepId resolves, or that macro names are known.\n\n The only template sanity check is `validateStepTemplates()` in\n apps/api/src/workflows/execution/api-sequence-executor.ts, which runs\n at EXECUTE time, only flags `{{stepId.X}}` missing `.response.`, and only\n LOGS A WARNING — the sequence still runs. Always smoke-test the sequence\n before committing it to a workflow.\n\n CLI users: see `canary workflow guide cli-api-sequences` for command usage.\n\nEXAMPLE (3-step sequence, correct shape)\n\n {\n \"description\": \"Create an item, fetch it, delete it\",\n \"stopOnFailure\": true,\n \"steps\": [\n {\n \"stepId\": \"create\",\n \"apiRequestId\": \"<POST /items id>\",\n \"credentialId\": null,\n \"method\": \"POST\",\n \"bodyTemplate\": \"{\\\"name\\\": \\\"item-$RANDOM_STRING(6)\\\"}\",\n \"expectedStatusCodes\": [201]\n },\n {\n \"stepId\": \"fetch\",\n \"apiRequestId\": \"<GET /items/:id id>\",\n \"credentialId\": null,\n \"method\": \"GET\",\n \"urlTemplate\": \"/items/{{create.response.id}}\",\n \"expectedStatusCodes\": [200],\n \"validations\": [\n { \"left\": \"fetch.response.name\", \"operator\": \"is_set\" }\n ]\n },\n {\n \"stepId\": \"remove\",\n \"apiRequestId\": \"<DELETE /items/:id id>\",\n \"credentialId\": null,\n \"method\": \"DELETE\",\n \"urlTemplate\": \"/items/{{create.response.id}}\",\n \"expectedStatusCodes\": [200, 204]\n }\n ],\n \"exports\": [\n { \"variableName\": \"item_id\", \"stepId\": \"create\", \"responsePath\": \"id\" }\n ]\n }\n\nTIPS\n\n - Give every step a short, stable `stepId`. Later steps and exports\n reference it; the default `stepN` label is brittle to reordering.\n - Always include `.response.` in step references. The runtime won't\n error out, but values will silently resolve to empty strings.\n - Prefer `$EMAIL()`, `$UUID()`, `$RANDOM_STRING()` for fields that must\n be unique per run — unless the workflow has an upstream credential,\n in which case use `$var.credential.username` / `.password` / `.email`.\n - Set `expectedStatusCodes` on every step so unexpected 4xx/5xx fails\n the step instead of silently flowing into the next template.\n - `bodyTemplate` is a JSON STRING. Escape inner quotes.\n - `workflow api-sequence generate` can AI-draft a config from a prompt\n or a prior browser run; refine with `update`. The generated output is\n just JSON — review it before committing.\n","Use this section when you need to create or inspect seed workflows from the\nCanary CLI. The conceptual model lives in `seed-workflows`; this section is\nonly command orientation. Prefer each command's `--help` output for the\ncurrent flag list.\n\nCREATE A SIMPLE SEED SHELL\n\n For simple data outputs, create the seed shell with repeatable output\n declarations:\n\n canary workflow seed create \\\n --name \"Create Test Project\" \\\n --description \"Provisions a test project with default settings\" \\\n --output \"project_id:Project ID:The created project's UUID\" \\\n --output \"project_name:Project Name\"\n\n This creates a draft seed workflow and, by default, a paired teardown\n workflow linked to the seed.\n\nCREATE A COMPLEX SEED SHELL\n\n For credential outputs or larger configs, put the full seed definition in a\n JSON file and create from that file:\n\n canary workflow seed create --from-file seed.json\n\n Keep generated credential fields in credentialOutput, and keep exported data\n fields in outputs. Downstream workflows consume both through $var.{dataKey}.\n\nAFTER CREATION\n\n Add the seed body through the Flow Designer or workflow sync, test both the\n seed and teardown, then publish. If the seed can be API-backed, generate or\n attach an API sequence after the browser version is proven.\n\nREFERENCE\n\n - Seed command help: `canary workflow seed --help`\n - Workflow sync help: `canary workflow sync --help`\n","Use this section when you need to drive API sequence authoring from the\nCanary CLI. The conceptual model lives in `api-sequences`; this section is\nonly command orientation. Prefer each command's `--help` output for the\ncurrent flag list.\n\nCOMMON FLOW\n\n 1. Inspect the API catalog for candidate endpoints.\n\n canary api-catalog sources list\n canary api-catalog endpoints list --search <keyword>\n canary api-catalog endpoints get <apiRequestId>\n\n 2. Compose a sequence JSON file locally. Reference endpoints by\n apiRequestId and chain steps with {{stepId.response.path}}.\n\n 3. Create an API-only workflow from the sequence file.\n\n canary workflow create --api-only --name \"smoke: create project\" \\\n --sequence-from-file seq.json\n\n The command returns the workflow, sequence, and node IDs.\n\n 4. Execute immediately to surface template warnings and API failures.\n\n canary workflow api-sequence execute <workflowId>\n\n 5. Inspect the run and iterate on the sequence file.\n\n canary workflow runs list <workflowId> --side api\n canary workflow runs get <workflowId> <runId>\n canary workflow api-sequence update <workflowId> --from-file seq.json\n\nREFERENCE\n\n - Command help: `canary workflow api-sequence --help`\n - Workflow creation help: `canary workflow create --help`\n - API catalog help: `canary api-catalog --help`\n","import type { GuideSection } from '../types.js';\n\nimport overview from './overview.txt';\nimport nodeTypes from './node-types.txt';\nimport playbook from './playbook.txt';\nimport bestPractices from './best-practices.txt';\nimport macros from './macros.txt';\nimport seedWorkflows from './seed-workflows.txt';\nimport dataLifecycle from './data-lifecycle.txt';\nimport assertions from './assertions.txt';\nimport apiSequences from './api-sequences.txt';\nimport cliSeeds from './cli-seeds.txt';\nimport cliApiSequences from './cli-api-sequences.txt';\n\nexport const WORKFLOW_GUIDE_CONCEPT_SECTIONS: GuideSection[] = [\n { title: 'Workflow Overview', slug: 'overview', content: overview },\n { title: 'Node Types', slug: 'node-types', content: nodeTypes },\n { title: 'Playbooks & Cache', slug: 'playbook', content: playbook },\n { title: 'Best Practices', slug: 'best-practices', content: bestPractices },\n { title: 'Macros & Variables', slug: 'macros', content: macros },\n { title: 'Seed Workflows', slug: 'seed-workflows', content: seedWorkflows },\n { title: 'Test Data Lifecycle', slug: 'data-lifecycle', content: dataLifecycle },\n { title: 'Assertions', slug: 'assertions', content: assertions },\n { title: 'API Sequences', slug: 'api-sequences', content: apiSequences },\n];\n\nexport const WORKFLOW_GUIDE_CLI_SECTIONS: GuideSection[] = [\n { title: 'CLI: Seed Workflows', slug: 'cli-seeds', content: cliSeeds },\n { title: 'CLI: API Sequences', slug: 'cli-api-sequences', content: cliApiSequences },\n];\n\nexport const WORKFLOW_GUIDE_SECTIONS: GuideSection[] = [\n ...WORKFLOW_GUIDE_CONCEPT_SECTIONS,\n ...WORKFLOW_GUIDE_CLI_SECTIONS,\n];\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,oDAAoD,aAAa;AAAA,MACjE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;A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","names":["fs","process","process","process","process","readFromStdin","process","process","process","fs","process","edges","fs","process","readFromStdin","raw","result","process","process","fs","process","process","fs","fs","process","readFromStdin","process","readJsonInput","fs","process","handleGet","fs","getAllArgValues"]}