@runcofactor/cli 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +125 -0
  2. package/dist/api-catalog-GFGCLVS4.js +401 -0
  3. package/dist/api-catalog-GFGCLVS4.js.map +1 -0
  4. package/dist/attachment-SJC7D7FY.js +276 -0
  5. package/dist/attachment-SJC7D7FY.js.map +1 -0
  6. package/dist/auth-EN6NQCJY.js +31 -0
  7. package/dist/auth-EN6NQCJY.js.map +1 -0
  8. package/dist/bin.js +7 -0
  9. package/dist/bin.js.map +1 -0
  10. package/dist/chunk-3CZU7XCS.js +272 -0
  11. package/dist/chunk-3CZU7XCS.js.map +1 -0
  12. package/dist/chunk-4NRDONSC.js +1048 -0
  13. package/dist/chunk-4NRDONSC.js.map +1 -0
  14. package/dist/chunk-4PNOV7OV.js +51980 -0
  15. package/dist/chunk-4PNOV7OV.js.map +1 -0
  16. package/dist/chunk-52IO7ACJ.js +2941 -0
  17. package/dist/chunk-52IO7ACJ.js.map +1 -0
  18. package/dist/chunk-6LEZCKKV.js +663 -0
  19. package/dist/chunk-6LEZCKKV.js.map +1 -0
  20. package/dist/chunk-A4OFTUVV.js +170 -0
  21. package/dist/chunk-A4OFTUVV.js.map +1 -0
  22. package/dist/chunk-B2VISN2V.js +2459 -0
  23. package/dist/chunk-B2VISN2V.js.map +1 -0
  24. package/dist/chunk-CLAWT7BJ.js +271 -0
  25. package/dist/chunk-CLAWT7BJ.js.map +1 -0
  26. package/dist/chunk-GKY2KXO5.js +281 -0
  27. package/dist/chunk-GKY2KXO5.js.map +1 -0
  28. package/dist/chunk-I4QLI3JO.js +413 -0
  29. package/dist/chunk-I4QLI3JO.js.map +1 -0
  30. package/dist/chunk-IMPZAX6L.js +180 -0
  31. package/dist/chunk-IMPZAX6L.js.map +1 -0
  32. package/dist/chunk-J6SH7GQT.js +241 -0
  33. package/dist/chunk-J6SH7GQT.js.map +1 -0
  34. package/dist/chunk-JDBCZ3Z2.js +298 -0
  35. package/dist/chunk-JDBCZ3Z2.js.map +1 -0
  36. package/dist/chunk-JICSYFRJ.js +46 -0
  37. package/dist/chunk-JICSYFRJ.js.map +1 -0
  38. package/dist/chunk-JWHYXEA2.js +32 -0
  39. package/dist/chunk-JWHYXEA2.js.map +1 -0
  40. package/dist/chunk-N7HFALX3.js +88 -0
  41. package/dist/chunk-N7HFALX3.js.map +1 -0
  42. package/dist/chunk-Q4BO4Z5V.js +178 -0
  43. package/dist/chunk-Q4BO4Z5V.js.map +1 -0
  44. package/dist/chunk-QFDOWABX.js +195 -0
  45. package/dist/chunk-QFDOWABX.js.map +1 -0
  46. package/dist/chunk-SJJW77WN.js +605 -0
  47. package/dist/chunk-SJJW77WN.js.map +1 -0
  48. package/dist/chunk-VKVL7WBN.js +50 -0
  49. package/dist/chunk-VKVL7WBN.js.map +1 -0
  50. package/dist/chunk-WOHL4FTB.js +353 -0
  51. package/dist/chunk-WOHL4FTB.js.map +1 -0
  52. package/dist/chunk-XQXVG7RA.js +426 -0
  53. package/dist/chunk-XQXVG7RA.js.map +1 -0
  54. package/dist/chunk-ZD3KHESI.js +94 -0
  55. package/dist/chunk-ZD3KHESI.js.map +1 -0
  56. package/dist/credential-COLTBV6D.js +450 -0
  57. package/dist/credential-COLTBV6D.js.map +1 -0
  58. package/dist/credential-template-EEPYFG7R.js +291 -0
  59. package/dist/credential-template-EEPYFG7R.js.map +1 -0
  60. package/dist/debug-workflow-KOVH5GOP.js +259 -0
  61. package/dist/debug-workflow-KOVH5GOP.js.map +1 -0
  62. package/dist/dist-44PZR7BQ.js +423 -0
  63. package/dist/dist-44PZR7BQ.js.map +1 -0
  64. package/dist/docs-3SSORHB5.js +366 -0
  65. package/dist/docs-3SSORHB5.js.map +1 -0
  66. package/dist/doctor-OTSIWV6G.js +132 -0
  67. package/dist/doctor-OTSIWV6G.js.map +1 -0
  68. package/dist/feature-flag-T2LRZME3.js +283 -0
  69. package/dist/feature-flag-T2LRZME3.js.map +1 -0
  70. package/dist/file-type-S3UUBVCT.js +4205 -0
  71. package/dist/file-type-S3UUBVCT.js.map +1 -0
  72. package/dist/index.d.ts +3 -0
  73. package/dist/index.js +982 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/init-TGWRECT2.js +208 -0
  76. package/dist/init-TGWRECT2.js.map +1 -0
  77. package/dist/install-DXSNWZKO.js +295 -0
  78. package/dist/install-DXSNWZKO.js.map +1 -0
  79. package/dist/issues-XIZOPX6T.js +564 -0
  80. package/dist/issues-XIZOPX6T.js.map +1 -0
  81. package/dist/knobs-NBINZIUB.js +295 -0
  82. package/dist/knobs-NBINZIUB.js.map +1 -0
  83. package/dist/list-3TDHK637.js +59 -0
  84. package/dist/list-3TDHK637.js.map +1 -0
  85. package/dist/local-HICVD6PU.js +100 -0
  86. package/dist/local-HICVD6PU.js.map +1 -0
  87. package/dist/login-UOIUXVUK.js +315 -0
  88. package/dist/login-UOIUXVUK.js.map +1 -0
  89. package/dist/mcp-54IJEOUA.js +1956 -0
  90. package/dist/mcp-54IJEOUA.js.map +1 -0
  91. package/dist/pdf-extract-ABWV3L5X.js +13 -0
  92. package/dist/pdf-extract-ABWV3L5X.js.map +1 -0
  93. package/dist/pdfjs-DQ2YA5S3.js +41561 -0
  94. package/dist/pdfjs-DQ2YA5S3.js.map +1 -0
  95. package/dist/property-UXLOLPTD.js +701 -0
  96. package/dist/property-UXLOLPTD.js.map +1 -0
  97. package/dist/property-skill-guide.md +189 -0
  98. package/dist/psql-BYUUNLGG.js +115 -0
  99. package/dist/psql-BYUUNLGG.js.map +1 -0
  100. package/dist/record-4TR2UIIS.js +233 -0
  101. package/dist/record-4TR2UIIS.js.map +1 -0
  102. package/dist/redis-35VBUYW7.js +116 -0
  103. package/dist/redis-35VBUYW7.js.map +1 -0
  104. package/dist/release-OOLTUBUT.js +354 -0
  105. package/dist/release-OOLTUBUT.js.map +1 -0
  106. package/dist/sandbox-XGSUU6G7.js +2046 -0
  107. package/dist/sandbox-XGSUU6G7.js.map +1 -0
  108. package/dist/scenarios-GWLJEGHA.js +280 -0
  109. package/dist/scenarios-GWLJEGHA.js.map +1 -0
  110. package/dist/session-MYFNZPRP.js +2414 -0
  111. package/dist/session-MYFNZPRP.js.map +1 -0
  112. package/dist/skill-KM34LDMO.js +1839 -0
  113. package/dist/skill-KM34LDMO.js.map +1 -0
  114. package/dist/skills/debug-run/SKILL.md +262 -0
  115. package/dist/skills/debug-run/history/1.0.0.md +244 -0
  116. package/dist/skills/debug-run/history/1.0.1.md +245 -0
  117. package/dist/skills/debug-run/history/1.0.2.md +254 -0
  118. package/dist/skills/debug-run/history/1.1.0.md +262 -0
  119. package/dist/skills/debug-run/version.json +3 -0
  120. package/dist/spec-RA3CFEKG.js +951 -0
  121. package/dist/spec-RA3CFEKG.js.map +1 -0
  122. package/dist/src-LB4HBTJQ.js +1516 -0
  123. package/dist/src-LB4HBTJQ.js.map +1 -0
  124. package/dist/src-N3TPKGTY.js +244 -0
  125. package/dist/src-N3TPKGTY.js.map +1 -0
  126. package/dist/src-UVDX5UP6.js +17 -0
  127. package/dist/src-UVDX5UP6.js.map +1 -0
  128. package/dist/start-PSEQSQA3.js +151 -0
  129. package/dist/start-PSEQSQA3.js.map +1 -0
  130. package/dist/tag-YY6YAABQ.js +22 -0
  131. package/dist/tag-YY6YAABQ.js.map +1 -0
  132. package/dist/task-IQC3YR5K.js +922 -0
  133. package/dist/task-IQC3YR5K.js.map +1 -0
  134. package/dist/test-suite-DZNJFXDW.js +394 -0
  135. package/dist/test-suite-DZNJFXDW.js.map +1 -0
  136. package/dist/trace-HXIW7U2D.js +14 -0
  137. package/dist/trace-HXIW7U2D.js.map +1 -0
  138. package/dist/triage-ORG45R5W.js +16 -0
  139. package/dist/triage-ORG45R5W.js.map +1 -0
  140. package/dist/upgrade-L2VYMP2V.js +61 -0
  141. package/dist/upgrade-L2VYMP2V.js.map +1 -0
  142. package/dist/workflow-XYFH5LTP.js +3708 -0
  143. package/dist/workflow-XYFH5LTP.js.map +1 -0
  144. package/dist/workflow-cache-NQJQFWMV.js +253 -0
  145. package/dist/workflow-cache-NQJQFWMV.js.map +1 -0
  146. package/dist/workflow-debug-BGD4UIXU.js +927 -0
  147. package/dist/workflow-debug-BGD4UIXU.js.map +1 -0
  148. package/dist/workflow-proposals-MTUDX46O.js +382 -0
  149. package/dist/workflow-proposals-MTUDX46O.js.map +1 -0
  150. package/package.json +61 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/workflow-debug.ts"],"sourcesContent":["/**\n * `canary workflow debug` — consolidated debug tool for a workflow run.\n *\n * Triangulates three signals so a human or AI agent can pinpoint what\n * happened in a run:\n *\n * 1. Visual — Playwright trace (screenshots, video)\n * 2. DOM — reconstructed snapshots of what the agent saw\n * 3. Telemetry — steps, cache, agent thoughts, Sentry logs/traces\n *\n * Subcommands are intentionally narrow so Claude/Codex can chain them:\n * overview, steps, cache, thoughts, logs, trace, playwright, trace-snapshot,\n * trace-fetch, snapshot, cache-debug, compare, bundle, variables\n *\n * Sentry-backed subcommands (`logs`, `trace`) need a `SENTRY_API_TOKEN`\n * configured on the API; without one they return an empty `partial: true`\n * payload with a reason rather than an error.\n */\n\nimport process from 'node:process';\nimport os from 'node:os';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { apiRequest } from './cli-helpers.js';\nimport { hasFlag, getArgValue } from './auth.js';\nimport { runTrace } from './trace.js';\n\ntype RunDebugStep = {\n id: string;\n nodeId: string;\n name: string | null;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n durationMs: number | null;\n cacheHitSource: string | null;\n cacheOutcome: string | null;\n cacheProcessingStatus: string | null;\n errorMessage: string | null;\n};\n\ntype RunDebugPayload = {\n run: {\n id: string;\n workflowId: string;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n durationMs: number | null;\n errorMessage: string | null;\n traceStorageKey: string | null;\n };\n steps: RunDebugStep[];\n cache: {\n hitRate: number;\n hitCount: number;\n missCount: number;\n bySource: Record<string, number>;\n misses: Array<{ stepId: string; reason: string }>;\n };\n thoughts: { count: number; byStepId: Record<string, number> };\n playwright: { viewerUrl: string | null; traceStorageKey: string | null };\n sentry: { logsAvailable: boolean; tracesAvailable: boolean };\n diagnosis: {\n slowestSteps: Array<{ stepId: string; name: string | null; durationMs: number }>;\n failedSteps: Array<{ stepId: string; name: string | null; errorMessage: string | null }>;\n cacheMissHotspots: Array<{ stepId: string; reason: string }>;\n };\n};\n\ntype OkEnvelope<T> = { ok: true; data: T };\ntype ErrEnvelope = { ok: false; error?: string };\ntype Envelope<T> = OkEnvelope<T> | ErrEnvelope;\n\nfunction printDebugHelp(): void {\n console.log(\n [\n 'Usage: canary workflow debug <sub-command> [options]',\n '',\n 'Triangulate three signals to debug a workflow run:',\n ' 1. Visual — what happened on screen? → debug playwright <runId>',\n ' 2. DOM — what did the agent see? → debug trace-snapshot <runId>',\n ' 3. Telemetry — what did we record? → debug steps | cache | thoughts | logs',\n '',\n 'Start with: canary workflow debug <runId> # diagnosis + pointers',\n 'Then drill in with the subcommand matching your question:',\n ' \"Where did we miss the cache?\" → debug cache --misses-only',\n ' \"What steps were slow?\" → debug steps --slow',\n ' \"Why did the agent click X?\" → debug thoughts --step <stepId>',\n ' \"What was on the page?\" → debug trace-snapshot <runId>',\n ' \"What errors did we log?\" → debug logs --level error',\n ' \"What variables did we have?\" → debug variables <runId>',\n ' \"What changed since it worked?\" → debug compare <oldRun> <newRun>',\n ' \"Give me everything for a run\" → debug bundle <runId> --out <dir>',\n '',\n 'Sub-commands:',\n ' overview <runId> Diagnosis summary (default when no sub given)',\n ' steps <runId> [--slow] [--json] Step timings + status',\n ' cache <runId> [--misses-only] [--json] Cache hit/miss breakdown',\n ' thoughts <runId> [--step <id>] [--grep <text>] [--json]',\n ' Agent reasoning for this run',\n ' navigation <runId> [--transitions-only] [--json]',\n ' Timestamped browser-URL history + cross-host transitions',\n ' logs <runId> [--step <id>] [--level info|warning|error] [--json]',\n ' Sentry logs for this run',\n ' trace <runId> [--step <id>] [--json] Sentry span tree',\n ' playwright <runId> [--open] [--json] Playwright trace viewer URL',\n ' trace-fetch <runId> [--out <path>] [--json]',\n ' Download trace.zip to disk',\n ' trace-snapshot <runId> [--action <index>] [--output-dir <path>] [--screenshots] [--html]',\n ' Download Playwright trace + reconstruct DOM snapshots',\n ' snapshot <runId> [--out <path>] [--json] Workflow definition that ran (published or draft)',\n ' cache-debug <runId> [--step <id>] [--json]',\n ' Per-step cache compilation + replay details',\n ' variables <runId> [--name <var>] [--json]',\n ' Run-input + captured variables with definition timestamps',\n ' compare <runIdA> <runIdB> [--out <dir>] [--json]',\n ' Diff two runs (steps, thoughts, cache, snapshot)',\n ' bundle <runId> --out <dir> Pull all debug artifacts into one directory',\n ' materialize <runId> [--out <dir>] [--json]',\n ' Materialize the canonical diagnostic workspace (same shape',\n ' the v2 failure-diagnostic agent uses). Start with `summary.md`.',\n '',\n 'Options:',\n ' --workflow <id> Workflow ID (auto-resolved from runId if omitted)',\n ' --json Raw JSON output',\n ' --env <env> Target environment (prod, dev, local)',\n ].join('\\n')\n );\n}\n\nexport async function handleWorkflowDebug(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const [maybeSub, ...rest] = argv;\n\n if (!maybeSub || maybeSub === 'help' || hasFlag(argv, '--help', '-h')) {\n printDebugHelp();\n return;\n }\n\n // Bare form: `canary workflow debug <runId>` → overview\n if (looksLikeRunId(maybeSub)) {\n await handleOverview([maybeSub, ...rest], apiUrl, token);\n return;\n }\n\n switch (maybeSub) {\n case 'overview':\n await handleOverview(rest, apiUrl, token);\n return;\n case 'steps':\n await handleSteps(rest, apiUrl, token);\n return;\n case 'cache':\n await handleCache(rest, apiUrl, token);\n return;\n case 'thoughts':\n await handleThoughts(rest, apiUrl, token);\n return;\n case 'navigation':\n await handleNavigation(rest, apiUrl, token);\n return;\n case 'logs':\n await handleLogs(rest, apiUrl, token);\n return;\n case 'trace':\n await handleSentryTrace(rest, apiUrl, token);\n return;\n case 'playwright':\n await handlePlaywright(rest, apiUrl, token);\n return;\n case 'trace-snapshot':\n await handleTraceSnapshot(rest, apiUrl, token);\n return;\n case 'trace-fetch':\n await handleTraceFetch(rest, apiUrl, token);\n return;\n case 'snapshot':\n await handleSnapshot(rest, apiUrl, token);\n return;\n case 'cache-debug':\n await handleCacheDebug(rest, apiUrl, token);\n return;\n case 'variables':\n await handleVariables(rest, apiUrl, token);\n return;\n case 'compare':\n await handleCompare(rest, apiUrl, token);\n return;\n case 'bundle':\n await handleBundle(rest, apiUrl, token);\n return;\n case 'materialize':\n await handleMaterialize(rest, apiUrl, token);\n return;\n default:\n console.error(`Unknown debug sub-command: ${maybeSub}`);\n printDebugHelp();\n process.exit(1);\n }\n}\n\nfunction looksLikeRunId(s: string): boolean {\n // Uuid-ish or prefixed id. Just avoid matching bare sub-commands.\n return !!s && !s.startsWith('-') && s.length >= 8 && !/^[a-z-]+$/i.test(s.slice(0, 8));\n}\n\nfunction requireRunId(argv: string[]): string {\n const runId = argv.find((a) => !a.startsWith('-'));\n if (!runId) {\n console.error('Error: <runId> is required');\n process.exit(1);\n }\n return runId;\n}\n\nasync function resolveWorkflowId(\n argv: string[],\n runId: string,\n apiUrl: string,\n token: string\n): Promise<string> {\n const explicit = getArgValue(argv, '--workflow');\n if (explicit) return explicit;\n const res = await apiRequest<{\n ok: boolean;\n error?: string;\n data?: { runId: string; workflowId: string };\n }>(apiUrl, token, 'GET', `/workflows/runs/${encodeURIComponent(runId)}/lookup`);\n if (res.ok && res.data?.workflowId) return res.data.workflowId;\n console.error(\n `Error: could not resolve workflowId from runId (${res.error ?? 'unknown error'}).`\n );\n console.error(\n ` Pass --workflow <workflowId> explicitly, or run: canary workflow runs list <workflowId>`\n );\n process.exit(1);\n return '';\n}\n\nasync function fetchDebug(\n apiUrl: string,\n token: string,\n workflowId: string,\n runId: string,\n subpath = ''\n): Promise<Envelope<unknown>> {\n return apiRequest<Envelope<unknown> & { ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/debug${subpath}`\n );\n}\n\nfunction fmtMs(ms: number | null): string {\n if (ms === null) return '—';\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\nasync function handleOverview(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = (await fetchDebug(apiUrl, token, workflowId, runId)) as Envelope<RunDebugPayload>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n const d = res.data;\n console.log(`Run ${d.run.id.slice(0, 8)} · ${d.run.status} · ${fmtMs(d.run.durationMs)}`);\n if (d.run.errorMessage) console.log(` error: ${d.run.errorMessage}`);\n console.log(\n ` cache: ${Math.round(d.cache.hitRate * 100)}% hit (${d.cache.hitCount}/${d.cache.hitCount + d.cache.missCount})`\n );\n console.log(` thoughts: ${d.thoughts.count} recorded`);\n console.log(\n ` playwright trace: ${d.playwright.traceStorageKey ? 'available' : 'not captured'}`\n );\n\n if (d.diagnosis.failedSteps.length > 0) {\n console.log('\\nFailed steps:');\n for (const s of d.diagnosis.failedSteps) {\n console.log(` ✗ ${s.name ?? s.stepId.slice(0, 8)} ${s.errorMessage ?? ''}`);\n }\n }\n if (d.diagnosis.slowestSteps.length > 0) {\n console.log('\\nSlowest steps:');\n for (const s of d.diagnosis.slowestSteps) {\n console.log(` · ${s.name ?? s.stepId.slice(0, 8)} ${fmtMs(s.durationMs)}`);\n }\n }\n if (d.diagnosis.cacheMissHotspots.length > 0) {\n console.log('\\nCache miss hotspots:');\n for (const s of d.diagnosis.cacheMissHotspots) {\n console.log(` · ${s.stepId.slice(0, 8)} ${s.reason}`);\n }\n }\n\n console.log('\\nNext:');\n console.log(\n ` canary workflow debug steps ${runId} --slow # timings`\n );\n console.log(\n ` canary workflow debug cache ${runId} --misses-only # cache diagnosis`\n );\n console.log(\n ` canary workflow debug thoughts ${runId} --step <id> # agent reasoning`\n );\n console.log(\n ` canary workflow debug trace-snapshot ${runId} # DOM the agent saw`\n );\n}\n\nasync function handleSteps(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = (await fetchDebug(apiUrl, token, workflowId, runId, '/steps')) as Envelope<{\n steps: RunDebugStep[];\n }>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n const steps = [...res.data.steps];\n if (hasFlag(argv, '--slow')) {\n steps.sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0));\n }\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(steps, null, 2));\n return;\n }\n console.log('STEP STATUS DURATION CACHE');\n for (const s of steps) {\n const name = (s.name ?? s.id.slice(0, 8)).padEnd(28).slice(0, 28);\n const status = s.status.padEnd(10);\n const dur = fmtMs(s.durationMs).padEnd(10);\n const cache = s.cacheHitSource ?? (s.cacheOutcome ?? '—');\n console.log(`${name} ${status} ${dur} ${cache}`);\n if (s.errorMessage) console.log(` ↳ ${s.errorMessage}`);\n }\n}\n\ntype NavigationEntry = {\n timestampMs: number;\n isoTimestamp: string | null;\n url: string;\n hostname: string | null;\n success: boolean;\n};\n\ntype NavigationTransition = {\n fromIndex: number;\n toIndex: number;\n fromHostname: string | null;\n toHostname: string | null;\n fromUrl: string;\n toUrl: string;\n timestampMs: number;\n};\n\ntype NavigationPayload = {\n startTimestamp: string | null;\n entries: NavigationEntry[];\n transitions: NavigationTransition[];\n};\n\nasync function handleNavigation(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = (await fetchDebug(\n apiUrl,\n token,\n workflowId,\n runId,\n '/navigation'\n )) as Envelope<NavigationPayload>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n\n const transitionsOnly = hasFlag(argv, '--transitions-only');\n const payload = res.data;\n\n if (hasFlag(argv, '--json')) {\n console.log(\n JSON.stringify(\n transitionsOnly\n ? { startTimestamp: payload.startTimestamp, transitions: payload.transitions }\n : payload,\n null,\n 2\n )\n );\n return;\n }\n\n if (payload.entries.length === 0) {\n console.log('No navigation events recorded for this run.');\n return;\n }\n\n if (payload.transitions.length > 0) {\n console.log(\n `⚠ ${payload.transitions.length} cross-host transition${payload.transitions.length === 1 ? '' : 's'}:`\n );\n for (const t of payload.transitions) {\n console.log(\n ` ${formatRelMs(t.timestampMs)} ${t.fromHostname} → ${t.toHostname}`\n );\n }\n console.log('');\n }\n\n if (transitionsOnly) return;\n\n const transitionTo = new Set(payload.transitions.map((t) => t.toIndex));\n console.log('TIME HOSTNAME URL');\n payload.entries.forEach((e, idx) => {\n const time = formatRelMs(e.timestampMs).padEnd(12);\n const host = (e.hostname ?? '—').padEnd(25).slice(0, 25);\n const marker = transitionTo.has(idx) ? '→' : ' ';\n console.log(`${time} ${marker} ${host} ${e.url}`);\n });\n}\n\nfunction formatRelMs(ms: number): string {\n if (ms < 0) ms = 0;\n const totalSeconds = Math.floor(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n const millis = ms % 1000;\n return `${minutes}:${String(seconds).padStart(2, '0')}.${String(millis).padStart(3, '0')}`;\n}\n\nasync function handleCache(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = (await fetchDebug(apiUrl, token, workflowId, runId)) as Envelope<RunDebugPayload>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n const { cache, steps } = res.data;\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(cache, null, 2));\n return;\n }\n console.log(\n `Cache hit rate: ${Math.round(cache.hitRate * 100)}% (${cache.hitCount} hit, ${cache.missCount} miss)`\n );\n if (Object.keys(cache.bySource).length > 0) {\n console.log('By source:');\n for (const [src, n] of Object.entries(cache.bySource)) {\n console.log(` ${src.padEnd(16)} ${n}`);\n }\n }\n const stepById = new Map(steps.map((s) => [s.id, s]));\n if (!hasFlag(argv, '--misses-only')) {\n console.log('\\nHits:');\n for (const s of steps.filter((x) => x.cacheHitSource)) {\n console.log(` ✓ ${(s.name ?? s.id.slice(0, 8)).padEnd(28)} ${s.cacheHitSource}`);\n }\n }\n if (cache.misses.length > 0) {\n console.log('\\nMisses:');\n for (const m of cache.misses) {\n const s = stepById.get(m.stepId);\n console.log(` ✗ ${(s?.name ?? m.stepId.slice(0, 8)).padEnd(28)} ${m.reason}`);\n }\n }\n}\n\nasync function handleThoughts(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const stepId = getArgValue(argv, '--step');\n const grep = getArgValue(argv, '--grep');\n const qs = stepId ? `?step=${encodeURIComponent(stepId)}` : '';\n const res = (await fetchDebug(\n apiUrl,\n token,\n workflowId,\n runId,\n `/thoughts${qs}`\n )) as Envelope<{\n thoughts: Array<{\n id: string;\n stepId: string | null;\n toolName: string | null;\n content: string;\n orderIndex: number;\n createdAt: string;\n }>;\n }>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n const totalThoughts = res.data.thoughts.length;\n let thoughts = res.data.thoughts;\n if (grep) {\n const needle = grep.toLowerCase();\n thoughts = thoughts.filter((t) => t.content.toLowerCase().includes(needle));\n }\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(thoughts, null, 2));\n return;\n }\n for (const t of thoughts) {\n const tag = t.toolName ? `[${t.toolName}] ` : '';\n const step = t.stepId ? `step ${t.stepId.slice(0, 8)} ` : '';\n console.log(`${step}${tag}${t.content}`);\n console.log('');\n }\n if (thoughts.length === 0) {\n if (totalThoughts === 0) {\n const scope = stepId ? ` for step ${stepId.slice(0, 8)}` : '';\n console.log(`(no thoughts recorded${scope})`);\n } else if (grep) {\n console.log(\n `(no thoughts matched --grep \"${grep}\"; ${totalThoughts} total thought${totalThoughts === 1 ? '' : 's'} in scope)`\n );\n } else {\n console.log('(no thoughts to display)');\n }\n }\n}\n\nasync function handleLogs(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const level = getArgValue(argv, '--level');\n const stepId = getArgValue(argv, '--step');\n const params = new URLSearchParams();\n if (level) params.set('level', level);\n if (stepId) params.set('step', stepId);\n const qs = params.toString() ? `?${params.toString()}` : '';\n const res = (await fetchDebug(apiUrl, token, workflowId, runId, `/logs${qs}`)) as Envelope<{\n rows: Array<{ timestamp: string; level: string; message: string }>;\n partial: boolean;\n reason: string | null;\n }>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n if (res.data.partial) {\n console.log(`(partial result: ${res.data.reason ?? 'unknown'})`);\n }\n for (const row of res.data.rows) {\n console.log(`${row.timestamp} ${row.level.padEnd(8)} ${row.message}`);\n }\n if (res.data.rows.length === 0 && !res.data.partial) {\n console.log('(no logs)');\n }\n}\n\nasync function handleSentryTrace(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const stepId = getArgValue(argv, '--step');\n const qs = stepId ? `?step=${encodeURIComponent(stepId)}` : '';\n const res = (await fetchDebug(\n apiUrl,\n token,\n workflowId,\n runId,\n `/sentry-trace${qs}`\n )) as Envelope<{\n traceId: string | null;\n spans: Array<{\n spanId: string;\n parentSpanId: string | null;\n op: string | null;\n description: string | null;\n durationMs: number | null;\n }>;\n partial: boolean;\n reason: string | null;\n }>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n if (res.data.partial) {\n console.log(`(partial result: ${res.data.reason ?? 'unknown'})`);\n }\n if (res.data.traceId) console.log(`trace ${res.data.traceId}`);\n for (const span of res.data.spans) {\n const op = (span.op ?? 'span').padEnd(22);\n const desc = (span.description ?? '').padEnd(40);\n const dur = span.durationMs !== null ? `${span.durationMs}ms` : '';\n console.log(` ${op} ${desc} ${dur}`);\n }\n if (res.data.spans.length === 0 && !res.data.partial) {\n console.log('(no spans)');\n }\n}\n\nasync function handlePlaywright(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = (await fetchDebug(apiUrl, token, workflowId, runId, '/trace')) as Envelope<{\n viewerUrl: string;\n signedUrl: string;\n storageKey: string;\n }>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n console.log(res.data.viewerUrl);\n if (hasFlag(argv, '--open')) {\n const opener =\n process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';\n const { spawn } = await import('node:child_process');\n spawn(opener, [res.data.viewerUrl], { detached: true, stdio: 'ignore' }).unref();\n }\n}\n\nasync function handleTraceSnapshot(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const runId = requireRunId(argv);\n if (getArgValue(argv, '--step')) {\n console.error(\n 'Error: trace-snapshot --step is not supported by the local trace reconstructor. Use --action <0-based trace action index> or omit filtering.'\n );\n process.exit(1);\n }\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = (await fetchDebug(apiUrl, token, workflowId, runId, '/trace')) as Envelope<{\n signedUrl: string;\n storageKey: string;\n }>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n\n // Download into a stable temp path so `canary trace snapshot` can open it.\n const tmp = await fs.mkdtemp(path.join(os.tmpdir(), `canary-trace-${runId}-`));\n const traceFile = path.join(tmp, 'trace.zip');\n const download = await fetch(res.data.signedUrl);\n if (!download.ok) {\n console.error(`Failed to download trace: HTTP ${download.status}`);\n process.exit(1);\n }\n const buf = Buffer.from(await download.arrayBuffer());\n await fs.writeFile(traceFile, buf);\n\n const forwarded: string[] = ['snapshot', traceFile];\n for (const flag of ['--output-dir', '--filter', '--action']) {\n const v = getArgValue(argv, flag);\n if (v !== undefined) forwarded.push(flag, v);\n }\n if (hasFlag(argv, '--screenshots')) forwarded.push('--screenshots');\n if (hasFlag(argv, '--html')) forwarded.push('--html');\n\n await runTrace(forwarded);\n}\n\n/**\n * `trace-fetch` — download the raw `trace.zip` to a chosen path.\n *\n * Distinct from `playwright` (prints/opens viewer URL) and `trace-snapshot`\n * (downloads to a tmp dir and pipes into `canary trace snapshot`). Use this\n * when you just want the file on disk for `unzip`, vendoring into a ticket,\n * or feeding to another tool.\n */\nasync function handleTraceFetch(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = (await fetchDebug(apiUrl, token, workflowId, runId, '/trace')) as Envelope<{\n signedUrl: string;\n storageKey: string;\n }>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n const out = getArgValue(argv, '--out') ?? `./trace-${runId}.zip`;\n const download = await fetch(res.data.signedUrl);\n if (!download.ok) {\n console.error(`Failed to download trace: HTTP ${download.status}`);\n process.exit(1);\n }\n const buf = Buffer.from(await download.arrayBuffer());\n await fs.writeFile(out, buf);\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify({ path: out, storageKey: res.data.storageKey }, null, 2));\n return;\n }\n console.log(out);\n}\n\ntype RunDetailResponse = {\n ok?: boolean;\n error?: string;\n run?: {\n id: string;\n workflowId: string;\n snapshotVersion: number | null;\n draftSnapshot: { id: string; version: string; basePublishedVersion: number } | null;\n };\n};\n\nasync function fetchRunDetail(\n apiUrl: string,\n token: string,\n workflowId: string,\n runId: string\n): Promise<RunDetailResponse['run']> {\n const res = await apiRequest<RunDetailResponse & { ok: boolean }>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}`\n );\n if (!res.run) {\n console.error(`Failed to load run: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n return res.run;\n}\n\n/**\n * `snapshot` — fetch the workflow definition that ran for this runId.\n *\n * Resolves to either a published snapshot (`snapshotVersion`) or a draft\n * snapshot (`draftSnapshotId.version`) by looking at the run record, then\n * fetches the corresponding `snapshotJson`. Useful for \"what was the workflow\n * when this ran?\" and as the input to `diff` for two runs.\n */\nasync function handleSnapshot(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const run = await fetchRunDetail(apiUrl, token, workflowId, runId);\n if (!run) return;\n\n let snapshotPath: string;\n let kind: 'published' | 'draft';\n if (run.draftSnapshot) {\n snapshotPath = `/workflows/${encodeURIComponent(workflowId)}/draft-snapshots/${encodeURIComponent(run.draftSnapshot.version)}`;\n kind = 'draft';\n } else if (run.snapshotVersion !== null && run.snapshotVersion !== undefined) {\n snapshotPath = `/workflows/${encodeURIComponent(workflowId)}/snapshots/${run.snapshotVersion}`;\n kind = 'published';\n } else {\n console.error('Run has no snapshotVersion or draftSnapshotId — cannot resolve definition.');\n process.exit(1);\n }\n\n const snap = await apiRequest<{ ok: boolean; error?: string; snapshot?: { snapshotJson: unknown; version: number | string; name?: string | null } }>(\n apiUrl,\n token,\n 'GET',\n snapshotPath\n );\n if (!snap.snapshot) {\n console.error(`Failed to load snapshot: ${snap.error ?? 'unknown error'}`);\n process.exit(1);\n }\n\n const out = getArgValue(argv, '--out');\n const text = JSON.stringify(snap.snapshot.snapshotJson, null, 2);\n if (out) {\n await fs.writeFile(out, text);\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify({ path: out, kind, version: snap.snapshot.version }, null, 2));\n } else {\n console.log(`${kind} snapshot v${snap.snapshot.version} → ${out}`);\n }\n return;\n }\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify({ kind, version: snap.snapshot.version, snapshotJson: snap.snapshot.snapshotJson }, null, 2));\n return;\n }\n console.log(text);\n}\n\ntype VariablesPayload = {\n inputs: Array<{\n name: string;\n value: string;\n definedAt: string;\n source: 'run-input';\n }>;\n captures: Array<{\n name: string;\n value: string;\n definedAt: string;\n source: 'capture';\n stepId: string;\n nodeId: string;\n nodeName: string | null;\n }>;\n};\n\n/**\n * `variables` — list run-time variables and where each one was defined.\n *\n * Two sections: workflow-level inputs (defined at run start) and per-step\n * captures (defined when the agent's saveAs directive fires). Use this to\n * answer \"what was {{var}} when this ran, and which step set it?\"\n */\nasync function handleVariables(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = (await fetchDebug(apiUrl, token, workflowId, runId, '/variables')) as Envelope<VariablesPayload>;\n if (!res.ok) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n const filter = getArgValue(argv, '--name');\n const data: VariablesPayload = filter\n ? {\n inputs: res.data.inputs.filter((v) => v.name === filter),\n captures: res.data.captures.filter((v) => v.name === filter),\n }\n : res.data;\n\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(data, null, 2));\n return;\n }\n\n const fmtValue = (v: string) => (v.length > 80 ? `${v.slice(0, 77)}...` : v);\n\n console.log(`Run inputs (${data.inputs.length})`);\n if (data.inputs.length === 0) {\n console.log(' (none)');\n } else {\n for (const v of data.inputs) {\n console.log(` ${v.name} = ${fmtValue(v.value)} [defined ${v.definedAt}]`);\n }\n }\n\n console.log('');\n console.log(`Captures (${data.captures.length})`);\n if (data.captures.length === 0) {\n console.log(' (none)');\n } else {\n for (const v of data.captures) {\n const where = v.nodeName ? `${v.nodeName} (${v.stepId})` : v.stepId;\n console.log(` ${v.name} = ${fmtValue(v.value)} [${v.definedAt} · ${where}]`);\n }\n }\n}\n\ntype CacheDebugResponse = {\n ok?: boolean;\n error?: string;\n cache?: unknown;\n steps?: Array<Record<string, unknown>>;\n debugSnapshots?: unknown[];\n};\ntype CacheDebugEnvelope = CacheDebugResponse & { ok: boolean; data?: CacheDebugResponse };\n\n/**\n * `cache-debug` — wrap the cache-debug endpoint.\n *\n * Exposes per-step cache compilation, attempted selectors, resolution results,\n * and a11y snapshots from `workflow_cache_debug_snapshots`. This is the data\n * that powers the cache outcomes tab in the web debug view.\n */\nasync function handleCacheDebug(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const res = await apiRequest<CacheDebugEnvelope>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/cache-debug`\n );\n if (res.ok === false) {\n console.error(`Failed: ${res.error ?? 'unknown error'}`);\n process.exit(1);\n }\n const stepFilter = getArgValue(argv, '--step');\n const payload = res.data ?? res;\n const data: CacheDebugResponse = stepFilter\n ? {\n ...payload,\n steps: (payload.steps ?? []).filter(\n (s) => s['stepId'] === stepFilter || s['nodeId'] === stepFilter\n ),\n }\n : payload;\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify(data, null, 2));\n return;\n }\n console.log(JSON.stringify(data, null, 2));\n}\n\ntype StepLite = { id: string; nodeId: string; name: string | null; status: string; durationMs: number | null; cacheHitSource: string | null; cacheOutcome: string | null; errorMessage: string | null };\ntype ThoughtLite = { id: string; stepId: string | null; content: string; toolName: string | null; orderIndex: number };\ntype RunBundle = {\n runId: string;\n overview: RunDebugPayload;\n steps: StepLite[];\n thoughts: ThoughtLite[];\n};\n\nasync function loadRunBundle(apiUrl: string, token: string, workflowId: string, runId: string): Promise<RunBundle> {\n const overview = (await fetchDebug(apiUrl, token, workflowId, runId)) as Envelope<RunDebugPayload>;\n if (!overview.ok) {\n console.error(`Failed to load run ${runId}: ${overview.error ?? 'unknown error'}`);\n process.exit(1);\n }\n const stepsRes = (await fetchDebug(apiUrl, token, workflowId, runId, '/steps')) as Envelope<{ steps: StepLite[] }>;\n const thoughtsRes = (await fetchDebug(apiUrl, token, workflowId, runId, '/thoughts')) as Envelope<{ thoughts: ThoughtLite[] }>;\n return {\n runId,\n overview: overview.data,\n steps: stepsRes.ok ? stepsRes.data.steps : [],\n thoughts: thoughtsRes.ok ? thoughtsRes.data.thoughts : [],\n };\n}\n\n/**\n * `compare` — structural diff between two runs.\n *\n * Aligns steps by nodeId; reports status/duration/cacheHitSource flips and\n * thought additions at diverging steps. Output is a JSON document the skill\n * can read and reason over (no LLM summarization in the CLI itself). With\n * `--out`, also pulls `trace.zip` and the snapshot JSON for both runs into\n * `<dir>/runA/` and `<dir>/runB/` for offline visual inspection.\n */\nasync function handleCompare(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n if (positional.length < 2) {\n console.error('Usage: canary workflow debug compare <runIdA> <runIdB> [--workflow <id>] [--out <dir>] [--json]');\n process.exit(1);\n }\n const [runA, runB] = positional;\n const workflowId = await resolveWorkflowId(argv, runA, apiUrl, token);\n\n const [a, b] = await Promise.all([\n loadRunBundle(apiUrl, token, workflowId, runA),\n loadRunBundle(apiUrl, token, workflowId, runB),\n ]);\n\n const stepsByNode = (steps: StepLite[]) => {\n const m = new Map<string, StepLite>();\n for (const s of steps) m.set(s.nodeId, s);\n return m;\n };\n const aMap = stepsByNode(a.steps);\n const bMap = stepsByNode(b.steps);\n const allNodes = new Set([...aMap.keys(), ...bMap.keys()]);\n\n const stepDiffs: Array<{\n nodeId: string;\n name: string | null;\n statusA: string | null;\n statusB: string | null;\n durationA: number | null;\n durationB: number | null;\n durationDeltaPct: number | null;\n cacheA: string | null;\n cacheB: string | null;\n flipped: string[];\n }> = [];\n\n for (const nodeId of allNodes) {\n const sa = aMap.get(nodeId) ?? null;\n const sb = bMap.get(nodeId) ?? null;\n const flipped: string[] = [];\n if ((sa?.status ?? null) !== (sb?.status ?? null)) flipped.push('status');\n if ((sa?.cacheHitSource ?? null) !== (sb?.cacheHitSource ?? null)) flipped.push('cache');\n const durA = sa?.durationMs ?? null;\n const durB = sb?.durationMs ?? null;\n let durationDeltaPct: number | null = null;\n if (durA !== null && durB !== null && durA > 0) {\n durationDeltaPct = Math.round(((durB - durA) / durA) * 100);\n if (Math.abs(durationDeltaPct) >= 100) flipped.push('duration');\n }\n if (flipped.length > 0 || !sa || !sb) {\n stepDiffs.push({\n nodeId,\n name: sa?.name ?? sb?.name ?? null,\n statusA: sa?.status ?? null,\n statusB: sb?.status ?? null,\n durationA: durA,\n durationB: durB,\n durationDeltaPct,\n cacheA: sa?.cacheHitSource ?? null,\n cacheB: sb?.cacheHitSource ?? null,\n flipped: !sa ? ['only-in-B'] : !sb ? ['only-in-A'] : flipped,\n });\n }\n }\n\n // Thought delta at diverging nodes\n const thoughtsByStep = (bundle: RunBundle) => {\n const m = new Map<string, ThoughtLite[]>();\n for (const t of bundle.thoughts) {\n const key = t.stepId ?? '';\n const arr = m.get(key) ?? [];\n arr.push(t);\n m.set(key, arr);\n }\n return m;\n };\n const aThoughts = thoughtsByStep(a);\n const bThoughts = thoughtsByStep(b);\n const thoughtDeltas = stepDiffs.map((d) => {\n const sa = aMap.get(d.nodeId);\n const sb = bMap.get(d.nodeId);\n return {\n nodeId: d.nodeId,\n thoughtsA: sa ? (aThoughts.get(sa.id)?.map((t) => t.content) ?? []) : [],\n thoughtsB: sb ? (bThoughts.get(sb.id)?.map((t) => t.content) ?? []) : [],\n };\n });\n\n const result = {\n runA,\n runB,\n workflowId,\n cacheHitRateDelta: b.overview.cache.hitRate - a.overview.cache.hitRate,\n statusA: a.overview.run.status,\n statusB: b.overview.run.status,\n durationA: a.overview.run.durationMs,\n durationB: b.overview.run.durationMs,\n stepDiffs,\n thoughtDeltas,\n };\n\n const outDir = getArgValue(argv, '--out');\n if (outDir) {\n await fs.mkdir(outDir, { recursive: true });\n await fs.writeFile(path.join(outDir, 'compare.json'), JSON.stringify(result, null, 2));\n for (const [label, runId] of [['runA', runA], ['runB', runB]] as const) {\n const sub = path.join(outDir, label);\n await fs.mkdir(sub, { recursive: true });\n await tryWriteSnapshot(apiUrl, token, workflowId, runId, path.join(sub, 'snapshot.json'));\n await tryWriteTrace(apiUrl, token, workflowId, runId, path.join(sub, 'trace.zip'));\n }\n if (!hasFlag(argv, '--json')) console.log(`Wrote compare bundle to ${outDir}`);\n }\n\n if (hasFlag(argv, '--json') || !outDir) {\n console.log(JSON.stringify(result, null, 2));\n }\n}\n\nasync function tryWriteTrace(\n apiUrl: string,\n token: string,\n workflowId: string,\n runId: string,\n outPath: string\n): Promise<void> {\n const res = (await fetchDebug(apiUrl, token, workflowId, runId, '/trace')) as Envelope<{\n signedUrl: string;\n }>;\n if (!res.ok) return;\n const dl = await fetch(res.data.signedUrl);\n if (!dl.ok) return;\n await fs.writeFile(outPath, Buffer.from(await dl.arrayBuffer()));\n}\n\nasync function tryWriteSnapshot(\n apiUrl: string,\n token: string,\n workflowId: string,\n runId: string,\n outPath: string\n): Promise<void> {\n const run = await fetchRunDetail(apiUrl, token, workflowId, runId);\n if (!run) return;\n const snapPath = run.draftSnapshot\n ? `/workflows/${encodeURIComponent(workflowId)}/draft-snapshots/${encodeURIComponent(run.draftSnapshot.version)}`\n : run.snapshotVersion !== null && run.snapshotVersion !== undefined\n ? `/workflows/${encodeURIComponent(workflowId)}/snapshots/${run.snapshotVersion}`\n : null;\n if (!snapPath) return;\n const snap = await apiRequest<{ ok: boolean; snapshot?: { snapshotJson: unknown } }>(\n apiUrl,\n token,\n 'GET',\n snapPath\n );\n if (!snap.snapshot) return;\n await fs.writeFile(outPath, JSON.stringify(snap.snapshot.snapshotJson, null, 2));\n}\n\n/**\n * `bundle` — pull every artifact for a run into one directory.\n *\n * Writes overview/steps/cache/thoughts/variables JSON, snapshot JSON, and\n * trace.zip. Logs/sentry-trace are best-effort (skipped if SENTRY_API_TOKEN\n * is not configured on the API). Produces a `bundle.json` manifest. Designed\n * for offline triage and ticket attachments.\n */\nasync function handleBundle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const outDir = getArgValue(argv, '--out');\n if (!outDir) {\n console.error('Error: --out <dir> is required');\n process.exit(1);\n }\n await fs.mkdir(outDir, { recursive: true });\n\n const manifest: Array<{ file: string; source: string; ok: boolean; error?: string }> = [];\n\n const writeJson = async (file: string, source: string, fetcher: () => Promise<unknown>) => {\n try {\n const data = await fetcher();\n await fs.writeFile(path.join(outDir, file), JSON.stringify(data, null, 2));\n manifest.push({ file, source, ok: true });\n } catch (err) {\n manifest.push({ file, source, ok: false, error: String(err) });\n }\n };\n\n await writeJson('overview.json', `GET /workflows/${workflowId}/runs/${runId}/debug`, async () => {\n const r = (await fetchDebug(apiUrl, token, workflowId, runId)) as Envelope<unknown>;\n if (!r.ok) throw new Error(r.error ?? 'failed');\n return r.data;\n });\n await writeJson('steps.json', `/debug/steps`, async () => {\n const r = (await fetchDebug(apiUrl, token, workflowId, runId, '/steps')) as Envelope<unknown>;\n if (!r.ok) throw new Error(r.error ?? 'failed');\n return r.data;\n });\n await writeJson('thoughts.json', `/debug/thoughts`, async () => {\n const r = (await fetchDebug(apiUrl, token, workflowId, runId, '/thoughts')) as Envelope<unknown>;\n if (!r.ok) throw new Error(r.error ?? 'failed');\n return r.data;\n });\n await writeJson('cache-debug.json', `/cache-debug`, async () => {\n const r = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/cache-debug`\n );\n if (r.ok === false) throw new Error(r.error ?? 'failed');\n return r;\n });\n await writeJson('logs.json', `/debug/logs`, async () => {\n const r = (await fetchDebug(apiUrl, token, workflowId, runId, '/logs')) as Envelope<unknown>;\n if (!r.ok) throw new Error(r.error ?? 'failed');\n return r.data;\n });\n await writeJson('sentry-trace.json', `/debug/sentry-trace`, async () => {\n const r = (await fetchDebug(apiUrl, token, workflowId, runId, '/sentry-trace')) as Envelope<unknown>;\n if (!r.ok) throw new Error(r.error ?? 'failed');\n return r.data;\n });\n await writeJson('variables.json', `/debug/variables`, async () => {\n const r = (await fetchDebug(apiUrl, token, workflowId, runId, '/variables')) as Envelope<unknown>;\n if (!r.ok) throw new Error(r.error ?? 'failed');\n return r.data;\n });\n\n // Snapshot JSON\n try {\n await tryWriteSnapshot(apiUrl, token, workflowId, runId, path.join(outDir, 'snapshot.json'));\n manifest.push({ file: 'snapshot.json', source: 'snapshots/:version', ok: true });\n } catch (err) {\n manifest.push({ file: 'snapshot.json', source: 'snapshots/:version', ok: false, error: String(err) });\n }\n\n // trace.zip\n try {\n await tryWriteTrace(apiUrl, token, workflowId, runId, path.join(outDir, 'trace.zip'));\n manifest.push({ file: 'trace.zip', source: '/debug/trace', ok: true });\n } catch (err) {\n manifest.push({ file: 'trace.zip', source: '/debug/trace', ok: false, error: String(err) });\n }\n\n await fs.writeFile(path.join(outDir, 'bundle.json'), JSON.stringify({ runId, workflowId, manifest }, null, 2));\n console.log(`Wrote bundle to ${outDir}`);\n for (const m of manifest) {\n console.log(` ${m.ok ? '✓' : '✗'} ${m.file}${m.ok ? '' : ` (${m.error ?? 'failed'})`}`);\n }\n}\n\n/**\n * `materialize` — produce the canonical diagnostic workspace on disk.\n *\n * The same workspace shape powers the v2 failure-diagnostic agent and the\n * Claude Code `debug-run` skill. Pipeline:\n * 1. CLI hits `/debug/materialize-data` → receives `RunData` JSON + a signed\n * S3 URL for trace.zip.\n * 2. CLI downloads trace.zip via the signed URL.\n * 3. CLI runs `assembleWorkspace` from `@chatsdet/diagnostic-workspace` locally.\n * This is the same code the server runs in-process for the v2 agent —\n * no drift possible.\n *\n * Trace reconstruction (Playwright headless) runs on the customer's machine,\n * not the server. After this command completes, start with `summary.md`.\n */\nasync function handleMaterialize(argv: string[], apiUrl: string, token: string): Promise<void> {\n const runId = requireRunId(argv);\n const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);\n const outDir = getArgValue(argv, '--out') ?? `./diag-${runId}`;\n\n const { assembleWorkspace } = await import('@chatsdet/diagnostic-workspace');\n\n type MaterializeDataResponse = {\n ok: true;\n data: { runData: import('@chatsdet/diagnostic-workspace').RunData; signedTraceUrl: string | null };\n } | { ok: false; error?: string };\n\n const dataUrl = `${apiUrl}/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/debug/materialize-data`;\n const dataRes = await fetch(dataUrl, { headers: { Authorization: `Bearer ${token}` } });\n if (!dataRes.ok) {\n const errText = await dataRes.text().catch(() => '');\n console.error(`Failed to fetch run data: HTTP ${dataRes.status} ${errText}`);\n process.exit(1);\n }\n const envelope = (await dataRes.json()) as MaterializeDataResponse;\n if (!envelope.ok) {\n console.error(`Failed: ${envelope.error ?? 'unknown error'}`);\n process.exit(1);\n }\n const { runData, signedTraceUrl } = envelope.data;\n\n await fs.mkdir(outDir, { recursive: true });\n\n // Download trace.zip locally so the assembler can copy + reconstruct it.\n // Stream the body to disk — trace.zip can be 200MB+ and customer CI runners\n // are commonly memory-constrained.\n let traceZipPath: string | null = null;\n if (signedTraceUrl) {\n traceZipPath = path.join(outDir, '.trace-source.zip');\n const traceRes = await fetch(signedTraceUrl);\n if (!traceRes.ok || !traceRes.body) {\n console.warn(`Trace download failed (HTTP ${traceRes.status}); workspace will be marked partial.`);\n traceZipPath = null;\n } else {\n const handle = await fs.open(traceZipPath, 'w');\n try {\n const reader = traceRes.body.getReader();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n if (value) await handle.write(value);\n }\n } finally {\n await handle.close();\n }\n }\n }\n\n await assembleWorkspace({ runData, workspaceRoot: outDir, traceZipPath });\n\n if (traceZipPath) {\n await fs.rm(traceZipPath, { force: true }).catch(() => undefined);\n }\n\n if (hasFlag(argv, '--json')) {\n console.log(JSON.stringify({ workspace: outDir, runId, workflowId }, null, 2));\n return;\n }\n console.log(`Materialized workspace at ${outDir}`);\n console.log(`Start with: cat ${path.join(outDir, 'summary.md')}`);\n}\n"],"mappings":"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","names":["a"]}
@@ -0,0 +1,382 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+ import {
3
+ diffSnapshots,
4
+ fromApiSnapshot,
5
+ getNodeDisplayTitle
6
+ } from "./chunk-JDBCZ3Z2.js";
7
+ import {
8
+ apiRequest
9
+ } from "./chunk-WOHL4FTB.js";
10
+ import "./chunk-SJJW77WN.js";
11
+ import "./chunk-3CZU7XCS.js";
12
+ import {
13
+ getArgValue,
14
+ hasFlag
15
+ } from "./chunk-A4OFTUVV.js";
16
+ import "./chunk-JWHYXEA2.js";
17
+ import "./chunk-VKVL7WBN.js";
18
+
19
+ // src/workflow-proposals.ts
20
+ import process from "process";
21
+
22
+ // src/proposals-format.ts
23
+ var STATUS_DOTS = {
24
+ pending: "\u25CF",
25
+ accepted: "\u2713",
26
+ rejected: "\u2717",
27
+ stale: "\u26A0"
28
+ };
29
+ function renderProposalList(proposals) {
30
+ if (proposals.length === 0) return "No proposals.";
31
+ const rows = proposals.map((p) => {
32
+ const dot = STATUS_DOTS[p.status] ?? "\u2022";
33
+ return `${dot} ${pad(p.status, 10)} ${pad(p.source, 8)} ${p.id.slice(0, 8)}\u2026 ${p.title}`;
34
+ });
35
+ return [
36
+ `${proposals.length} proposal${proposals.length === 1 ? "" : "s"}`,
37
+ "",
38
+ ...rows
39
+ ].join("\n");
40
+ }
41
+ function renderProposalDiff(payload, opts = {}) {
42
+ const { proposal, summary, nodes, edges } = payload;
43
+ const staleNote = proposal.stale ? " \u26A0 STALE" : "";
44
+ const header = [
45
+ `Proposal: ${proposal.title}`,
46
+ `Source: ${proposal.source} Status: ${proposal.status}${staleNote}`,
47
+ `Created: ${proposal.createdAt}`,
48
+ "",
49
+ `Summary: ${summary.addedNodes} added \xB7 ${summary.removedNodes} removed \xB7 ${summary.changedNodes} changed \xB7 ${summary.touchedCount} touched`
50
+ ];
51
+ if (summary.isEmpty) {
52
+ return [...header, "", "No changes \u2014 proposal matches the current draft."].join("\n");
53
+ }
54
+ const blocks = [];
55
+ for (const n of nodes.added) {
56
+ blocks.push(
57
+ `+ ${pad(n.nodeType.toUpperCase(), 14)} ${getNodeDisplayTitle(n.nodeType, n.configJson)} (${n.id})`
58
+ );
59
+ }
60
+ for (const n of nodes.removed) {
61
+ blocks.push(
62
+ `- ${pad(n.nodeType.toUpperCase(), 14)} ${getNodeDisplayTitle(n.nodeType, n.configJson)} (${n.id})`
63
+ );
64
+ }
65
+ for (const c of nodes.changed) {
66
+ const lines = [
67
+ `~ ${pad(c.nodeType.toUpperCase(), 14)} ${c.id}`
68
+ ];
69
+ if (c.typeChanged) {
70
+ lines.push(` nodeType: ${c.beforeType} \u2192 ${c.afterType}`);
71
+ }
72
+ for (const fc of c.fieldChanges) {
73
+ lines.push(` ${fc.path}: ${fmt(fc.before)} \u2192 ${fmt(fc.after)}`);
74
+ }
75
+ blocks.push(lines.join("\n"));
76
+ }
77
+ const edgeLine = `Edges: +${summary.addedEdges} -${summary.removedEdges}`;
78
+ if (edges.added.length === 0 && edges.removed.length === 0) {
79
+ return [...header, "", ...blocks, "", edgeLine].join("\n");
80
+ }
81
+ const edgeLines = [
82
+ ...edges.added.map(
83
+ (e) => ` + ${e.sourceNodeId} \u2192 ${e.targetNodeId}${e.edgeType ? ` [${e.edgeType}]` : ""}`
84
+ ),
85
+ ...edges.removed.map(
86
+ (e) => ` - ${e.sourceNodeId} \u2192 ${e.targetNodeId}${e.edgeType ? ` [${e.edgeType}]` : ""}`
87
+ )
88
+ ];
89
+ const out = [...header, "", ...blocks, "", edgeLine, ...edgeLines];
90
+ if (opts.includeUnchanged) {
91
+ out.push("", "(--include-unchanged has no additional output in v1)");
92
+ }
93
+ return out.join("\n");
94
+ }
95
+ function pad(s, n) {
96
+ return s.length >= n ? s : s + " ".repeat(n - s.length);
97
+ }
98
+ function fmt(v) {
99
+ if (v === void 0) return "(none)";
100
+ if (v === null) return "null";
101
+ if (typeof v === "string") return JSON.stringify(v);
102
+ if (typeof v === "number" || typeof v === "boolean") return String(v);
103
+ try {
104
+ return JSON.stringify(v);
105
+ } catch {
106
+ return String(v);
107
+ }
108
+ }
109
+
110
+ // src/workflow-proposals.ts
111
+ function getArg(argv, key) {
112
+ const prefix = `${key}=`;
113
+ const eq = argv.find((a) => a.startsWith(prefix));
114
+ if (eq) return eq.slice(prefix.length);
115
+ return getArgValue(argv, key);
116
+ }
117
+ var _internalsForTesting = { getArg };
118
+ async function handleWorkflowProposals(argv, apiUrl, token) {
119
+ const [verb, ...rest] = argv;
120
+ switch (verb) {
121
+ case "list":
122
+ await handleList(rest, apiUrl, token);
123
+ break;
124
+ case "get":
125
+ await handleGet(rest, apiUrl, token);
126
+ break;
127
+ case "diff":
128
+ await handleDiff(rest, apiUrl, token);
129
+ break;
130
+ case "accept":
131
+ await handleAccept(rest, apiUrl, token);
132
+ break;
133
+ case "reject":
134
+ await handleReject(rest, apiUrl, token);
135
+ break;
136
+ case "revert":
137
+ await handleRevert(rest, apiUrl, token);
138
+ break;
139
+ default:
140
+ printHelp();
141
+ process.exit(verb ? 1 : 0);
142
+ }
143
+ }
144
+ function printHelp() {
145
+ console.error(
146
+ [
147
+ "Usage: canary workflow proposals <verb> <workflowId> [<proposalId>] [options]",
148
+ "",
149
+ "Verbs:",
150
+ " list <wf> list proposals for a workflow",
151
+ " get <wf> <pid> fetch a proposal (full snapshot)",
152
+ " diff <wf> <pid> show the diff against the current draft",
153
+ " accept <wf> <pid> apply the proposal (full or --select=id1,id2)",
154
+ " reject <wf> <pid> reject the proposal (no draft change)",
155
+ " revert <wf> <pid> revert a previously-accepted proposal to pending",
156
+ "",
157
+ "Global options:",
158
+ " --json force JSON output",
159
+ " --text force pretty-text output (default when stdout is a TTY)",
160
+ " --status=<status> (list) filter by pending|accepted|rejected|stale|all",
161
+ " --include-unchanged (diff) also list rows that did not change",
162
+ " --select=<ids> (accept) comma-separated node ids to accept (default: all)"
163
+ ].join("\n")
164
+ );
165
+ }
166
+ function wantsJson(argv) {
167
+ if (hasFlag(argv, "--json")) return true;
168
+ if (hasFlag(argv, "--text")) return false;
169
+ return !process.stdout.isTTY;
170
+ }
171
+ function emit(argv, textFallback, json) {
172
+ if (wantsJson(argv)) {
173
+ console.log(JSON.stringify(json, null, 2));
174
+ } else {
175
+ console.log(textFallback);
176
+ }
177
+ }
178
+ function requireArgs(argv, n, verb) {
179
+ if (argv.length < n) {
180
+ console.error(
181
+ `Error: canary workflow proposals ${verb} requires ${n} argument${n === 1 ? "" : "s"}`
182
+ );
183
+ printHelp();
184
+ process.exit(1);
185
+ }
186
+ }
187
+ async function handleList(argv, apiUrl, token) {
188
+ requireArgs(argv, 1, "list");
189
+ const [workflowId] = argv;
190
+ const status = getArg(argv, "--status") ?? "pending";
191
+ const query = status === "all" ? "" : `?status=${encodeURIComponent(status)}`;
192
+ const result = await apiRequest(apiUrl, token, "GET", `/workflows/${workflowId}/proposals${query}`);
193
+ if (!result.ok) {
194
+ console.error(`Error: ${result.error ?? "failed to list proposals"}`);
195
+ process.exit(1);
196
+ }
197
+ const proposals = result.data ?? [];
198
+ emit(argv, renderProposalList(proposals), {
199
+ workflowId,
200
+ count: proposals.length,
201
+ proposals
202
+ });
203
+ }
204
+ async function handleGet(argv, apiUrl, token) {
205
+ requireArgs(argv, 2, "get");
206
+ const [workflowId, proposalId] = argv;
207
+ const result = await apiRequest(apiUrl, token, "GET", `/workflows/${workflowId}/proposals/${proposalId}`);
208
+ if (!result.ok || !result.data) {
209
+ console.error(`Error: ${result.error ?? "proposal not found"}`);
210
+ process.exit(1);
211
+ }
212
+ const prop = result.data;
213
+ const text = [
214
+ `Proposal: ${prop.title}`,
215
+ `Source: ${prop.source} Status: ${prop.status}`,
216
+ `Created: ${prop.createdAt}`,
217
+ `Nodes: ${prop.snapshotJson.nodes?.length ?? 0} Edges: ${prop.snapshotJson.edges?.length ?? 0}`
218
+ ].join("\n");
219
+ emit(argv, text, prop);
220
+ }
221
+ async function handleDiff(argv, apiUrl, token) {
222
+ requireArgs(argv, 2, "diff");
223
+ const [workflowId, proposalId] = argv;
224
+ const [propRes, wfRes] = await Promise.all([
225
+ apiRequest(
226
+ apiUrl,
227
+ token,
228
+ "GET",
229
+ `/workflows/${workflowId}/proposals/${proposalId}`
230
+ ),
231
+ apiRequest(
232
+ apiUrl,
233
+ token,
234
+ "GET",
235
+ `/workflows/${workflowId}`
236
+ )
237
+ ]);
238
+ if (!propRes.ok || !propRes.data) {
239
+ console.error(`Error: ${propRes.error ?? "proposal not found"}`);
240
+ process.exit(1);
241
+ }
242
+ if (!wfRes.workflow) {
243
+ console.error(`Error: ${wfRes.error ?? "workflow not found"}`);
244
+ process.exit(1);
245
+ }
246
+ const proposal = propRes.data;
247
+ const workflow = wfRes.workflow;
248
+ const current = fromApiSnapshot({
249
+ nodes: workflow.nodes,
250
+ edges: workflow.edges
251
+ });
252
+ const proposed = fromApiSnapshot(proposal.snapshotJson);
253
+ const diff = diffSnapshots(current, proposed);
254
+ const payload = buildDiffPayload(proposal, proposed, diff);
255
+ const includeUnchanged = hasFlag(argv, "--include-unchanged");
256
+ emit(argv, renderProposalDiff(payload, { includeUnchanged }), payload);
257
+ }
258
+ async function handleAccept(argv, apiUrl, token) {
259
+ requireArgs(argv, 2, "accept");
260
+ const [workflowId, proposalId] = argv;
261
+ const selectArg = getArg(argv, "--select");
262
+ const body = {};
263
+ if (selectArg) {
264
+ const ids = selectArg.split(",").map((s) => s.trim()).filter(Boolean);
265
+ body.selection = { acceptedNodeIds: ids };
266
+ }
267
+ const result = await apiRequest(
268
+ apiUrl,
269
+ token,
270
+ "POST",
271
+ `/workflows/${workflowId}/proposals/${proposalId}/accept`,
272
+ selectArg ? body : void 0
273
+ );
274
+ if (!result.ok) {
275
+ console.error(`Error: ${result.error ?? "accept failed"}`);
276
+ process.exit(1);
277
+ }
278
+ emit(
279
+ argv,
280
+ selectArg ? `Accepted ${body.selection.acceptedNodeIds.length} changes from ${proposalId}.` : `Accepted proposal ${proposalId} in full.`,
281
+ { ok: true, proposalId, workflowId, partial: Boolean(selectArg) }
282
+ );
283
+ }
284
+ async function handleReject(argv, apiUrl, token) {
285
+ requireArgs(argv, 2, "reject");
286
+ const [workflowId, proposalId] = argv;
287
+ const result = await apiRequest(
288
+ apiUrl,
289
+ token,
290
+ "POST",
291
+ `/workflows/${workflowId}/proposals/${proposalId}/reject`
292
+ );
293
+ if (!result.ok) {
294
+ console.error(`Error: ${result.error ?? "reject failed"}`);
295
+ process.exit(1);
296
+ }
297
+ emit(argv, `Rejected proposal ${proposalId}.`, {
298
+ ok: true,
299
+ proposalId,
300
+ workflowId
301
+ });
302
+ }
303
+ async function handleRevert(argv, apiUrl, token) {
304
+ requireArgs(argv, 2, "revert");
305
+ const [workflowId, proposalId] = argv;
306
+ const result = await apiRequest(
307
+ apiUrl,
308
+ token,
309
+ "POST",
310
+ `/workflows/${workflowId}/proposals/${proposalId}/revert`
311
+ );
312
+ if (!result.ok) {
313
+ console.error(`Error: ${result.error ?? "revert failed"}`);
314
+ process.exit(1);
315
+ }
316
+ emit(argv, `Reverted proposal ${proposalId} back to pending.`, {
317
+ ok: true,
318
+ proposalId,
319
+ workflowId
320
+ });
321
+ }
322
+ function buildDiffPayload(proposal, proposedSnap, diff) {
323
+ const byId = new Map(proposedSnap.nodes.map((n) => [n.id, n]));
324
+ return {
325
+ proposal: {
326
+ id: proposal.id,
327
+ title: proposal.title,
328
+ source: proposal.source,
329
+ status: proposal.status,
330
+ stale: proposal.status === "stale",
331
+ createdAt: proposal.createdAt,
332
+ decidedAt: proposal.decidedAt
333
+ },
334
+ summary: {
335
+ addedNodes: diff.addedNodes.length,
336
+ removedNodes: diff.removedNodes.length,
337
+ changedNodes: diff.changedNodes.length,
338
+ addedEdges: diff.addedEdges.length,
339
+ removedEdges: diff.removedEdges.length,
340
+ touchedCount: diff.touchedCount,
341
+ isEmpty: diff.isEmpty
342
+ },
343
+ nodes: {
344
+ added: diff.addedNodes.map((n) => ({
345
+ id: n.id,
346
+ nodeType: n.nodeType,
347
+ configJson: n.configJson
348
+ })),
349
+ removed: diff.removedNodes.map((n) => ({
350
+ id: n.id,
351
+ nodeType: n.nodeType,
352
+ configJson: n.configJson
353
+ })),
354
+ changed: diff.changedNodes.map((c) => ({
355
+ id: c.id,
356
+ nodeType: c.nodeType,
357
+ typeChanged: c.typeChanged,
358
+ beforeType: c.beforeType,
359
+ afterType: c.afterType,
360
+ fieldChanges: c.fieldChanges
361
+ }))
362
+ },
363
+ edges: {
364
+ added: diff.addedEdges.map((e) => ({
365
+ sourceNodeId: e.sourceNodeId,
366
+ targetNodeId: e.targetNodeId,
367
+ edgeType: e.edgeType ?? null
368
+ })),
369
+ removed: diff.removedEdges.map((e) => ({
370
+ sourceNodeId: e.sourceNodeId,
371
+ targetNodeId: e.targetNodeId,
372
+ edgeType: e.edgeType ?? null
373
+ }))
374
+ }
375
+ };
376
+ void byId;
377
+ }
378
+ export {
379
+ _internalsForTesting,
380
+ handleWorkflowProposals
381
+ };
382
+ //# sourceMappingURL=workflow-proposals-MTUDX46O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/workflow-proposals.ts","../src/proposals-format.ts"],"sourcesContent":["/**\n * `canary workflow proposals <verb>` — list / get / diff / accept / reject /\n * revert workflow proposals.\n *\n * Output mode auto-detects: JSON when piped (`!process.stdout.isTTY`), pretty\n * text when running interactively. `--json` and `--text` flags force either\n * mode. Designed so an agent can pipe JSON straight into `jq` without any\n * extra flag, and a human gets the readable report at a terminal.\n */\n\nimport process from 'node:process';\nimport {\n diffSnapshots,\n fromApiSnapshot,\n type SnapshotDiff,\n} from '@chatsdet/workflow-diff';\nimport { getArgValue, hasFlag } from './auth.js';\n\n/**\n * Like `getArgValue` but also accepts the `--key=value` form that many\n * agents emit by default. Falls back to the space-separated form. Matches\n * only exact `--key=` to avoid false-positives on `--status-filter=x` when\n * looking for `--status`.\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\n/** @internal — exported for unit tests only. */\nexport const _internalsForTesting = { getArg };\nimport { apiRequest } from './cli-helpers.js';\nimport { renderProposalList, renderProposalDiff } from './proposals-format.js';\n\n// ── Types ────────────────────────────────────────────────────────────────\n\nexport interface ProposalSummary {\n id: string;\n workflowId: string;\n title: string;\n description: string | null;\n source: 'agent' | 'user' | 'import' | 'api';\n status: 'pending' | 'accepted' | 'rejected' | 'stale';\n createdByUserId: string | null;\n decidedByUserId: string | null;\n decidedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ProposalDetail extends ProposalSummary {\n snapshotJson: {\n nodes?: Array<{\n id: string;\n nodeType: string;\n orderIndex?: number;\n configJson?: Record<string, unknown>;\n }>;\n edges?: Array<{\n id: string;\n sourceNodeId: string;\n targetNodeId: string;\n edgeType?: string | null;\n }>;\n };\n sourceMetadata: Record<string, unknown> | null;\n}\n\ninterface WorkflowDetail {\n id: string;\n nodes: Array<{\n id: string;\n nodeType: string;\n orderIndex?: number;\n configJson?: Record<string, unknown>;\n }>;\n edges: Array<{\n id: string;\n sourceNodeId: string;\n targetNodeId: string;\n edgeType?: string | null;\n }>;\n updatedAt?: string;\n}\n\n// ── Dispatcher ───────────────────────────────────────────────────────────\n\nexport async function handleWorkflowProposals(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n const [verb, ...rest] = argv;\n switch (verb) {\n case 'list':\n await handleList(rest, apiUrl, token);\n break;\n case 'get':\n await handleGet(rest, apiUrl, token);\n break;\n case 'diff':\n await handleDiff(rest, apiUrl, token);\n break;\n case 'accept':\n await handleAccept(rest, apiUrl, token);\n break;\n case 'reject':\n await handleReject(rest, apiUrl, token);\n break;\n case 'revert':\n await handleRevert(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 proposals <verb> <workflowId> [<proposalId>] [options]',\n '',\n 'Verbs:',\n ' list <wf> list proposals for a workflow',\n ' get <wf> <pid> fetch a proposal (full snapshot)',\n ' diff <wf> <pid> show the diff against the current draft',\n ' accept <wf> <pid> apply the proposal (full or --select=id1,id2)',\n ' reject <wf> <pid> reject the proposal (no draft change)',\n ' revert <wf> <pid> revert a previously-accepted proposal to pending',\n '',\n 'Global options:',\n ' --json force JSON output',\n ' --text force pretty-text output (default when stdout is a TTY)',\n ' --status=<status> (list) filter by pending|accepted|rejected|stale|all',\n ' --include-unchanged (diff) also list rows that did not change',\n ' --select=<ids> (accept) comma-separated node ids to accept (default: all)',\n ].join('\\n'),\n );\n}\n\n// ── Output-mode helper ───────────────────────────────────────────────────\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\nfunction requireArgs(\n argv: string[],\n n: number,\n verb: string,\n): asserts argv is string[] {\n if (argv.length < n) {\n console.error(\n `Error: canary workflow proposals ${verb} requires ${n} argument${n === 1 ? '' : 's'}`,\n );\n printHelp();\n process.exit(1);\n }\n}\n\n// ── Handlers ─────────────────────────────────────────────────────────────\n\nasync function handleList(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 1, 'list');\n const [workflowId] = argv;\n const status = getArg(argv, '--status') ?? 'pending';\n const query = status === 'all' ? '' : `?status=${encodeURIComponent(status)}`;\n\n const result = await apiRequest<{\n ok: boolean;\n data?: ProposalSummary[];\n error?: string;\n }>(apiUrl, token, 'GET', `/workflows/${workflowId}/proposals${query}`);\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'failed to list proposals'}`);\n process.exit(1);\n }\n\n const proposals = result.data ?? [];\n emit(argv, renderProposalList(proposals), {\n workflowId,\n count: proposals.length,\n proposals,\n });\n}\n\nasync function handleGet(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'get');\n const [workflowId, proposalId] = argv;\n\n const result = await apiRequest<{\n ok: boolean;\n data?: ProposalDetail;\n error?: string;\n }>(apiUrl, token, 'GET', `/workflows/${workflowId}/proposals/${proposalId}`);\n\n if (!result.ok || !result.data) {\n console.error(`Error: ${result.error ?? 'proposal not found'}`);\n process.exit(1);\n }\n\n const prop = result.data;\n const text = [\n `Proposal: ${prop.title}`,\n `Source: ${prop.source} Status: ${prop.status}`,\n `Created: ${prop.createdAt}`,\n `Nodes: ${prop.snapshotJson.nodes?.length ?? 0} Edges: ${prop.snapshotJson.edges?.length ?? 0}`,\n ].join('\\n');\n emit(argv, text, prop);\n}\n\nasync function handleDiff(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'diff');\n const [workflowId, proposalId] = argv;\n\n const [propRes, wfRes] = await Promise.all([\n apiRequest<{ ok: boolean; data?: ProposalDetail; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/proposals/${proposalId}`,\n ),\n apiRequest<{ ok: boolean; workflow?: WorkflowDetail; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}`,\n ),\n ]);\n\n if (!propRes.ok || !propRes.data) {\n console.error(`Error: ${propRes.error ?? 'proposal not found'}`);\n process.exit(1);\n }\n if (!wfRes.workflow) {\n console.error(`Error: ${wfRes.error ?? 'workflow not found'}`);\n process.exit(1);\n }\n\n const proposal = propRes.data;\n const workflow = wfRes.workflow;\n\n const current = fromApiSnapshot({\n nodes: workflow.nodes,\n edges: workflow.edges,\n });\n const proposed = fromApiSnapshot(proposal.snapshotJson);\n const diff = diffSnapshots(current, proposed);\n\n const payload = buildDiffPayload(proposal, proposed, diff);\n const includeUnchanged = hasFlag(argv, '--include-unchanged');\n emit(argv, renderProposalDiff(payload, { includeUnchanged }), payload);\n}\n\nasync function handleAccept(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'accept');\n const [workflowId, proposalId] = argv;\n const selectArg = getArg(argv, '--select');\n const body: { selection?: { acceptedNodeIds: string[] } } = {};\n if (selectArg) {\n const ids = selectArg.split(',').map((s) => s.trim()).filter(Boolean);\n body.selection = { acceptedNodeIds: ids };\n }\n\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/accept`,\n selectArg ? body : undefined,\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'accept failed'}`);\n process.exit(1);\n }\n\n emit(\n argv,\n selectArg\n ? `Accepted ${body.selection!.acceptedNodeIds.length} changes from ${proposalId}.`\n : `Accepted proposal ${proposalId} in full.`,\n { ok: true, proposalId, workflowId, partial: Boolean(selectArg) },\n );\n}\n\nasync function handleReject(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'reject');\n const [workflowId, proposalId] = argv;\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/reject`,\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'reject failed'}`);\n process.exit(1);\n }\n emit(argv, `Rejected proposal ${proposalId}.`, {\n ok: true,\n proposalId,\n workflowId,\n });\n}\n\nasync function handleRevert(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'revert');\n const [workflowId, proposalId] = argv;\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/revert`,\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'revert failed'}`);\n process.exit(1);\n }\n emit(argv, `Reverted proposal ${proposalId} back to pending.`, {\n ok: true,\n proposalId,\n workflowId,\n });\n}\n\n// ── Diff payload shaper ──────────────────────────────────────────────────\n\nexport interface DiffPayload {\n proposal: {\n id: string;\n title: string;\n source: string;\n status: string;\n stale: boolean;\n createdAt: string;\n decidedAt: string | null;\n };\n summary: {\n addedNodes: number;\n removedNodes: number;\n changedNodes: number;\n addedEdges: number;\n removedEdges: number;\n touchedCount: number;\n isEmpty: boolean;\n };\n nodes: {\n added: Array<{\n id: string;\n nodeType: string;\n configJson: Record<string, unknown>;\n }>;\n removed: Array<{\n id: string;\n nodeType: string;\n configJson: Record<string, unknown>;\n }>;\n changed: Array<{\n id: string;\n nodeType: string;\n typeChanged: boolean;\n beforeType?: string;\n afterType?: string;\n fieldChanges: Array<{ path: string; before: unknown; after: unknown }>;\n }>;\n };\n edges: {\n added: Array<{\n sourceNodeId: string;\n targetNodeId: string;\n edgeType: string | null;\n }>;\n removed: Array<{\n sourceNodeId: string;\n targetNodeId: string;\n edgeType: string | null;\n }>;\n };\n}\n\nfunction buildDiffPayload(\n proposal: ProposalDetail,\n proposedSnap: ReturnType<typeof fromApiSnapshot>,\n diff: SnapshotDiff,\n): DiffPayload {\n // Build a proposed-nodes map so the diff payload can include configJson\n // for each changed node (the diff itself only has field-level changes).\n const byId = new Map(proposedSnap.nodes.map((n) => [n.id, n]));\n\n return {\n proposal: {\n id: proposal.id,\n title: proposal.title,\n source: proposal.source,\n status: proposal.status,\n stale: proposal.status === 'stale',\n createdAt: proposal.createdAt,\n decidedAt: proposal.decidedAt,\n },\n summary: {\n addedNodes: diff.addedNodes.length,\n removedNodes: diff.removedNodes.length,\n changedNodes: diff.changedNodes.length,\n addedEdges: diff.addedEdges.length,\n removedEdges: diff.removedEdges.length,\n touchedCount: diff.touchedCount,\n isEmpty: diff.isEmpty,\n },\n nodes: {\n added: diff.addedNodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n configJson: n.configJson,\n })),\n removed: diff.removedNodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n configJson: n.configJson,\n })),\n changed: diff.changedNodes.map((c) => ({\n id: c.id,\n nodeType: c.nodeType,\n typeChanged: c.typeChanged,\n beforeType: c.beforeType,\n afterType: c.afterType,\n fieldChanges: c.fieldChanges,\n })),\n },\n edges: {\n added: diff.addedEdges.map((e) => ({\n sourceNodeId: e.sourceNodeId,\n targetNodeId: e.targetNodeId,\n edgeType: e.edgeType ?? null,\n })),\n removed: diff.removedEdges.map((e) => ({\n sourceNodeId: e.sourceNodeId,\n targetNodeId: e.targetNodeId,\n edgeType: e.edgeType ?? null,\n })),\n },\n };\n void byId;\n}\n","/**\n * Pretty-text renderers for `canary workflow proposals list | diff`.\n * Pure — no fetching, easy to test.\n */\n\nimport { getNodeDisplayTitle } from '@chatsdet/workflow-diff';\nimport type { ProposalSummary, DiffPayload } from './workflow-proposals.js';\n\nconst STATUS_DOTS: Record<string, string> = {\n pending: '●',\n accepted: '✓',\n rejected: '✗',\n stale: '⚠',\n};\n\nexport function renderProposalList(proposals: ProposalSummary[]): string {\n if (proposals.length === 0) return 'No proposals.';\n const rows = proposals.map((p) => {\n const dot = STATUS_DOTS[p.status] ?? '•';\n return `${dot} ${pad(p.status, 10)} ${pad(p.source, 8)} ${p.id.slice(0, 8)}… ${p.title}`;\n });\n return [\n `${proposals.length} proposal${proposals.length === 1 ? '' : 's'}`,\n '',\n ...rows,\n ].join('\\n');\n}\n\nexport function renderProposalDiff(\n payload: DiffPayload,\n opts: { includeUnchanged?: boolean } = {},\n): string {\n const { proposal, summary, nodes, edges } = payload;\n const staleNote = proposal.stale ? ' ⚠ STALE' : '';\n const header = [\n `Proposal: ${proposal.title}`,\n `Source: ${proposal.source} Status: ${proposal.status}${staleNote}`,\n `Created: ${proposal.createdAt}`,\n '',\n `Summary: ${summary.addedNodes} added · ${summary.removedNodes} removed · ${summary.changedNodes} changed · ${summary.touchedCount} touched`,\n ];\n\n if (summary.isEmpty) {\n return [...header, '', 'No changes — proposal matches the current draft.'].join('\\n');\n }\n\n const blocks: string[] = [];\n\n for (const n of nodes.added) {\n blocks.push(\n `+ ${pad(n.nodeType.toUpperCase(), 14)} ${getNodeDisplayTitle(n.nodeType, n.configJson)} (${n.id})`,\n );\n }\n for (const n of nodes.removed) {\n blocks.push(\n `- ${pad(n.nodeType.toUpperCase(), 14)} ${getNodeDisplayTitle(n.nodeType, n.configJson)} (${n.id})`,\n );\n }\n for (const c of nodes.changed) {\n const lines = [\n `~ ${pad(c.nodeType.toUpperCase(), 14)} ${c.id}`,\n ];\n if (c.typeChanged) {\n lines.push(` nodeType: ${c.beforeType} → ${c.afterType}`);\n }\n for (const fc of c.fieldChanges) {\n lines.push(` ${fc.path}: ${fmt(fc.before)} → ${fmt(fc.after)}`);\n }\n blocks.push(lines.join('\\n'));\n }\n\n const edgeLine = `Edges: +${summary.addedEdges} -${summary.removedEdges}`;\n if (edges.added.length === 0 && edges.removed.length === 0) {\n return [...header, '', ...blocks, '', edgeLine].join('\\n');\n }\n const edgeLines = [\n ...edges.added.map(\n (e) => ` + ${e.sourceNodeId} → ${e.targetNodeId}${e.edgeType ? ` [${e.edgeType}]` : ''}`,\n ),\n ...edges.removed.map(\n (e) => ` - ${e.sourceNodeId} → ${e.targetNodeId}${e.edgeType ? ` [${e.edgeType}]` : ''}`,\n ),\n ];\n\n const out = [...header, '', ...blocks, '', edgeLine, ...edgeLines];\n\n // --include-unchanged is a passthrough hook for a future expansion; today\n // the diff engine doesn't surface unchanged nodes, so we just note that.\n if (opts.includeUnchanged) {\n out.push('', '(--include-unchanged has no additional output in v1)');\n }\n\n return out.join('\\n');\n}\n\nfunction pad(s: string, n: number): string {\n return s.length >= n ? s : s + ' '.repeat(n - s.length);\n}\n\nfunction fmt(v: unknown): string {\n if (v === undefined) return '(none)';\n if (v === null) return 'null';\n if (typeof v === 'string') return JSON.stringify(v);\n if (typeof v === 'number' || typeof v === 'boolean') return String(v);\n try {\n return JSON.stringify(v);\n } catch {\n return String(v);\n }\n}\n"],"mappings":"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","names":[]}