@shipfox/client-workflows 18.0.0 → 19.0.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 (29) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +11 -0
  3. package/dist/components/workflow-run-list/job-status-strip.d.ts.map +1 -1
  4. package/dist/components/workflow-run-list/job-status-strip.js +20 -7
  5. package/dist/components/workflow-run-list/job-status-strip.js.map +1 -1
  6. package/dist/core/entities/job.d.ts +5 -2
  7. package/dist/core/entities/job.d.ts.map +1 -1
  8. package/dist/core/entities/job.js +8 -1
  9. package/dist/core/entities/job.js.map +1 -1
  10. package/dist/core/entities/workflow-run.d.ts +7 -4
  11. package/dist/core/entities/workflow-run.d.ts.map +1 -1
  12. package/dist/core/entities/workflow-run.js.map +1 -1
  13. package/dist/hooks/api/workflow-run-mapper.d.ts.map +1 -1
  14. package/dist/hooks/api/workflow-run-mapper.js +11 -1
  15. package/dist/hooks/api/workflow-run-mapper.js.map +1 -1
  16. package/dist/tsconfig.test.tsbuildinfo +1 -1
  17. package/package.json +2 -2
  18. package/src/components/job-graph/job-node.test.tsx +2 -2
  19. package/src/components/workflow-run-list/job-status-strip.tsx +25 -12
  20. package/src/components/workflow-run-list/workflow-run-list-view.test.tsx +73 -0
  21. package/src/components/workflow-run-list/workflow-run-list.stories.tsx +31 -0
  22. package/src/core/entities/job-status.test.ts +47 -1
  23. package/src/core/entities/job.ts +15 -3
  24. package/src/core/entities/workflow-run-display.test.ts +28 -0
  25. package/src/core/entities/workflow-run.ts +18 -4
  26. package/src/core/workflow-run.test.ts +13 -0
  27. package/src/hooks/api/workflow-run-mapper.ts +18 -1
  28. package/test/fixtures/workflow-run.ts +32 -12
  29. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,2 +1,2 @@
1
1
  $ shipfox-swc
2
- Successfully compiled: 86 files with swc (559.86ms)
2
+ Successfully compiled: 86 files with swc (649.43ms)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @shipfox/client-workflows
2
2
 
3
+ ## 19.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 53b87f0: Distinguish queued and executing jobs in workflow run list status strips.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [53b87f0]
12
+ - @shipfox/api-workflows-dto@12.6.0
13
+
3
14
  ## 18.0.0
4
15
 
5
16
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"job-status-strip.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/job-status-strip.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAmC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAyC7F,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,EAAC,IAAI,EAAE,SAAS,EAAC,EAAE,mBAAmB,sCAqDpE;AAgCD,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAO9D;AAyBD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAI9D"}
1
+ {"version":3,"file":"job-status-strip.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/job-status-strip.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAwB,eAAe,EAAC,MAAM,uBAAuB,CAAC;AA0ClF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,EAAC,IAAI,EAAE,SAAS,EAAC,EAAE,mBAAmB,sCAqDpE;AAgCD,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAO9D;AA0BD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAI9D"}
@@ -4,6 +4,7 @@ import { Code, Text } from '@shipfox/react-ui/typography';
4
4
  import { cn } from '@shipfox/react-ui/utils';
5
5
  import { getWorkflowStatusVisual } from '#components/workflow-status/status-visuals.js';
6
6
  import { WorkflowStatusIcon } from '#components/workflow-status/workflow-status-icon.js';
7
+ import { deriveJobDisplayStatus } from '#core/entities/job.js';
7
8
  /**
8
9
  * How many glyphs fit the strip's column before it starts costing the run name width.
9
10
  *
@@ -31,6 +32,7 @@ const COMPACT_COUNT_FORMAT = new Intl.NumberFormat('en', {
31
32
  const STATUS_SEVERITY = {
32
33
  failed: 5,
33
34
  running: 4,
35
+ listening: 4,
34
36
  pending: 3,
35
37
  cancelled: 2,
36
38
  skipped: 1,
@@ -38,7 +40,8 @@ const STATUS_SEVERITY = {
38
40
  };
39
41
  const NOTABLE_STATUSES = [
40
42
  'failed',
41
- 'running'
43
+ 'running',
44
+ 'listening'
42
45
  ];
43
46
  /**
44
47
  * A run's jobs as a row of status glyphs, in graph order.
@@ -69,7 +72,7 @@ const NOTABLE_STATUSES = [
69
72
  className: "inline-flex items-center gap-[3px]",
70
73
  children: [
71
74
  visible.map((job)=>/*#__PURE__*/ _jsx(WorkflowStatusIcon, {
72
- status: job.status,
75
+ status: displayStatus(job),
73
76
  size: GLYPH_SIZE,
74
77
  // One ripple per running job, on every row, would turn a calm list into a
75
78
  // field of pulses. The run's own glyph already carries the live edge.
@@ -114,7 +117,7 @@ function JobStatusStripTooltip({ jobs, summary }) {
114
117
  // left to the counts so the tooltip stays a glance rather than a list. Only previewed jobs
115
118
  // can be named, but the count of those left over is read off the totals, so a failure past
116
119
  // the preview is still accounted for rather than silently missing.
117
- const named = jobs.preview.filter((job)=>NOTABLE_STATUSES.includes(job.status)).slice(0, MAX_TOOLTIP_JOB_NAMES);
120
+ const named = jobs.preview.filter((job)=>NOTABLE_STATUSES.includes(displayStatus(job))).slice(0, MAX_TOOLTIP_JOB_NAMES);
118
121
  const notableTotal = NOTABLE_STATUSES.reduce((total, status)=>total + countOf(jobs, status), 0);
119
122
  const remaining = notableTotal - named.length;
120
123
  return /*#__PURE__*/ _jsxs("span", {
@@ -131,7 +134,7 @@ function JobStatusStripTooltip({ jobs, summary }) {
131
134
  variant: "label",
132
135
  className: "block truncate",
133
136
  children: [
134
- getWorkflowStatusVisual(job.status).label.toLowerCase(),
137
+ getWorkflowStatusVisual(displayStatus(job)).label.toLowerCase(),
135
138
  " · ",
136
139
  job.name ?? job.key
137
140
  ]
@@ -164,9 +167,10 @@ function JobStatusStripTooltip({ jobs, summary }) {
164
167
  count
165
168
  ]));
166
169
  for (const job of visible){
167
- const remaining = (hidden.get(job.status) ?? 0) - 1;
168
- if (remaining > 0) hidden.set(job.status, remaining);
169
- else hidden.delete(job.status);
170
+ const status = displayStatus(job);
171
+ const remaining = (hidden.get(status) ?? 0) - 1;
172
+ if (remaining > 0) hidden.set(status, remaining);
173
+ else hidden.delete(status);
170
174
  }
171
175
  let worst = null;
172
176
  for (const [status, count] of hidden){
@@ -181,5 +185,14 @@ export function overflowCountLabel(hiddenCount) {
181
185
  function countOf(jobs, status) {
182
186
  return jobs.statusCounts.find((entry)=>entry.status === status)?.count ?? 0;
183
187
  }
188
+ function displayStatus(job) {
189
+ return deriveJobDisplayStatus({
190
+ mode: job.mode,
191
+ status: job.status,
192
+ listenerStatus: job.listenerStatus,
193
+ executionStatus: job.executionStatus,
194
+ jobExecutions: []
195
+ });
196
+ }
184
197
 
185
198
  //# sourceMappingURL=job-status-strip.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-list/job-status-strip.tsx"],"sourcesContent":["import {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {getWorkflowStatusVisual} from '#components/workflow-status/status-visuals.js';\nimport {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';\nimport type {JobStatus, WorkflowRunJobSummary, WorkflowRunJobs} from '#core/workflow-run.js';\n\n/**\n * How many glyphs fit the strip's column before it starts costing the run name width.\n *\n * Sized so the widest case still fits the row's 160px strip column: seven 12px glyphs with\n * 3px gaps is 102px, and the overflow indicator adds a glyph plus a count of at most five\n * monospace characters, about 56px. Overshooting does not wrap, it paints over the duration\n * column. This sits under the API's preview bound, so resizing the strip is a change here.\n */\nconst MAX_VISIBLE_JOBS = 7;\nconst GLYPH_SIZE = 12;\nconst MAX_TOOLTIP_JOB_NAMES = 6;\n\n/**\n * Above this the overflow count is abbreviated.\n *\n * Nothing caps a workflow's job count, so an exact count is unbounded in width and would\n * eventually push the strip over its column. Abbreviating keeps the label at most five\n * characters for any magnitude, and the exact figure stays in the tooltip and the strip's\n * accessible name, which is where a precise number is actually read.\n */\nconst MAX_EXACT_OVERFLOW_COUNT = 999;\nconst COMPACT_COUNT_FORMAT = new Intl.NumberFormat('en', {\n notation: 'compact',\n maximumFractionDigits: 1,\n});\n\n// Worst-first, so the overflow glyph reports the most alarming thing it is standing in for.\n// A strip that hides a failure behind eight green discs would be worse than no strip at all.\nconst STATUS_SEVERITY: Record<JobStatus, number> = {\n failed: 5,\n running: 4,\n pending: 3,\n cancelled: 2,\n skipped: 1,\n succeeded: 0,\n};\n\nconst NOTABLE_STATUSES: readonly JobStatus[] = ['failed', 'running'];\n\nexport interface JobStatusStripProps {\n jobs: WorkflowRunJobs;\n className?: string | undefined;\n}\n\n/**\n * A run's jobs as a row of status glyphs, in graph order.\n *\n * This is the reason the list is worth its width: it answers \"where did this run fail\"\n * without opening the run. Glyphs are silent to assistive tech and carry no tooltip of their\n * own; the strip speaks once, as a summary, so a 40-job run does not read out 40 labels.\n *\n * What it draws comes from the preview; what it says comes from the counts, which cover every\n * job including those the server never sent. That split is what lets the overflow glyph\n * report a failure sitting past the preview instead of quietly dropping it.\n */\nexport function JobStatusStrip({jobs, className}: JobStatusStripProps) {\n if (jobs.total === 0) return null;\n\n const visible = jobs.preview.slice(0, MAX_VISIBLE_JOBS);\n const hiddenCount = jobs.total - visible.length;\n const overflowStatus = worstHiddenStatus(jobs, visible);\n const summary = jobStatusSummary(jobs);\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n role=\"img\"\n aria-label={summary}\n className={cn('inline-flex items-center gap-[3px]', className)}\n >\n <span aria-hidden=\"true\" className=\"inline-flex items-center gap-[3px]\">\n {visible.map((job) => (\n <WorkflowStatusIcon\n key={job.id}\n status={job.status}\n size={GLYPH_SIZE}\n // One ripple per running job, on every row, would turn a calm list into a\n // field of pulses. The run's own glyph already carries the live edge.\n ripple={false}\n tooltip={false}\n />\n ))}\n {hiddenCount > 0 && overflowStatus ? (\n <span className=\"inline-flex items-center gap-[2px]\">\n <WorkflowStatusIcon\n status={overflowStatus}\n size={GLYPH_SIZE}\n ripple={false}\n tooltip={false}\n />\n <Code\n as=\"span\"\n variant=\"label\"\n className=\"tabular-nums text-foreground-neutral-muted\"\n >\n +{overflowCountLabel(hiddenCount)}\n </Code>\n </span>\n ) : null}\n </span>\n </span>\n </TooltipTrigger>\n <TooltipContent>\n <JobStatusStripTooltip jobs={jobs} summary={summary} />\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction JobStatusStripTooltip({jobs, summary}: {jobs: WorkflowRunJobs; summary: string}) {\n // Naming the jobs that need attention is the whole point of hovering; succeeded jobs are\n // left to the counts so the tooltip stays a glance rather than a list. Only previewed jobs\n // can be named, but the count of those left over is read off the totals, so a failure past\n // the preview is still accounted for rather than silently missing.\n const named = jobs.preview\n .filter((job) => NOTABLE_STATUSES.includes(job.status))\n .slice(0, MAX_TOOLTIP_JOB_NAMES);\n const notableTotal = NOTABLE_STATUSES.reduce((total, status) => total + countOf(jobs, status), 0);\n const remaining = notableTotal - named.length;\n\n return (\n <span className=\"flex max-w-[280px] flex-col gap-tight\">\n <Text as=\"span\" size=\"xs\" className=\"block\">\n {summary}\n </Text>\n {named.map((job) => (\n <Code as=\"span\" variant=\"label\" key={job.id} className=\"block truncate\">\n {getWorkflowStatusVisual(job.status).label.toLowerCase()} · {job.name ?? job.key}\n </Code>\n ))}\n {remaining > 0 ? (\n <Text as=\"span\" size=\"xs\" className=\"block text-foreground-neutral-muted\">\n and {remaining} more\n </Text>\n ) : null}\n </span>\n );\n}\n\n/** \"12 jobs: 9 succeeded, 2 failed, 1 running\" — a count is not an accessible name on its own. */\nexport function jobStatusSummary(jobs: WorkflowRunJobs): string {\n const breakdown = [...jobs.statusCounts]\n .sort((left, right) => STATUS_SEVERITY[right.status] - STATUS_SEVERITY[left.status])\n .map(({status, count}) => `${count} ${getWorkflowStatusVisual(status).label.toLowerCase()}`)\n .join(', ');\n\n return `${jobs.total} ${jobs.total === 1 ? 'job' : 'jobs'}: ${breakdown}`;\n}\n\n/**\n * The worst status among the jobs the strip is not drawing, found by subtracting what it\n * draws from the run's totals rather than by inspecting jobs it was never sent.\n */\nfunction worstHiddenStatus(\n jobs: WorkflowRunJobs,\n visible: readonly WorkflowRunJobSummary[],\n): JobStatus | null {\n const hidden = new Map(jobs.statusCounts.map(({status, count}) => [status, count]));\n for (const job of visible) {\n const remaining = (hidden.get(job.status) ?? 0) - 1;\n if (remaining > 0) hidden.set(job.status, remaining);\n else hidden.delete(job.status);\n }\n\n let worst: JobStatus | null = null;\n for (const [status, count] of hidden) {\n if (count <= 0) continue;\n if (worst === null || STATUS_SEVERITY[status] > STATUS_SEVERITY[worst]) worst = status;\n }\n return worst;\n}\n\nexport function overflowCountLabel(hiddenCount: number): string {\n return hiddenCount <= MAX_EXACT_OVERFLOW_COUNT\n ? String(hiddenCount)\n : COMPACT_COUNT_FORMAT.format(hiddenCount);\n}\n\nfunction countOf(jobs: WorkflowRunJobs, status: JobStatus): number {\n return jobs.statusCounts.find((entry) => entry.status === status)?.count ?? 0;\n}\n"],"names":["Tooltip","TooltipContent","TooltipTrigger","Code","Text","cn","getWorkflowStatusVisual","WorkflowStatusIcon","MAX_VISIBLE_JOBS","GLYPH_SIZE","MAX_TOOLTIP_JOB_NAMES","MAX_EXACT_OVERFLOW_COUNT","COMPACT_COUNT_FORMAT","Intl","NumberFormat","notation","maximumFractionDigits","STATUS_SEVERITY","failed","running","pending","cancelled","skipped","succeeded","NOTABLE_STATUSES","JobStatusStrip","jobs","className","total","visible","preview","slice","hiddenCount","length","overflowStatus","worstHiddenStatus","summary","jobStatusSummary","asChild","span","role","aria-label","aria-hidden","map","job","status","size","ripple","tooltip","id","as","variant","overflowCountLabel","JobStatusStripTooltip","named","filter","includes","notableTotal","reduce","countOf","remaining","label","toLowerCase","name","key","breakdown","statusCounts","sort","left","right","count","join","hidden","Map","get","set","delete","worst","String","format","find","entry"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-list/job-status-strip.tsx"],"sourcesContent":["import {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {getWorkflowStatusVisual} from '#components/workflow-status/status-visuals.js';\nimport {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';\nimport {deriveJobDisplayStatus, type JobDisplayStatus} from '#core/entities/job.js';\nimport type {WorkflowRunJobSummary, WorkflowRunJobs} from '#core/workflow-run.js';\n\n/**\n * How many glyphs fit the strip's column before it starts costing the run name width.\n *\n * Sized so the widest case still fits the row's 160px strip column: seven 12px glyphs with\n * 3px gaps is 102px, and the overflow indicator adds a glyph plus a count of at most five\n * monospace characters, about 56px. Overshooting does not wrap, it paints over the duration\n * column. This sits under the API's preview bound, so resizing the strip is a change here.\n */\nconst MAX_VISIBLE_JOBS = 7;\nconst GLYPH_SIZE = 12;\nconst MAX_TOOLTIP_JOB_NAMES = 6;\n\n/**\n * Above this the overflow count is abbreviated.\n *\n * Nothing caps a workflow's job count, so an exact count is unbounded in width and would\n * eventually push the strip over its column. Abbreviating keeps the label at most five\n * characters for any magnitude, and the exact figure stays in the tooltip and the strip's\n * accessible name, which is where a precise number is actually read.\n */\nconst MAX_EXACT_OVERFLOW_COUNT = 999;\nconst COMPACT_COUNT_FORMAT = new Intl.NumberFormat('en', {\n notation: 'compact',\n maximumFractionDigits: 1,\n});\n\n// Worst-first, so the overflow glyph reports the most alarming thing it is standing in for.\n// A strip that hides a failure behind eight green discs would be worse than no strip at all.\nconst STATUS_SEVERITY: Record<JobDisplayStatus, number> = {\n failed: 5,\n running: 4,\n listening: 4,\n pending: 3,\n cancelled: 2,\n skipped: 1,\n succeeded: 0,\n};\n\nconst NOTABLE_STATUSES: readonly JobDisplayStatus[] = ['failed', 'running', 'listening'];\n\nexport interface JobStatusStripProps {\n jobs: WorkflowRunJobs;\n className?: string | undefined;\n}\n\n/**\n * A run's jobs as a row of status glyphs, in graph order.\n *\n * This is the reason the list is worth its width: it answers \"where did this run fail\"\n * without opening the run. Glyphs are silent to assistive tech and carry no tooltip of their\n * own; the strip speaks once, as a summary, so a 40-job run does not read out 40 labels.\n *\n * What it draws comes from the preview; what it says comes from the counts, which cover every\n * job including those the server never sent. That split is what lets the overflow glyph\n * report a failure sitting past the preview instead of quietly dropping it.\n */\nexport function JobStatusStrip({jobs, className}: JobStatusStripProps) {\n if (jobs.total === 0) return null;\n\n const visible = jobs.preview.slice(0, MAX_VISIBLE_JOBS);\n const hiddenCount = jobs.total - visible.length;\n const overflowStatus = worstHiddenStatus(jobs, visible);\n const summary = jobStatusSummary(jobs);\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n role=\"img\"\n aria-label={summary}\n className={cn('inline-flex items-center gap-[3px]', className)}\n >\n <span aria-hidden=\"true\" className=\"inline-flex items-center gap-[3px]\">\n {visible.map((job) => (\n <WorkflowStatusIcon\n key={job.id}\n status={displayStatus(job)}\n size={GLYPH_SIZE}\n // One ripple per running job, on every row, would turn a calm list into a\n // field of pulses. The run's own glyph already carries the live edge.\n ripple={false}\n tooltip={false}\n />\n ))}\n {hiddenCount > 0 && overflowStatus ? (\n <span className=\"inline-flex items-center gap-[2px]\">\n <WorkflowStatusIcon\n status={overflowStatus}\n size={GLYPH_SIZE}\n ripple={false}\n tooltip={false}\n />\n <Code\n as=\"span\"\n variant=\"label\"\n className=\"tabular-nums text-foreground-neutral-muted\"\n >\n +{overflowCountLabel(hiddenCount)}\n </Code>\n </span>\n ) : null}\n </span>\n </span>\n </TooltipTrigger>\n <TooltipContent>\n <JobStatusStripTooltip jobs={jobs} summary={summary} />\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction JobStatusStripTooltip({jobs, summary}: {jobs: WorkflowRunJobs; summary: string}) {\n // Naming the jobs that need attention is the whole point of hovering; succeeded jobs are\n // left to the counts so the tooltip stays a glance rather than a list. Only previewed jobs\n // can be named, but the count of those left over is read off the totals, so a failure past\n // the preview is still accounted for rather than silently missing.\n const named = jobs.preview\n .filter((job) => NOTABLE_STATUSES.includes(displayStatus(job)))\n .slice(0, MAX_TOOLTIP_JOB_NAMES);\n const notableTotal = NOTABLE_STATUSES.reduce((total, status) => total + countOf(jobs, status), 0);\n const remaining = notableTotal - named.length;\n\n return (\n <span className=\"flex max-w-[280px] flex-col gap-tight\">\n <Text as=\"span\" size=\"xs\" className=\"block\">\n {summary}\n </Text>\n {named.map((job) => (\n <Code as=\"span\" variant=\"label\" key={job.id} className=\"block truncate\">\n {getWorkflowStatusVisual(displayStatus(job)).label.toLowerCase()} · {job.name ?? job.key}\n </Code>\n ))}\n {remaining > 0 ? (\n <Text as=\"span\" size=\"xs\" className=\"block text-foreground-neutral-muted\">\n and {remaining} more\n </Text>\n ) : null}\n </span>\n );\n}\n\n/** \"12 jobs: 9 succeeded, 2 failed, 1 running\" — a count is not an accessible name on its own. */\nexport function jobStatusSummary(jobs: WorkflowRunJobs): string {\n const breakdown = [...jobs.statusCounts]\n .sort((left, right) => STATUS_SEVERITY[right.status] - STATUS_SEVERITY[left.status])\n .map(({status, count}) => `${count} ${getWorkflowStatusVisual(status).label.toLowerCase()}`)\n .join(', ');\n\n return `${jobs.total} ${jobs.total === 1 ? 'job' : 'jobs'}: ${breakdown}`;\n}\n\n/**\n * The worst status among the jobs the strip is not drawing, found by subtracting what it\n * draws from the run's totals rather than by inspecting jobs it was never sent.\n */\nfunction worstHiddenStatus(\n jobs: WorkflowRunJobs,\n visible: readonly WorkflowRunJobSummary[],\n): JobDisplayStatus | null {\n const hidden = new Map(jobs.statusCounts.map(({status, count}) => [status, count]));\n for (const job of visible) {\n const status = displayStatus(job);\n const remaining = (hidden.get(status) ?? 0) - 1;\n if (remaining > 0) hidden.set(status, remaining);\n else hidden.delete(status);\n }\n\n let worst: JobDisplayStatus | null = null;\n for (const [status, count] of hidden) {\n if (count <= 0) continue;\n if (worst === null || STATUS_SEVERITY[status] > STATUS_SEVERITY[worst]) worst = status;\n }\n return worst;\n}\n\nexport function overflowCountLabel(hiddenCount: number): string {\n return hiddenCount <= MAX_EXACT_OVERFLOW_COUNT\n ? String(hiddenCount)\n : COMPACT_COUNT_FORMAT.format(hiddenCount);\n}\n\nfunction countOf(jobs: WorkflowRunJobs, status: JobDisplayStatus): number {\n return jobs.statusCounts.find((entry) => entry.status === status)?.count ?? 0;\n}\n\nfunction displayStatus(job: WorkflowRunJobSummary): JobDisplayStatus {\n return deriveJobDisplayStatus({\n mode: job.mode,\n status: job.status,\n listenerStatus: job.listenerStatus,\n executionStatus: job.executionStatus,\n jobExecutions: [],\n });\n}\n"],"names":["Tooltip","TooltipContent","TooltipTrigger","Code","Text","cn","getWorkflowStatusVisual","WorkflowStatusIcon","deriveJobDisplayStatus","MAX_VISIBLE_JOBS","GLYPH_SIZE","MAX_TOOLTIP_JOB_NAMES","MAX_EXACT_OVERFLOW_COUNT","COMPACT_COUNT_FORMAT","Intl","NumberFormat","notation","maximumFractionDigits","STATUS_SEVERITY","failed","running","listening","pending","cancelled","skipped","succeeded","NOTABLE_STATUSES","JobStatusStrip","jobs","className","total","visible","preview","slice","hiddenCount","length","overflowStatus","worstHiddenStatus","summary","jobStatusSummary","asChild","span","role","aria-label","aria-hidden","map","job","status","displayStatus","size","ripple","tooltip","id","as","variant","overflowCountLabel","JobStatusStripTooltip","named","filter","includes","notableTotal","reduce","countOf","remaining","label","toLowerCase","name","key","breakdown","statusCounts","sort","left","right","count","join","hidden","Map","get","set","delete","worst","String","format","find","entry","mode","listenerStatus","executionStatus","jobExecutions"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type JobExecution, type JobExecutionDisplayDuration } from './job-execution.js';
1
+ import { type JobExecution, type JobExecutionDisplayDuration, type JobExecutionStatus } from './job-execution.js';
2
2
  import type { EvaluationTraceEntry } from './step-attempt.js';
3
3
  export type JobStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'skipped';
4
4
  export type JobDisplayStatus = JobStatus | 'listening';
@@ -82,7 +82,10 @@ export declare class Job {
82
82
  get executionCountVisible(): boolean;
83
83
  }
84
84
  export declare function isTerminalJobStatus(status: JobStatus): boolean;
85
- export declare function deriveJobDisplayStatus(job: Pick<Job, 'mode' | 'status' | 'listenerStatus' | 'jobExecutions'>): JobDisplayStatus;
85
+ export declare function deriveJobDisplayStatus(job: Pick<Job, 'mode' | 'status' | 'listenerStatus' | 'jobExecutions'> & {
86
+ /** List previews carry the selected execution state without its step tree. */
87
+ executionStatus?: JobExecutionStatus | null | undefined;
88
+ }): JobDisplayStatus;
86
89
  export declare function resolveJobExecution(job: Job, jobExecutionId: string | undefined): JobExecution | undefined;
87
90
  export declare function defaultJobExecution(job: Pick<Job, 'jobExecutions'>): JobExecution | undefined;
88
91
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../../src/core/entities/job.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../../src/core/entities/job.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,mBAAmB,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;AACjG,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,CAAC;AACvD,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC;AAC/C,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;AACnE,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,SAAS,GAAG,gBAAgB,GAAG,WAAW,CAAC;AACpF,MAAM,MAAM,eAAe,GACvB,0BAA0B,GAC1B,iBAAiB,GACjB,uBAAuB,GACvB,oBAAoB,GACpB,mBAAmB,GACnB,gBAAgB,GAChB,eAAe,GACf,WAAW,GACX,aAAa,GACb,kBAAkB,GAClB,aAAa,GACb,SAAS,GACT,gBAAgB,CAAC;AACrB,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,KAAK,CAAC;QACR,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;QAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC7B,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;QAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC7B,CAAC,GAAG,IAAI,CAAC;IACV,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE;QACL,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAChC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAChC,GAAG,IAAI,CAAC;IACT,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,MAAM,kBAAkB,GAAG,2BAA2B,CAAC;AAE7D,eAAO,MAAM,qBAAqB,gFAOO,CAAC;AAE1C,eAAO,MAAM,8BAA8B,0DAKF,CAAC;AAI1C,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,SAAS,CAAC;IAClB,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,eAAe,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC;IAC/C,SAAS,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,qBAAa,GAAG;IACd,EAAE,EAAG,MAAM,CAAC;IACZ,YAAY,EAAG,MAAM,CAAC;IACtB,GAAG,EAAG,MAAM,CAAC;IACb,IAAI,EAAG,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAG,OAAO,CAAC;IACf,MAAM,EAAG,SAAS,CAAC;IACnB,YAAY,EAAG,eAAe,GAAG,IAAI,CAAC;IACtC,WAAW,EAAG,OAAO,CAAC;IACtB,OAAO,EAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,OAAO,EAAG,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACzB,eAAe,EAAG,oBAAoB,EAAE,GAAG,IAAI,CAAC;IAChD,SAAS,EAAG,YAAY,GAAG,IAAI,CAAC;IAChC,cAAc,EAAG,cAAc,CAAC;IAChC,gBAAgB,EAAG,gBAAgB,GAAG,IAAI,CAAC;IAC3C,YAAY,EAAG,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAG,MAAM,CAAC;IAClB,SAAS,EAAG,MAAM,CAAC;IACnB,SAAS,EAAG,MAAM,CAAC;IACnB,aAAa,EAAG,YAAY,EAAE,CAAC;IAE/B,YAAY,MAAM,EAAE,SAAS,EAE5B;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,eAAe,IAAI,kBAAkB,GAAG,IAAI,CAI/C;IAED,IAAI,qBAAqB,IAAI,OAAO,CAInC;CACF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAE9D;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,gBAAgB,GAAG,eAAe,CAAC,GAAG;IACvE,8EAA8E;IAC9E,eAAe,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,CAAC;CACzD,GACA,gBAAgB,CAclB;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,GAAG,EACR,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,YAAY,GAAG,SAAS,CAO1B;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,GAAG,YAAY,GAAG,SAAS,CAU7F"}
@@ -36,7 +36,14 @@ export function isTerminalJobStatus(status) {
36
36
  export function deriveJobDisplayStatus(job) {
37
37
  if (isTerminalJobStatus(job.status)) return job.status;
38
38
  if (job.mode === 'listening' && job.listenerStatus === 'listening') return 'listening';
39
- const execution = defaultJobExecution(job);
39
+ const execution = job.executionStatus === undefined ? defaultJobExecution(job) : job.executionStatus === null ? undefined : {
40
+ status: job.executionStatus,
41
+ steps: []
42
+ };
43
+ // A running execution is the shared display rule for both list previews and detail jobs.
44
+ // The list has no step tree, while the detail path can still use the execution's steps for
45
+ // other non-running states.
46
+ if (execution?.status === 'running') return 'running';
40
47
  return execution ? deriveJobExecutionDisplayStatus(execution) : 'pending';
41
48
  }
42
49
  export function resolveJobExecution(job, jobExecutionId) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/entities/job.ts"],"sourcesContent":["import {\n deriveJobExecutionDisplayStatus,\n type JobExecution,\n type JobExecutionDisplayDuration,\n} from './job-execution.js';\nimport type {EvaluationTraceEntry} from './step-attempt.js';\n\nexport type JobStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'skipped';\nexport type JobDisplayStatus = JobStatus | 'listening';\nexport type JobMode = 'one_shot' | 'listening';\nexport type ListenerStatus = 'inactive' | 'listening' | 'resolved';\nexport type ResolutionReason = 'until' | 'timeout' | 'max_executions' | 'cancelled';\nexport type JobStatusReason =\n | 'dependency_not_completed'\n | 'condition_false'\n | 'default_gate_rejected'\n | 'condition_rejected'\n | 'condition_errored'\n | 'user_cancelled'\n | 'run_cancelled'\n | 'timed_out'\n | 'runner_lost'\n | 'output_too_large'\n | 'step_failed'\n | 'unknown'\n | 'output_invalid';\nexport interface JobListening {\n on: Array<{\n source: string;\n event: string;\n inputs?: Record<string, unknown> | undefined;\n filter?: string | undefined;\n }>;\n until: Array<{\n source: string;\n event: string;\n inputs?: Record<string, unknown> | undefined;\n filter?: string | undefined;\n }> | null;\n timeoutMs: number | null;\n maxExecutions: number | null;\n batch: {\n debounceMs?: number | undefined;\n maxSize?: number | undefined;\n maxWaitMs?: number | undefined;\n } | null;\n onResolve: 'finish' | 'cancel';\n executionTimeoutMs: number | null;\n name: string | null;\n}\n\nexport type JobDisplayDuration = JobExecutionDisplayDuration;\n\nexport const WORKFLOW_JOB_STATUSES = [\n 'pending',\n 'running',\n 'succeeded',\n 'failed',\n 'cancelled',\n 'skipped',\n] as const satisfies readonly JobStatus[];\n\nexport const TERMINAL_WORKFLOW_JOB_STATUSES = [\n 'succeeded',\n 'failed',\n 'cancelled',\n 'skipped',\n] as const satisfies readonly JobStatus[];\n\nconst TERMINAL_JOB_STATUS_SET = new Set<JobStatus>(TERMINAL_WORKFLOW_JOB_STATUSES);\n\ninterface JobFields {\n id: string;\n runAttemptId: string;\n key: string;\n name: string | null;\n mode: JobMode;\n status: JobStatus;\n statusReason: JobStatusReason | null;\n carriedOver: boolean;\n outputs: Record<string, unknown> | null;\n success: string | null;\n runner: string[] | null;\n evaluationTrace: EvaluationTraceEntry[] | null;\n listening: JobListening | null;\n listenerStatus: ListenerStatus;\n resolutionReason: ResolutionReason | null;\n dependencies: string[];\n position: number;\n createdAt: string;\n updatedAt: string;\n jobExecutions: JobExecution[];\n}\n\nexport class Job {\n id!: string;\n runAttemptId!: string;\n key!: string;\n name!: string | null;\n mode!: JobMode;\n status!: JobStatus;\n statusReason!: JobStatusReason | null;\n carriedOver!: boolean;\n outputs!: Record<string, unknown> | null;\n success!: string | null;\n runner!: string[] | null;\n evaluationTrace!: EvaluationTraceEntry[] | null;\n listening!: JobListening | null;\n listenerStatus!: ListenerStatus;\n resolutionReason!: ResolutionReason | null;\n dependencies!: string[];\n position!: number;\n createdAt!: string;\n updatedAt!: string;\n jobExecutions!: JobExecution[];\n\n constructor(fields: JobFields) {\n Object.assign(this, fields);\n }\n\n get displayName(): string {\n return this.name ?? this.key;\n }\n\n get displayDuration(): JobDisplayDuration | null {\n if (this.mode === 'listening') return null;\n if (this.jobExecutions.length !== 1) return null;\n return this.jobExecutions[0]?.displayDuration ?? null;\n }\n\n get executionCountVisible(): boolean {\n return (\n this.jobExecutions.length > 0 && (this.mode === 'listening' || this.jobExecutions.length > 1)\n );\n }\n}\n\nexport function isTerminalJobStatus(status: JobStatus): boolean {\n return TERMINAL_JOB_STATUS_SET.has(status);\n}\n\nexport function deriveJobDisplayStatus(\n job: Pick<Job, 'mode' | 'status' | 'listenerStatus' | 'jobExecutions'>,\n): JobDisplayStatus {\n if (isTerminalJobStatus(job.status)) return job.status;\n if (job.mode === 'listening' && job.listenerStatus === 'listening') return 'listening';\n\n const execution = defaultJobExecution(job);\n return execution ? deriveJobExecutionDisplayStatus(execution) : 'pending';\n}\n\nexport function resolveJobExecution(\n job: Job,\n jobExecutionId: string | undefined,\n): JobExecution | undefined {\n const selectedExecution = jobExecutionId\n ? job.jobExecutions.find((jobExecution) => jobExecution.id === jobExecutionId)\n : undefined;\n if (selectedExecution) return selectedExecution;\n\n return defaultJobExecution(job);\n}\n\nexport function defaultJobExecution(job: Pick<Job, 'jobExecutions'>): JobExecution | undefined {\n const runningExecution = job.jobExecutions.find(\n (jobExecution) => jobExecution.status === 'running',\n );\n if (runningExecution) return runningExecution;\n\n return job.jobExecutions.reduce<JobExecution | undefined>((latest, jobExecution) => {\n if (!latest) return jobExecution;\n return jobExecution.sequence > latest.sequence ? jobExecution : latest;\n }, undefined);\n}\n"],"names":["deriveJobExecutionDisplayStatus","WORKFLOW_JOB_STATUSES","TERMINAL_WORKFLOW_JOB_STATUSES","TERMINAL_JOB_STATUS_SET","Set","Job","fields","Object","assign","displayName","name","key","displayDuration","mode","jobExecutions","length","executionCountVisible","isTerminalJobStatus","status","has","deriveJobDisplayStatus","job","listenerStatus","execution","defaultJobExecution","resolveJobExecution","jobExecutionId","selectedExecution","find","jobExecution","id","undefined","runningExecution","reduce","latest","sequence"],"mappings":"AAAA,SACEA,+BAA+B,QAG1B,qBAAqB;AAiD5B,OAAO,MAAMC,wBAAwB;IACnC;IACA;IACA;IACA;IACA;IACA;CACD,CAAyC;AAE1C,OAAO,MAAMC,iCAAiC;IAC5C;IACA;IACA;IACA;CACD,CAAyC;AAE1C,MAAMC,0BAA0B,IAAIC,IAAeF;AAyBnD,OAAO,MAAMG;IAsBX,YAAYC,MAAiB,CAAE;QAC7BC,OAAOC,MAAM,CAAC,IAAI,EAAEF;IACtB;IAEA,IAAIG,cAAsB;QACxB,OAAO,IAAI,CAACC,IAAI,IAAI,IAAI,CAACC,GAAG;IAC9B;IAEA,IAAIC,kBAA6C;QAC/C,IAAI,IAAI,CAACC,IAAI,KAAK,aAAa,OAAO;QACtC,IAAI,IAAI,CAACC,aAAa,CAACC,MAAM,KAAK,GAAG,OAAO;QAC5C,OAAO,IAAI,CAACD,aAAa,CAAC,EAAE,EAAEF,mBAAmB;IACnD;IAEA,IAAII,wBAAiC;QACnC,OACE,IAAI,CAACF,aAAa,CAACC,MAAM,GAAG,KAAM,CAAA,IAAI,CAACF,IAAI,KAAK,eAAe,IAAI,CAACC,aAAa,CAACC,MAAM,GAAG,CAAA;IAE/F;AACF;AAEA,OAAO,SAASE,oBAAoBC,MAAiB;IACnD,OAAOf,wBAAwBgB,GAAG,CAACD;AACrC;AAEA,OAAO,SAASE,uBACdC,GAAsE;IAEtE,IAAIJ,oBAAoBI,IAAIH,MAAM,GAAG,OAAOG,IAAIH,MAAM;IACtD,IAAIG,IAAIR,IAAI,KAAK,eAAeQ,IAAIC,cAAc,KAAK,aAAa,OAAO;IAE3E,MAAMC,YAAYC,oBAAoBH;IACtC,OAAOE,YAAYvB,gCAAgCuB,aAAa;AAClE;AAEA,OAAO,SAASE,oBACdJ,GAAQ,EACRK,cAAkC;IAElC,MAAMC,oBAAoBD,iBACtBL,IAAIP,aAAa,CAACc,IAAI,CAAC,CAACC,eAAiBA,aAAaC,EAAE,KAAKJ,kBAC7DK;IACJ,IAAIJ,mBAAmB,OAAOA;IAE9B,OAAOH,oBAAoBH;AAC7B;AAEA,OAAO,SAASG,oBAAoBH,GAA+B;IACjE,MAAMW,mBAAmBX,IAAIP,aAAa,CAACc,IAAI,CAC7C,CAACC,eAAiBA,aAAaX,MAAM,KAAK;IAE5C,IAAIc,kBAAkB,OAAOA;IAE7B,OAAOX,IAAIP,aAAa,CAACmB,MAAM,CAA2B,CAACC,QAAQL;QACjE,IAAI,CAACK,QAAQ,OAAOL;QACpB,OAAOA,aAAaM,QAAQ,GAAGD,OAAOC,QAAQ,GAAGN,eAAeK;IAClE,GAAGH;AACL"}
1
+ {"version":3,"sources":["../../../src/core/entities/job.ts"],"sourcesContent":["import {\n deriveJobExecutionDisplayStatus,\n type JobExecution,\n type JobExecutionDisplayDuration,\n type JobExecutionStatus,\n} from './job-execution.js';\nimport type {EvaluationTraceEntry} from './step-attempt.js';\n\nexport type JobStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'skipped';\nexport type JobDisplayStatus = JobStatus | 'listening';\nexport type JobMode = 'one_shot' | 'listening';\nexport type ListenerStatus = 'inactive' | 'listening' | 'resolved';\nexport type ResolutionReason = 'until' | 'timeout' | 'max_executions' | 'cancelled';\nexport type JobStatusReason =\n | 'dependency_not_completed'\n | 'condition_false'\n | 'default_gate_rejected'\n | 'condition_rejected'\n | 'condition_errored'\n | 'user_cancelled'\n | 'run_cancelled'\n | 'timed_out'\n | 'runner_lost'\n | 'output_too_large'\n | 'step_failed'\n | 'unknown'\n | 'output_invalid';\nexport interface JobListening {\n on: Array<{\n source: string;\n event: string;\n inputs?: Record<string, unknown> | undefined;\n filter?: string | undefined;\n }>;\n until: Array<{\n source: string;\n event: string;\n inputs?: Record<string, unknown> | undefined;\n filter?: string | undefined;\n }> | null;\n timeoutMs: number | null;\n maxExecutions: number | null;\n batch: {\n debounceMs?: number | undefined;\n maxSize?: number | undefined;\n maxWaitMs?: number | undefined;\n } | null;\n onResolve: 'finish' | 'cancel';\n executionTimeoutMs: number | null;\n name: string | null;\n}\n\nexport type JobDisplayDuration = JobExecutionDisplayDuration;\n\nexport const WORKFLOW_JOB_STATUSES = [\n 'pending',\n 'running',\n 'succeeded',\n 'failed',\n 'cancelled',\n 'skipped',\n] as const satisfies readonly JobStatus[];\n\nexport const TERMINAL_WORKFLOW_JOB_STATUSES = [\n 'succeeded',\n 'failed',\n 'cancelled',\n 'skipped',\n] as const satisfies readonly JobStatus[];\n\nconst TERMINAL_JOB_STATUS_SET = new Set<JobStatus>(TERMINAL_WORKFLOW_JOB_STATUSES);\n\ninterface JobFields {\n id: string;\n runAttemptId: string;\n key: string;\n name: string | null;\n mode: JobMode;\n status: JobStatus;\n statusReason: JobStatusReason | null;\n carriedOver: boolean;\n outputs: Record<string, unknown> | null;\n success: string | null;\n runner: string[] | null;\n evaluationTrace: EvaluationTraceEntry[] | null;\n listening: JobListening | null;\n listenerStatus: ListenerStatus;\n resolutionReason: ResolutionReason | null;\n dependencies: string[];\n position: number;\n createdAt: string;\n updatedAt: string;\n jobExecutions: JobExecution[];\n}\n\nexport class Job {\n id!: string;\n runAttemptId!: string;\n key!: string;\n name!: string | null;\n mode!: JobMode;\n status!: JobStatus;\n statusReason!: JobStatusReason | null;\n carriedOver!: boolean;\n outputs!: Record<string, unknown> | null;\n success!: string | null;\n runner!: string[] | null;\n evaluationTrace!: EvaluationTraceEntry[] | null;\n listening!: JobListening | null;\n listenerStatus!: ListenerStatus;\n resolutionReason!: ResolutionReason | null;\n dependencies!: string[];\n position!: number;\n createdAt!: string;\n updatedAt!: string;\n jobExecutions!: JobExecution[];\n\n constructor(fields: JobFields) {\n Object.assign(this, fields);\n }\n\n get displayName(): string {\n return this.name ?? this.key;\n }\n\n get displayDuration(): JobDisplayDuration | null {\n if (this.mode === 'listening') return null;\n if (this.jobExecutions.length !== 1) return null;\n return this.jobExecutions[0]?.displayDuration ?? null;\n }\n\n get executionCountVisible(): boolean {\n return (\n this.jobExecutions.length > 0 && (this.mode === 'listening' || this.jobExecutions.length > 1)\n );\n }\n}\n\nexport function isTerminalJobStatus(status: JobStatus): boolean {\n return TERMINAL_JOB_STATUS_SET.has(status);\n}\n\nexport function deriveJobDisplayStatus(\n job: Pick<Job, 'mode' | 'status' | 'listenerStatus' | 'jobExecutions'> & {\n /** List previews carry the selected execution state without its step tree. */\n executionStatus?: JobExecutionStatus | null | undefined;\n },\n): JobDisplayStatus {\n if (isTerminalJobStatus(job.status)) return job.status;\n if (job.mode === 'listening' && job.listenerStatus === 'listening') return 'listening';\n const execution =\n job.executionStatus === undefined\n ? defaultJobExecution(job)\n : job.executionStatus === null\n ? undefined\n : {status: job.executionStatus, steps: []};\n // A running execution is the shared display rule for both list previews and detail jobs.\n // The list has no step tree, while the detail path can still use the execution's steps for\n // other non-running states.\n if (execution?.status === 'running') return 'running';\n return execution ? deriveJobExecutionDisplayStatus(execution) : 'pending';\n}\n\nexport function resolveJobExecution(\n job: Job,\n jobExecutionId: string | undefined,\n): JobExecution | undefined {\n const selectedExecution = jobExecutionId\n ? job.jobExecutions.find((jobExecution) => jobExecution.id === jobExecutionId)\n : undefined;\n if (selectedExecution) return selectedExecution;\n\n return defaultJobExecution(job);\n}\n\nexport function defaultJobExecution(job: Pick<Job, 'jobExecutions'>): JobExecution | undefined {\n const runningExecution = job.jobExecutions.find(\n (jobExecution) => jobExecution.status === 'running',\n );\n if (runningExecution) return runningExecution;\n\n return job.jobExecutions.reduce<JobExecution | undefined>((latest, jobExecution) => {\n if (!latest) return jobExecution;\n return jobExecution.sequence > latest.sequence ? jobExecution : latest;\n }, undefined);\n}\n"],"names":["deriveJobExecutionDisplayStatus","WORKFLOW_JOB_STATUSES","TERMINAL_WORKFLOW_JOB_STATUSES","TERMINAL_JOB_STATUS_SET","Set","Job","fields","Object","assign","displayName","name","key","displayDuration","mode","jobExecutions","length","executionCountVisible","isTerminalJobStatus","status","has","deriveJobDisplayStatus","job","listenerStatus","execution","executionStatus","undefined","defaultJobExecution","steps","resolveJobExecution","jobExecutionId","selectedExecution","find","jobExecution","id","runningExecution","reduce","latest","sequence"],"mappings":"AAAA,SACEA,+BAA+B,QAI1B,qBAAqB;AAiD5B,OAAO,MAAMC,wBAAwB;IACnC;IACA;IACA;IACA;IACA;IACA;CACD,CAAyC;AAE1C,OAAO,MAAMC,iCAAiC;IAC5C;IACA;IACA;IACA;CACD,CAAyC;AAE1C,MAAMC,0BAA0B,IAAIC,IAAeF;AAyBnD,OAAO,MAAMG;IAsBX,YAAYC,MAAiB,CAAE;QAC7BC,OAAOC,MAAM,CAAC,IAAI,EAAEF;IACtB;IAEA,IAAIG,cAAsB;QACxB,OAAO,IAAI,CAACC,IAAI,IAAI,IAAI,CAACC,GAAG;IAC9B;IAEA,IAAIC,kBAA6C;QAC/C,IAAI,IAAI,CAACC,IAAI,KAAK,aAAa,OAAO;QACtC,IAAI,IAAI,CAACC,aAAa,CAACC,MAAM,KAAK,GAAG,OAAO;QAC5C,OAAO,IAAI,CAACD,aAAa,CAAC,EAAE,EAAEF,mBAAmB;IACnD;IAEA,IAAII,wBAAiC;QACnC,OACE,IAAI,CAACF,aAAa,CAACC,MAAM,GAAG,KAAM,CAAA,IAAI,CAACF,IAAI,KAAK,eAAe,IAAI,CAACC,aAAa,CAACC,MAAM,GAAG,CAAA;IAE/F;AACF;AAEA,OAAO,SAASE,oBAAoBC,MAAiB;IACnD,OAAOf,wBAAwBgB,GAAG,CAACD;AACrC;AAEA,OAAO,SAASE,uBACdC,GAGC;IAED,IAAIJ,oBAAoBI,IAAIH,MAAM,GAAG,OAAOG,IAAIH,MAAM;IACtD,IAAIG,IAAIR,IAAI,KAAK,eAAeQ,IAAIC,cAAc,KAAK,aAAa,OAAO;IAC3E,MAAMC,YACJF,IAAIG,eAAe,KAAKC,YACpBC,oBAAoBL,OACpBA,IAAIG,eAAe,KAAK,OACtBC,YACA;QAACP,QAAQG,IAAIG,eAAe;QAAEG,OAAO,EAAE;IAAA;IAC/C,yFAAyF;IACzF,2FAA2F;IAC3F,4BAA4B;IAC5B,IAAIJ,WAAWL,WAAW,WAAW,OAAO;IAC5C,OAAOK,YAAYvB,gCAAgCuB,aAAa;AAClE;AAEA,OAAO,SAASK,oBACdP,GAAQ,EACRQ,cAAkC;IAElC,MAAMC,oBAAoBD,iBACtBR,IAAIP,aAAa,CAACiB,IAAI,CAAC,CAACC,eAAiBA,aAAaC,EAAE,KAAKJ,kBAC7DJ;IACJ,IAAIK,mBAAmB,OAAOA;IAE9B,OAAOJ,oBAAoBL;AAC7B;AAEA,OAAO,SAASK,oBAAoBL,GAA+B;IACjE,MAAMa,mBAAmBb,IAAIP,aAAa,CAACiB,IAAI,CAC7C,CAACC,eAAiBA,aAAad,MAAM,KAAK;IAE5C,IAAIgB,kBAAkB,OAAOA;IAE7B,OAAOb,IAAIP,aAAa,CAACqB,MAAM,CAA2B,CAACC,QAAQJ;QACjE,IAAI,CAACI,QAAQ,OAAOJ;QACpB,OAAOA,aAAaK,QAAQ,GAAGD,OAAOC,QAAQ,GAAGL,eAAeI;IAClE,GAAGX;AACL"}
@@ -1,5 +1,5 @@
1
- import { type Job, type JobStatus, WORKFLOW_JOB_STATUSES } from './job.js';
2
- import { type JobExecutionDisplayDuration } from './job-execution.js';
1
+ import { type Job, type JobDisplayStatus, type JobMode, type JobStatus, type ListenerStatus, WORKFLOW_JOB_STATUSES } from './job.js';
2
+ import { type JobExecutionDisplayDuration, type JobExecutionStatus } from './job-execution.js';
3
3
  import type { WorkflowRunAttempt, WorkflowRunAttemptSummary } from './workflow-run-attempt.js';
4
4
  export type WorkflowRunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled';
5
5
  export type WorkflowRunRerunMode = 'all' | 'failed';
@@ -32,10 +32,13 @@ export interface WorkflowRunJobSummary {
32
32
  key: string;
33
33
  name: string | null;
34
34
  status: JobStatus;
35
+ mode: JobMode;
36
+ listenerStatus: ListenerStatus;
37
+ executionStatus: JobExecutionStatus | null;
35
38
  position: number;
36
39
  }
37
40
  export interface WorkflowRunJobStatusCount {
38
- status: JobStatus;
41
+ status: JobDisplayStatus;
39
42
  count: number;
40
43
  }
41
44
  /**
@@ -133,7 +136,7 @@ export interface WorkflowRunProgress {
133
136
  runStatus: WorkflowRunStatus;
134
137
  startedAt: string | null;
135
138
  finishedAt: string | null;
136
- jobStatuses: JobStatus[];
139
+ jobStatuses: JobDisplayStatus[];
137
140
  firstStartedAt?: string | null | undefined;
138
141
  }
139
142
  /** When the run's earliest execution began, or null while none of them has. */
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run.d.ts","sourceRoot":"","sources":["../../../src/core/entities/workflow-run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflow-run.d.ts","sourceRoot":"","sources":["../../../src/core/entities/workflow-run.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/entities/workflow-run.ts"],"sourcesContent":["import {type Job, type JobStatus, WORKFLOW_JOB_STATUSES} from './job.js';\nimport {elapsedTimeFromTimestamps, type JobExecutionDisplayDuration} from './job-execution.js';\nimport type {WorkflowRunAttempt, WorkflowRunAttemptSummary} from './workflow-run-attempt.js';\n\nexport type WorkflowRunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled';\nexport type WorkflowRunRerunMode = 'all' | 'failed';\nexport type WorkflowStatus = WorkflowRunStatus | (typeof WORKFLOW_JOB_STATUSES)[number];\n/**\n * `listening` and `queued` are display-only: the API never returns them, and both are derived\n * from the jobs a run already carries.\n */\nexport type WorkflowDisplayStatus = WorkflowStatus | 'listening' | 'queued';\n\nexport const WORKFLOW_RUN_STATUSES = [\n 'pending',\n 'running',\n 'succeeded',\n 'failed',\n 'cancelled',\n] as const satisfies readonly WorkflowRunStatus[];\n\nexport const WORKFLOW_DISPLAY_STATUSES = [\n ...WORKFLOW_RUN_STATUSES,\n ...WORKFLOW_JOB_STATUSES,\n 'listening',\n 'queued',\n] as const satisfies readonly WorkflowDisplayStatus[];\n\nexport const TERMINAL_WORKFLOW_RUN_STATUSES = [\n 'succeeded',\n 'failed',\n 'cancelled',\n] as const satisfies readonly WorkflowRunStatus[];\n\nconst WORKFLOW_STATUSES = new Set<WorkflowStatus>([\n ...WORKFLOW_RUN_STATUSES,\n ...WORKFLOW_JOB_STATUSES,\n]);\nconst TERMINAL_WORKFLOW_RUN_STATUS_SET = new Set<WorkflowRunStatus>(TERMINAL_WORKFLOW_RUN_STATUSES);\n\nexport interface WorkflowSourceSnapshot {\n content: string;\n format: 'yaml';\n}\n\n/**\n * Provider-neutral trigger facts. Every field is nullable: only source-control triggers\n * resolve a reference at all, and a payload can name a ref without naming an actor.\n */\nexport interface WorkflowRunTriggerReference {\n repository: string | null;\n ref: string | null;\n commit: string | null;\n actor: string | null;\n}\n\n/** One glyph in a run row's job status strip: enough to draw and label it, nothing more. */\nexport interface WorkflowRunJobSummary {\n id: string;\n key: string;\n name: string | null;\n status: JobStatus;\n position: number;\n}\n\nexport interface WorkflowRunJobStatusCount {\n status: JobStatus;\n count: number;\n}\n\n/**\n * A run's jobs as the list receives them: a bounded slice to draw, plus totals covering all\n * of them.\n *\n * `preview` is capped by the API, so `preview.length` is not the job count and the strip\n * reads `total` and `statusCounts` for anything it says rather than anything it draws.\n */\nexport interface WorkflowRunJobs {\n preview: WorkflowRunJobSummary[];\n statusCounts: WorkflowRunJobStatusCount[];\n total: number;\n}\n\nexport interface WorkflowRun {\n id: string;\n projectId: string;\n definitionId: string;\n number: number | null;\n name: string;\n workflowName: string;\n currentAttempt: number;\n triggerProvider: string | null;\n triggerSource: string;\n triggerEvent: string;\n triggerDisplayLabel: string;\n triggerLabel: string;\n triggerPayload: Record<string, unknown>;\n triggerReference: WorkflowRunTriggerReference | null;\n inputs: Record<string, unknown> | null;\n sourceSnapshot: WorkflowSourceSnapshot | null;\n createdAt: string;\n updatedAt: string;\n isTemporary: boolean;\n}\n\n/** A run as the API returns it outside the list: no job strip, because none was fetched. */\nexport interface WorkflowRunRecord extends WorkflowRun {\n status: WorkflowRunStatus;\n latestAttempt: number;\n runAttempt: WorkflowRunAttemptSummary;\n}\n\nexport interface WorkflowRunListItem extends WorkflowRunRecord {\n jobs: WorkflowRunJobs;\n}\n\nexport interface WorkflowRunDetail extends WorkflowRun {\n latestAttempt: number;\n runAttempt: WorkflowRunAttempt;\n jobs: Job[];\n}\n\nexport interface WorkflowRunListPage {\n runs: WorkflowRunListItem[];\n nextCursor: string | null;\n filteredTotalCount: number | null;\n}\n\nexport interface ManualWorkflowLaunch {\n workflowRunId: string;\n}\n\nexport function workflowRunTriggerLabel({\n triggerSource,\n triggerEvent,\n}: {\n triggerSource: string;\n triggerEvent: string;\n}): string {\n return [triggerSource, triggerEvent].filter(Boolean).join(' · ');\n}\n\nexport function workflowRunTriggerDisplayLabel({\n triggerSource,\n triggerEvent,\n}: {\n triggerSource: string;\n triggerEvent: string;\n}): string {\n return triggerEvent || triggerSource;\n}\n\nconst SHORT_COMMIT_LENGTH = 7;\nconst PULL_REQUEST_REF_PATTERN = /^refs\\/pull\\/(\\d+)\\/head$/u;\n\n/**\n * The ref as a person names it: `main` for a branch, `#42` for a pull request, the tag for a\n * tag. An unrecognized ref is shown verbatim rather than hidden, since a ref nobody can read\n * is still better evidence than a blank cell.\n */\nexport function workflowRunBranchLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n const ref = run.triggerReference?.ref;\n if (!ref) return null;\n const pullRequest = PULL_REQUEST_REF_PATTERN.exec(ref);\n if (pullRequest) return `#${pullRequest[1]}`;\n if (ref.startsWith('refs/heads/')) return ref.slice('refs/heads/'.length);\n if (ref.startsWith('refs/tags/')) return ref.slice('refs/tags/'.length);\n return ref;\n}\n\nexport function workflowRunCommitLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n const commit = run.triggerReference?.commit;\n return commit ? commit.slice(0, SHORT_COMMIT_LENGTH) : null;\n}\n\nexport function workflowRunActor(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n return run.triggerReference?.actor ?? null;\n}\n\nexport function isWorkflowRunTerminal(status: WorkflowRunStatus): boolean {\n return TERMINAL_WORKFLOW_RUN_STATUS_SET.has(status);\n}\n\nexport function isWorkflowStatus(status: string): status is WorkflowStatus {\n return WORKFLOW_STATUSES.has(status as WorkflowStatus);\n}\n\n/**\n * A run's headline duration, split the way a job's already is. An attempt's `startedAt` marks\n * when the orchestrator picked the run up, not when work began, so a run whose jobs are all\n * still waiting for a runner reads as queue time rather than as run time.\n */\nexport type WorkflowRunDisplayDuration = JobExecutionDisplayDuration;\n\n/** What every surface shows for a run, derived together so status and duration cannot disagree. */\nexport interface WorkflowRunDisplay {\n status: WorkflowDisplayStatus;\n duration: WorkflowRunDisplayDuration | null;\n}\n\n/**\n * The evidence a surface can offer about a run's progress.\n *\n * `jobStatuses` is what every surface has: the list carries status counts, the detail carries\n * whole jobs. `firstStartedAt` is the detail's extra precision, and where it is absent the\n * attempt's own mark stands in.\n */\nexport interface WorkflowRunProgress {\n runStatus: WorkflowRunStatus;\n startedAt: string | null;\n finishedAt: string | null;\n jobStatuses: JobStatus[];\n firstStartedAt?: string | null | undefined;\n}\n\n/** When the run's earliest execution began, or null while none of them has. */\nexport function workflowRunFirstStartedAt(jobs: Job[]): string | null {\n let earliest: string | null = null;\n let earliestMs = Number.POSITIVE_INFINITY;\n\n for (const job of jobs) {\n for (const {startedAt} of job.jobExecutions) {\n if (startedAt === null) continue;\n const startedMs = new Date(startedAt).getTime();\n if (!Number.isFinite(startedMs) || startedMs >= earliestMs) continue;\n earliest = startedAt;\n earliestMs = startedMs;\n }\n }\n\n return earliest;\n}\n\n/**\n * Whether any work has begun. A run with no jobs on hand is a run whose jobs were not fetched,\n * which is no evidence that nothing started, so it counts as started rather than claiming a\n * queue this surface cannot see.\n */\nfunction workflowRunHasStarted({jobStatuses, firstStartedAt}: WorkflowRunProgress): boolean {\n if (firstStartedAt != null) return true;\n if (jobStatuses.length === 0) return true;\n return jobStatuses.some((status) => status !== 'pending' && status !== 'skipped');\n}\n\n/**\n * The single rule behind every run readout. An attempt's `startedAt` marks when the\n * orchestrator picked the run up, not when work began, so a run whose jobs are all still\n * waiting reads as `Queued` for queue time. Calling that \"running for 2h\" sends an operator to\n * debug a build that never began.\n */\nexport function deriveWorkflowRunDisplay(progress: WorkflowRunProgress): WorkflowRunDisplay {\n const {runStatus, startedAt, finishedAt, firstStartedAt} = progress;\n const hasStarted = workflowRunHasStarted(progress);\n const status = runStatus === 'running' && !hasStarted ? 'queued' : runStatus;\n\n if (startedAt === null) return {status, duration: null};\n\n // A run cancelled before anything started keeps its queue reading rather than reporting a\n // run that never was.\n const time = elapsedTimeFromTimestamps({from: firstStartedAt ?? startedAt, to: finishedAt});\n if (time === null) return {status, duration: null};\n\n return {status, duration: {kind: hasStarted ? 'run' : 'queue', ...time}};\n}\n\n/** The run detail's reading: whole jobs, so queue and run time split on the first execution. */\nexport function workflowRunDetailDisplay(run: {\n runAttempt: Pick<WorkflowRunAttemptSummary, 'status' | 'startedAt' | 'finishedAt'>;\n jobs: Job[];\n}): WorkflowRunDisplay {\n return deriveWorkflowRunDisplay({\n runStatus: run.runAttempt.status,\n startedAt: run.runAttempt.startedAt,\n finishedAt: run.runAttempt.finishedAt,\n jobStatuses: run.jobs.map((job) => job.status),\n firstStartedAt: workflowRunFirstStartedAt(run.jobs),\n });\n}\n\n/**\n * The run list's reading: status counts cover every job, not just the drawn preview, so a row\n * reaches the same verdict as the detail page without fetching a single timestamp more.\n */\nexport function workflowRunListItemDisplay(run: WorkflowRunListItem): WorkflowRunDisplay {\n return deriveWorkflowRunDisplay({\n runStatus: run.status,\n startedAt: run.runAttempt.startedAt,\n finishedAt: run.runAttempt.finishedAt,\n jobStatuses: run.jobs.statusCounts.filter(({count}) => count > 0).map(({status}) => status),\n });\n}\n\n/**\n * The job the run is waiting on: the one queued longest without starting. Named only so a\n * queued run says what it waits for instead of showing a number with no subject.\n */\nexport function workflowRunBlockingJob(jobs: Job[]): Job | null {\n let blocking: Job | null = null;\n let queuedMs = Number.POSITIVE_INFINITY;\n\n for (const job of jobs) {\n for (const {queuedAt, startedAt, finishedAt} of job.jobExecutions) {\n if (queuedAt === null || startedAt !== null || finishedAt !== null) continue;\n const candidateMs = new Date(queuedAt).getTime();\n if (!Number.isFinite(candidateMs) || candidateMs >= queuedMs) continue;\n blocking = job;\n queuedMs = candidateMs;\n }\n }\n\n return blocking;\n}\n"],"names":["WORKFLOW_JOB_STATUSES","elapsedTimeFromTimestamps","WORKFLOW_RUN_STATUSES","WORKFLOW_DISPLAY_STATUSES","TERMINAL_WORKFLOW_RUN_STATUSES","WORKFLOW_STATUSES","Set","TERMINAL_WORKFLOW_RUN_STATUS_SET","workflowRunTriggerLabel","triggerSource","triggerEvent","filter","Boolean","join","workflowRunTriggerDisplayLabel","SHORT_COMMIT_LENGTH","PULL_REQUEST_REF_PATTERN","workflowRunBranchLabel","run","ref","triggerReference","pullRequest","exec","startsWith","slice","length","workflowRunCommitLabel","commit","workflowRunActor","actor","isWorkflowRunTerminal","status","has","isWorkflowStatus","workflowRunFirstStartedAt","jobs","earliest","earliestMs","Number","POSITIVE_INFINITY","job","startedAt","jobExecutions","startedMs","Date","getTime","isFinite","workflowRunHasStarted","jobStatuses","firstStartedAt","some","deriveWorkflowRunDisplay","progress","runStatus","finishedAt","hasStarted","duration","time","from","to","kind","workflowRunDetailDisplay","runAttempt","map","workflowRunListItemDisplay","statusCounts","count","workflowRunBlockingJob","blocking","queuedMs","queuedAt","candidateMs"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/core/entities/workflow-run.ts"],"sourcesContent":["import {\n type Job,\n type JobDisplayStatus,\n type JobMode,\n type JobStatus,\n type ListenerStatus,\n WORKFLOW_JOB_STATUSES,\n} from './job.js';\nimport {\n elapsedTimeFromTimestamps,\n type JobExecutionDisplayDuration,\n type JobExecutionStatus,\n} from './job-execution.js';\nimport type {WorkflowRunAttempt, WorkflowRunAttemptSummary} from './workflow-run-attempt.js';\n\nexport type WorkflowRunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled';\nexport type WorkflowRunRerunMode = 'all' | 'failed';\nexport type WorkflowStatus = WorkflowRunStatus | (typeof WORKFLOW_JOB_STATUSES)[number];\n/**\n * `listening` and `queued` are display-only: the API never returns them, and both are derived\n * from the jobs a run already carries.\n */\nexport type WorkflowDisplayStatus = WorkflowStatus | 'listening' | 'queued';\n\nexport const WORKFLOW_RUN_STATUSES = [\n 'pending',\n 'running',\n 'succeeded',\n 'failed',\n 'cancelled',\n] as const satisfies readonly WorkflowRunStatus[];\n\nexport const WORKFLOW_DISPLAY_STATUSES = [\n ...WORKFLOW_RUN_STATUSES,\n ...WORKFLOW_JOB_STATUSES,\n 'listening',\n 'queued',\n] as const satisfies readonly WorkflowDisplayStatus[];\n\nexport const TERMINAL_WORKFLOW_RUN_STATUSES = [\n 'succeeded',\n 'failed',\n 'cancelled',\n] as const satisfies readonly WorkflowRunStatus[];\n\nconst WORKFLOW_STATUSES = new Set<WorkflowStatus>([\n ...WORKFLOW_RUN_STATUSES,\n ...WORKFLOW_JOB_STATUSES,\n]);\nconst TERMINAL_WORKFLOW_RUN_STATUS_SET = new Set<WorkflowRunStatus>(TERMINAL_WORKFLOW_RUN_STATUSES);\n\nexport interface WorkflowSourceSnapshot {\n content: string;\n format: 'yaml';\n}\n\n/**\n * Provider-neutral trigger facts. Every field is nullable: only source-control triggers\n * resolve a reference at all, and a payload can name a ref without naming an actor.\n */\nexport interface WorkflowRunTriggerReference {\n repository: string | null;\n ref: string | null;\n commit: string | null;\n actor: string | null;\n}\n\n/** One glyph in a run row's job status strip: enough to draw and label it, nothing more. */\nexport interface WorkflowRunJobSummary {\n id: string;\n key: string;\n name: string | null;\n status: JobStatus;\n mode: JobMode;\n listenerStatus: ListenerStatus;\n executionStatus: JobExecutionStatus | null;\n position: number;\n}\n\nexport interface WorkflowRunJobStatusCount {\n status: JobDisplayStatus;\n count: number;\n}\n\n/**\n * A run's jobs as the list receives them: a bounded slice to draw, plus totals covering all\n * of them.\n *\n * `preview` is capped by the API, so `preview.length` is not the job count and the strip\n * reads `total` and `statusCounts` for anything it says rather than anything it draws.\n */\nexport interface WorkflowRunJobs {\n preview: WorkflowRunJobSummary[];\n statusCounts: WorkflowRunJobStatusCount[];\n total: number;\n}\n\nexport interface WorkflowRun {\n id: string;\n projectId: string;\n definitionId: string;\n number: number | null;\n name: string;\n workflowName: string;\n currentAttempt: number;\n triggerProvider: string | null;\n triggerSource: string;\n triggerEvent: string;\n triggerDisplayLabel: string;\n triggerLabel: string;\n triggerPayload: Record<string, unknown>;\n triggerReference: WorkflowRunTriggerReference | null;\n inputs: Record<string, unknown> | null;\n sourceSnapshot: WorkflowSourceSnapshot | null;\n createdAt: string;\n updatedAt: string;\n isTemporary: boolean;\n}\n\n/** A run as the API returns it outside the list: no job strip, because none was fetched. */\nexport interface WorkflowRunRecord extends WorkflowRun {\n status: WorkflowRunStatus;\n latestAttempt: number;\n runAttempt: WorkflowRunAttemptSummary;\n}\n\nexport interface WorkflowRunListItem extends WorkflowRunRecord {\n jobs: WorkflowRunJobs;\n}\n\nexport interface WorkflowRunDetail extends WorkflowRun {\n latestAttempt: number;\n runAttempt: WorkflowRunAttempt;\n jobs: Job[];\n}\n\nexport interface WorkflowRunListPage {\n runs: WorkflowRunListItem[];\n nextCursor: string | null;\n filteredTotalCount: number | null;\n}\n\nexport interface ManualWorkflowLaunch {\n workflowRunId: string;\n}\n\nexport function workflowRunTriggerLabel({\n triggerSource,\n triggerEvent,\n}: {\n triggerSource: string;\n triggerEvent: string;\n}): string {\n return [triggerSource, triggerEvent].filter(Boolean).join(' · ');\n}\n\nexport function workflowRunTriggerDisplayLabel({\n triggerSource,\n triggerEvent,\n}: {\n triggerSource: string;\n triggerEvent: string;\n}): string {\n return triggerEvent || triggerSource;\n}\n\nconst SHORT_COMMIT_LENGTH = 7;\nconst PULL_REQUEST_REF_PATTERN = /^refs\\/pull\\/(\\d+)\\/head$/u;\n\n/**\n * The ref as a person names it: `main` for a branch, `#42` for a pull request, the tag for a\n * tag. An unrecognized ref is shown verbatim rather than hidden, since a ref nobody can read\n * is still better evidence than a blank cell.\n */\nexport function workflowRunBranchLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n const ref = run.triggerReference?.ref;\n if (!ref) return null;\n const pullRequest = PULL_REQUEST_REF_PATTERN.exec(ref);\n if (pullRequest) return `#${pullRequest[1]}`;\n if (ref.startsWith('refs/heads/')) return ref.slice('refs/heads/'.length);\n if (ref.startsWith('refs/tags/')) return ref.slice('refs/tags/'.length);\n return ref;\n}\n\nexport function workflowRunCommitLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n const commit = run.triggerReference?.commit;\n return commit ? commit.slice(0, SHORT_COMMIT_LENGTH) : null;\n}\n\nexport function workflowRunActor(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n return run.triggerReference?.actor ?? null;\n}\n\nexport function isWorkflowRunTerminal(status: WorkflowRunStatus): boolean {\n return TERMINAL_WORKFLOW_RUN_STATUS_SET.has(status);\n}\n\nexport function isWorkflowStatus(status: string): status is WorkflowStatus {\n return WORKFLOW_STATUSES.has(status as WorkflowStatus);\n}\n\n/**\n * A run's headline duration, split the way a job's already is. An attempt's `startedAt` marks\n * when the orchestrator picked the run up, not when work began, so a run whose jobs are all\n * still waiting for a runner reads as queue time rather than as run time.\n */\nexport type WorkflowRunDisplayDuration = JobExecutionDisplayDuration;\n\n/** What every surface shows for a run, derived together so status and duration cannot disagree. */\nexport interface WorkflowRunDisplay {\n status: WorkflowDisplayStatus;\n duration: WorkflowRunDisplayDuration | null;\n}\n\n/**\n * The evidence a surface can offer about a run's progress.\n *\n * `jobStatuses` is what every surface has: the list carries status counts, the detail carries\n * whole jobs. `firstStartedAt` is the detail's extra precision, and where it is absent the\n * attempt's own mark stands in.\n */\nexport interface WorkflowRunProgress {\n runStatus: WorkflowRunStatus;\n startedAt: string | null;\n finishedAt: string | null;\n jobStatuses: JobDisplayStatus[];\n firstStartedAt?: string | null | undefined;\n}\n\n/** When the run's earliest execution began, or null while none of them has. */\nexport function workflowRunFirstStartedAt(jobs: Job[]): string | null {\n let earliest: string | null = null;\n let earliestMs = Number.POSITIVE_INFINITY;\n\n for (const job of jobs) {\n for (const {startedAt} of job.jobExecutions) {\n if (startedAt === null) continue;\n const startedMs = new Date(startedAt).getTime();\n if (!Number.isFinite(startedMs) || startedMs >= earliestMs) continue;\n earliest = startedAt;\n earliestMs = startedMs;\n }\n }\n\n return earliest;\n}\n\n/**\n * Whether any work has begun. A run with no jobs on hand is a run whose jobs were not fetched,\n * which is no evidence that nothing started, so it counts as started rather than claiming a\n * queue this surface cannot see.\n */\nfunction workflowRunHasStarted({jobStatuses, firstStartedAt}: WorkflowRunProgress): boolean {\n if (firstStartedAt != null) return true;\n if (jobStatuses.length === 0) return true;\n return jobStatuses.some((status) => status !== 'pending' && status !== 'skipped');\n}\n\n/**\n * The single rule behind every run readout. An attempt's `startedAt` marks when the\n * orchestrator picked the run up, not when work began, so a run whose jobs are all still\n * waiting reads as `Queued` for queue time. Calling that \"running for 2h\" sends an operator to\n * debug a build that never began.\n */\nexport function deriveWorkflowRunDisplay(progress: WorkflowRunProgress): WorkflowRunDisplay {\n const {runStatus, startedAt, finishedAt, firstStartedAt} = progress;\n const hasStarted = workflowRunHasStarted(progress);\n const status = runStatus === 'running' && !hasStarted ? 'queued' : runStatus;\n\n if (startedAt === null) return {status, duration: null};\n\n // A run cancelled before anything started keeps its queue reading rather than reporting a\n // run that never was.\n const time = elapsedTimeFromTimestamps({from: firstStartedAt ?? startedAt, to: finishedAt});\n if (time === null) return {status, duration: null};\n\n return {status, duration: {kind: hasStarted ? 'run' : 'queue', ...time}};\n}\n\n/** The run detail's reading: whole jobs, so queue and run time split on the first execution. */\nexport function workflowRunDetailDisplay(run: {\n runAttempt: Pick<WorkflowRunAttemptSummary, 'status' | 'startedAt' | 'finishedAt'>;\n jobs: Job[];\n}): WorkflowRunDisplay {\n return deriveWorkflowRunDisplay({\n runStatus: run.runAttempt.status,\n startedAt: run.runAttempt.startedAt,\n finishedAt: run.runAttempt.finishedAt,\n jobStatuses: run.jobs.map((job) => job.status),\n firstStartedAt: workflowRunFirstStartedAt(run.jobs),\n });\n}\n\n/**\n * The run list's reading: status counts cover every job, not just the drawn preview, so a row\n * reaches the same verdict as the detail page without fetching a single timestamp more.\n */\nexport function workflowRunListItemDisplay(run: WorkflowRunListItem): WorkflowRunDisplay {\n return deriveWorkflowRunDisplay({\n runStatus: run.status,\n startedAt: run.runAttempt.startedAt,\n finishedAt: run.runAttempt.finishedAt,\n jobStatuses: run.jobs.statusCounts.filter(({count}) => count > 0).map(({status}) => status),\n });\n}\n\n/**\n * The job the run is waiting on: the one queued longest without starting. Named only so a\n * queued run says what it waits for instead of showing a number with no subject.\n */\nexport function workflowRunBlockingJob(jobs: Job[]): Job | null {\n let blocking: Job | null = null;\n let queuedMs = Number.POSITIVE_INFINITY;\n\n for (const job of jobs) {\n for (const {queuedAt, startedAt, finishedAt} of job.jobExecutions) {\n if (queuedAt === null || startedAt !== null || finishedAt !== null) continue;\n const candidateMs = new Date(queuedAt).getTime();\n if (!Number.isFinite(candidateMs) || candidateMs >= queuedMs) continue;\n blocking = job;\n queuedMs = candidateMs;\n }\n }\n\n return blocking;\n}\n"],"names":["WORKFLOW_JOB_STATUSES","elapsedTimeFromTimestamps","WORKFLOW_RUN_STATUSES","WORKFLOW_DISPLAY_STATUSES","TERMINAL_WORKFLOW_RUN_STATUSES","WORKFLOW_STATUSES","Set","TERMINAL_WORKFLOW_RUN_STATUS_SET","workflowRunTriggerLabel","triggerSource","triggerEvent","filter","Boolean","join","workflowRunTriggerDisplayLabel","SHORT_COMMIT_LENGTH","PULL_REQUEST_REF_PATTERN","workflowRunBranchLabel","run","ref","triggerReference","pullRequest","exec","startsWith","slice","length","workflowRunCommitLabel","commit","workflowRunActor","actor","isWorkflowRunTerminal","status","has","isWorkflowStatus","workflowRunFirstStartedAt","jobs","earliest","earliestMs","Number","POSITIVE_INFINITY","job","startedAt","jobExecutions","startedMs","Date","getTime","isFinite","workflowRunHasStarted","jobStatuses","firstStartedAt","some","deriveWorkflowRunDisplay","progress","runStatus","finishedAt","hasStarted","duration","time","from","to","kind","workflowRunDetailDisplay","runAttempt","map","workflowRunListItemDisplay","statusCounts","count","workflowRunBlockingJob","blocking","queuedMs","queuedAt","candidateMs"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run-mapper.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/workflow-run-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,4BAA4B,EAC5B,cAAc,EAGd,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,EACvB,gCAAgC,EAChC,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,oBAAoB,EACzB,GAAG,EACH,YAAY,EAEZ,KAAK,IAAI,EACT,WAAW,EAGX,KAAK,WAAW,EAChB,kBAAkB,EAElB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EAGvB,MAAM,uBAAuB,CAAC;AAE/B,wBAAgB,aAAa,CAAC,GAAG,EAAE,sBAAsB,GAAG,WAAW,CA8BtE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,qBAAqB,GAAG,kBAAkB,CAWnF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,sBAAsB,GAAG,iBAAiB,CAclF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,sBAAsB,GAAG,mBAAmB,CAkBtF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,0BAA0B,GAAG,mBAAmB,CAM1F;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,4BAA4B,GAAG,iBAAiB,CAOxF;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,uBAAuB,GAAG,GAAG,CAuBvD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,gCAAgC,GAAG,YAAY,CAqBlF;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,wBAAwB,GAAG,IAAI,CA+B1D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,GAAG,WAAW,CAkBtF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,4BAA4B;IAEjE,MAAM;IACN,OAAO;IACP,cAAc;IACd,MAAM;IACN,eAAe;EAElB"}
1
+ {"version":3,"file":"workflow-run-mapper.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/workflow-run-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,4BAA4B,EAC5B,cAAc,EAGd,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,EACvB,gCAAgC,EAChC,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,oBAAoB,EACzB,GAAG,EACH,YAAY,EAEZ,KAAK,IAAI,EACT,WAAW,EAGX,KAAK,WAAW,EAChB,kBAAkB,EAElB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EAGvB,MAAM,uBAAuB,CAAC;AAE/B,wBAAgB,aAAa,CAAC,GAAG,EAAE,sBAAsB,GAAG,WAAW,CA8BtE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,qBAAqB,GAAG,kBAAkB,CAWnF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,sBAAsB,GAAG,iBAAiB,CAclF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,sBAAsB,GAAG,mBAAmB,CA6BtF;AAQD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,0BAA0B,GAAG,mBAAmB,CAM1F;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,4BAA4B,GAAG,iBAAiB,CAOxF;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,uBAAuB,GAAG,GAAG,CAuBvD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,gCAAgC,GAAG,YAAY,CAqBlF;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,wBAAwB,GAAG,IAAI,CA+B1D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,GAAG,WAAW,CAkBtF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,4BAA4B;IAEjE,MAAM;IACN,OAAO;IACP,cAAc;IACd,MAAM;IACN,eAAe;EAElB"}
@@ -59,7 +59,8 @@ export function toWorkflowRunRecord(dto) {
59
59
  };
60
60
  }
61
61
  export function toWorkflowRunListItem(dto) {
62
- const statusCounts = dto.job_status_counts.map(({ status, count })=>({
62
+ const hasDisplayStatusCounts = dto.job_display_status_counts !== undefined;
63
+ const statusCounts = (dto.job_display_status_counts ?? dto.job_status_counts).map(({ status, count })=>({
63
64
  status,
64
65
  count
65
66
  }));
@@ -71,6 +72,12 @@ export function toWorkflowRunListItem(dto) {
71
72
  key: job.key,
72
73
  name: job.name,
73
74
  status: job.status,
75
+ mode: job.mode ?? 'one_shot',
76
+ listenerStatus: job.listener_status ?? 'inactive',
77
+ // The optional display-count field is the rollout capability signal. Pre-display API
78
+ // responses only carry raw verdict counts, so mirror their non-terminal verdict into
79
+ // execution evidence to keep each legacy glyph aligned with those fallback counts.
80
+ executionStatus: hasDisplayStatusCounts ? job.execution_status ?? null : legacyExecutionStatus(job.status),
74
81
  position: job.position
75
82
  })),
76
83
  statusCounts,
@@ -80,6 +87,9 @@ export function toWorkflowRunListItem(dto) {
80
87
  }
81
88
  };
82
89
  }
90
+ function legacyExecutionStatus(status) {
91
+ return status === 'pending' || status === 'running' ? status : null;
92
+ }
83
93
  export function toWorkflowRunListPage(dto) {
84
94
  return {
85
95
  runs: dto.runs.map(toWorkflowRunListItem),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/api/workflow-run-mapper.ts"],"sourcesContent":["import type {\n EvaluationTraceDto,\n JobListeningDto,\n StepAttemptDetailResponseDto,\n StepAttemptDto,\n StepGateResultDto,\n WorkflowExecutionEventDto,\n WorkflowRunAttemptDto,\n WorkflowRunDetailResponseDto,\n WorkflowRunJobDetailDto,\n WorkflowRunJobExecutionDetailDto,\n WorkflowRunListItemDto,\n WorkflowRunListResponseDto,\n WorkflowRunResponseDto,\n WorkflowRunStepDetailDto,\n} from '@shipfox/api-workflows-dto';\nimport {\n type EvaluationTraceEntry,\n Job,\n JobExecution,\n type JobListening,\n type Step,\n StepAttempt,\n type StepGateResult,\n type WorkflowExecutionEvent,\n type WorkflowRun,\n WorkflowRunAttempt,\n WorkflowRunAttemptSummary,\n type WorkflowRunDetail,\n type WorkflowRunListItem,\n type WorkflowRunListPage,\n type WorkflowRunRecord,\n workflowRunTriggerDisplayLabel,\n workflowRunTriggerLabel,\n} from '#core/workflow-run.js';\n\nexport function toWorkflowRun(dto: WorkflowRunResponseDto): WorkflowRun {\n return {\n id: dto.id,\n projectId: dto.project_id,\n definitionId: dto.definition_id,\n number: dto.number,\n name: dto.name,\n workflowName: dto.workflow_name,\n currentAttempt: dto.current_attempt,\n triggerProvider: dto.trigger_provider,\n triggerSource: dto.trigger_source,\n triggerEvent: dto.trigger_event,\n triggerDisplayLabel: workflowRunTriggerDisplayLabel({\n triggerSource: dto.trigger_source,\n triggerEvent: dto.trigger_event,\n }),\n triggerLabel: workflowRunTriggerLabel({\n triggerSource: dto.trigger_source,\n triggerEvent: dto.trigger_event,\n }),\n triggerPayload: dto.trigger_payload,\n triggerReference: dto.trigger_reference,\n inputs: dto.inputs ?? null,\n sourceSnapshot: dto.source_snapshot\n ? {content: dto.source_snapshot.content, format: dto.source_snapshot.format}\n : null,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n isTemporary: dto.id.startsWith('temp-'),\n };\n}\n\nexport function toWorkflowRunAttempt(dto: WorkflowRunAttemptDto): WorkflowRunAttempt {\n return new WorkflowRunAttempt({\n id: dto.id,\n workflowRunId: dto.workflow_run_id,\n attempt: dto.attempt,\n status: dto.status,\n createdAt: dto.created_at,\n startedAt: dto.started_at ?? null,\n finishedAt: dto.finished_at ?? null,\n rerunMode: dto.rerun_mode,\n });\n}\n\nexport function toWorkflowRunRecord(dto: WorkflowRunResponseDto): WorkflowRunRecord {\n return {\n ...toWorkflowRun(dto),\n status: dto.status,\n latestAttempt: dto.latest_attempt,\n runAttempt: new WorkflowRunAttemptSummary({\n workflowRunId: dto.id,\n attempt: dto.current_attempt,\n status: dto.status,\n createdAt: dto.created_at,\n startedAt: dto.started_at ?? null,\n finishedAt: dto.finished_at ?? null,\n }),\n };\n}\n\nexport function toWorkflowRunListItem(dto: WorkflowRunListItemDto): WorkflowRunListItem {\n const statusCounts = dto.job_status_counts.map(({status, count}) => ({status, count}));\n return {\n ...toWorkflowRunRecord(dto),\n jobs: {\n preview: dto.jobs.map((job) => ({\n id: job.id,\n key: job.key,\n name: job.name,\n status: job.status,\n position: job.position,\n })),\n statusCounts,\n // Derived rather than sent: the counts already cover every job, and a separate total\n // would be a second source of truth that could disagree with them.\n total: statusCounts.reduce((sum, entry) => sum + entry.count, 0),\n },\n };\n}\n\nexport function toWorkflowRunListPage(dto: WorkflowRunListResponseDto): WorkflowRunListPage {\n return {\n runs: dto.runs.map(toWorkflowRunListItem),\n nextCursor: dto.next_cursor,\n filteredTotalCount: dto.filtered_total_count,\n };\n}\n\nexport function toWorkflowRunDetail(dto: WorkflowRunDetailResponseDto): WorkflowRunDetail {\n return {\n ...toWorkflowRun(dto),\n latestAttempt: dto.latest_attempt,\n runAttempt: toWorkflowRunAttempt(dto.run_attempt),\n jobs: dto.jobs.map(toJob),\n };\n}\n\nexport function toJob(dto: WorkflowRunJobDetailDto): Job {\n return new Job({\n id: dto.id,\n runAttemptId: dto.run_attempt_id,\n key: dto.key,\n name: dto.name,\n mode: dto.mode,\n status: dto.status,\n statusReason: dto.status_reason,\n carriedOver: dto.carried_over,\n outputs: dto.outputs ?? null,\n success: dto.success ?? null,\n runner: dto.runner ?? null,\n evaluationTrace: toEvaluationTrace(dto.evaluation_trace),\n listening: dto.listening ? toJobListening(dto.listening) : null,\n listenerStatus: dto.listener_status,\n resolutionReason: dto.resolution_reason,\n dependencies: dto.dependencies,\n position: dto.position,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n jobExecutions: dto.job_executions.map(toJobExecution),\n });\n}\n\nexport function toJobExecution(dto: WorkflowRunJobExecutionDetailDto): JobExecution {\n return new JobExecution({\n id: dto.id,\n jobId: dto.job_id,\n sequence: dto.sequence,\n name: dto.name,\n status: dto.status,\n statusReason: dto.status_reason,\n statusReasonMessage: dto.status_reason_message ?? null,\n runner: dto.runner ?? null,\n outputs: dto.outputs ?? null,\n triggerEvents: (dto.trigger_events ?? []).map(toWorkflowExecutionEvent),\n queuedAt: dto.queued_at ?? null,\n startedAt: dto.started_at ?? null,\n finishedAt: dto.finished_at ?? null,\n timedOutAt: dto.timed_out_at ?? null,\n evaluationTrace: toEvaluationTrace(dto.evaluation_trace),\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n steps: dto.steps.map(toStep),\n });\n}\n\nexport function toStep(dto: WorkflowRunStepDetailDto): Step {\n return {\n id: dto.id,\n jobExecutionId: dto.job_execution_id,\n key: dto.key,\n name: dto.name,\n sourceLocation: dto.source_location\n ? {startLine: dto.source_location.start_line, endLine: dto.source_location.end_line}\n : null,\n status: dto.status,\n statusReason: dto.status_reason,\n type: dto.type,\n config: dto.config,\n evaluationTrace: toEvaluationTrace(dto.evaluation_trace),\n agentConfig: toAgentStepConfig(dto),\n error: dto.error\n ? {\n message: dto.error.message,\n exitCode: dto.error.exit_code ?? null,\n signal: dto.error.signal,\n reason: dto.error.reason,\n agentConfigIssue: dto.error.agent_config_issue,\n category: dto.error.category,\n }\n : null,\n position: dto.position,\n currentAttempt: dto.current_attempt,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n attempts: dto.attempts.map((attempt) => toStepAttempt(attempt, dto.job_execution_id)),\n };\n}\n\nexport function toStepAttempt(dto: StepAttemptDto, jobExecutionId: string): StepAttempt {\n return new StepAttempt({\n id: dto.id,\n stepId: dto.step_id,\n jobExecutionId,\n attempt: dto.attempt,\n executionOrder: dto.execution_order,\n status: dto.status,\n exitCode: dto.exit_code ?? null,\n output: dto.output ?? null,\n outputs: dto.outputs ?? dto.output ?? null,\n response: dto.response ?? null,\n error: dto.error ?? null,\n gateResult: toStepGateResult(dto.gate_result),\n restartFeedback: dto.restart_feedback ?? null,\n startedAt: dto.started_at,\n finishedAt: dto.finished_at ?? null,\n });\n}\n\nexport function toStepAttemptDetail(dto: StepAttemptDetailResponseDto) {\n return {\n stepId: dto.step_id,\n attempt: dto.attempt,\n authoredConfig: dto.authored_config,\n config: dto.config,\n evaluationTrace: toEvaluationTrace(dto.evaluation_trace),\n };\n}\n\nfunction toJobListening(dto: JobListeningDto): JobListening {\n return {\n on: dto.on,\n until: dto.until,\n timeoutMs: dto.timeout_ms,\n maxExecutions: dto.max_executions,\n batch: dto.batch\n ? {\n debounceMs: dto.batch.debounce_ms,\n maxSize: dto.batch.max_size,\n maxWaitMs: dto.batch.max_wait_ms,\n }\n : null,\n onResolve: dto.on_resolve,\n executionTimeoutMs: dto.execution_timeout_ms,\n name: dto.name,\n };\n}\n\nfunction toWorkflowExecutionEvent(dto: WorkflowExecutionEventDto): WorkflowExecutionEvent {\n return {\n source: dto.source,\n event: dto.event,\n deliveryId: dto.delivery_id,\n receivedAt: dto.received_at,\n project: dto.project,\n repository: dto.repository,\n ref: dto.ref,\n commit: dto.commit,\n data: dto.data,\n };\n}\n\nfunction toStepGateResult(dto: StepGateResultDto): StepGateResult {\n if (dto === null || dto.kind === 'none' || dto.kind === 'not_evaluated') return dto;\n if (dto.kind === 'passed' || dto.kind === 'failed') return {...dto, exitCode: dto.exit_code};\n if (dto.kind === 'uncheckable' || dto.kind === 'evaluation_error')\n return {...dto, exitCode: dto.exit_code};\n return dto;\n}\n\nfunction toEvaluationTrace(trace: EvaluationTraceDto | null): EvaluationTraceEntry[] | null {\n return (\n trace?.map((entry) =>\n 'dropped' in entry\n ? entry\n : {\n expression: entry.expression,\n roots: entry.roots,\n fillTarget: entry.fill_target,\n evaluatedAt: entry.evaluated_at,\n field: entry.field,\n ...(entry.value === undefined ? {} : {value: entry.value}),\n ...(entry.truncated === undefined ? {} : {truncated: entry.truncated}),\n ...(entry.expr_truncated === undefined ? {} : {exprTruncated: entry.expr_truncated}),\n ...(entry.reference === undefined ? {} : {reference: entry.reference}),\n ...(entry.degraded === undefined ? {} : {degraded: entry.degraded}),\n ...(entry.env_key === undefined ? {} : {envKey: entry.env_key}),\n },\n ) ?? null\n );\n}\n\nfunction toAgentStepConfig(dto: WorkflowRunStepDetailDto): Step['agentConfig'] {\n if (dto.type !== 'agent') return null;\n return {\n provider: stringConfigValue(dto.config.provider),\n model: stringConfigValue(dto.config.model),\n thinking: stringConfigValue(dto.config.thinking),\n };\n}\n\nfunction stringConfigValue(value: unknown): string | null {\n return typeof value === 'string' && value.trim() ? value.trim() : null;\n}\n"],"names":["Job","JobExecution","StepAttempt","WorkflowRunAttempt","WorkflowRunAttemptSummary","workflowRunTriggerDisplayLabel","workflowRunTriggerLabel","toWorkflowRun","dto","id","projectId","project_id","definitionId","definition_id","number","name","workflowName","workflow_name","currentAttempt","current_attempt","triggerProvider","trigger_provider","triggerSource","trigger_source","triggerEvent","trigger_event","triggerDisplayLabel","triggerLabel","triggerPayload","trigger_payload","triggerReference","trigger_reference","inputs","sourceSnapshot","source_snapshot","content","format","createdAt","created_at","updatedAt","updated_at","isTemporary","startsWith","toWorkflowRunAttempt","workflowRunId","workflow_run_id","attempt","status","startedAt","started_at","finishedAt","finished_at","rerunMode","rerun_mode","toWorkflowRunRecord","latestAttempt","latest_attempt","runAttempt","toWorkflowRunListItem","statusCounts","job_status_counts","map","count","jobs","preview","job","key","position","total","reduce","sum","entry","toWorkflowRunListPage","runs","nextCursor","next_cursor","filteredTotalCount","filtered_total_count","toWorkflowRunDetail","run_attempt","toJob","runAttemptId","run_attempt_id","mode","statusReason","status_reason","carriedOver","carried_over","outputs","success","runner","evaluationTrace","toEvaluationTrace","evaluation_trace","listening","toJobListening","listenerStatus","listener_status","resolutionReason","resolution_reason","dependencies","jobExecutions","job_executions","toJobExecution","jobId","job_id","sequence","statusReasonMessage","status_reason_message","triggerEvents","trigger_events","toWorkflowExecutionEvent","queuedAt","queued_at","timedOutAt","timed_out_at","steps","toStep","jobExecutionId","job_execution_id","sourceLocation","source_location","startLine","start_line","endLine","end_line","type","config","agentConfig","toAgentStepConfig","error","message","exitCode","exit_code","signal","reason","agentConfigIssue","agent_config_issue","category","attempts","toStepAttempt","stepId","step_id","executionOrder","execution_order","output","response","gateResult","toStepGateResult","gate_result","restartFeedback","restart_feedback","toStepAttemptDetail","authoredConfig","authored_config","on","until","timeoutMs","timeout_ms","maxExecutions","max_executions","batch","debounceMs","debounce_ms","maxSize","max_size","maxWaitMs","max_wait_ms","onResolve","on_resolve","executionTimeoutMs","execution_timeout_ms","source","event","deliveryId","delivery_id","receivedAt","received_at","project","repository","ref","commit","data","kind","trace","expression","roots","fillTarget","fill_target","evaluatedAt","evaluated_at","field","value","undefined","truncated","expr_truncated","exprTruncated","reference","degraded","env_key","envKey","provider","stringConfigValue","model","thinking","trim"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/hooks/api/workflow-run-mapper.ts"],"sourcesContent":["import type {\n EvaluationTraceDto,\n JobListeningDto,\n StepAttemptDetailResponseDto,\n StepAttemptDto,\n StepGateResultDto,\n WorkflowExecutionEventDto,\n WorkflowRunAttemptDto,\n WorkflowRunDetailResponseDto,\n WorkflowRunJobDetailDto,\n WorkflowRunJobExecutionDetailDto,\n WorkflowRunListItemDto,\n WorkflowRunListResponseDto,\n WorkflowRunResponseDto,\n WorkflowRunStepDetailDto,\n} from '@shipfox/api-workflows-dto';\nimport {\n type EvaluationTraceEntry,\n Job,\n JobExecution,\n type JobListening,\n type Step,\n StepAttempt,\n type StepGateResult,\n type WorkflowExecutionEvent,\n type WorkflowRun,\n WorkflowRunAttempt,\n WorkflowRunAttemptSummary,\n type WorkflowRunDetail,\n type WorkflowRunListItem,\n type WorkflowRunListPage,\n type WorkflowRunRecord,\n workflowRunTriggerDisplayLabel,\n workflowRunTriggerLabel,\n} from '#core/workflow-run.js';\n\nexport function toWorkflowRun(dto: WorkflowRunResponseDto): WorkflowRun {\n return {\n id: dto.id,\n projectId: dto.project_id,\n definitionId: dto.definition_id,\n number: dto.number,\n name: dto.name,\n workflowName: dto.workflow_name,\n currentAttempt: dto.current_attempt,\n triggerProvider: dto.trigger_provider,\n triggerSource: dto.trigger_source,\n triggerEvent: dto.trigger_event,\n triggerDisplayLabel: workflowRunTriggerDisplayLabel({\n triggerSource: dto.trigger_source,\n triggerEvent: dto.trigger_event,\n }),\n triggerLabel: workflowRunTriggerLabel({\n triggerSource: dto.trigger_source,\n triggerEvent: dto.trigger_event,\n }),\n triggerPayload: dto.trigger_payload,\n triggerReference: dto.trigger_reference,\n inputs: dto.inputs ?? null,\n sourceSnapshot: dto.source_snapshot\n ? {content: dto.source_snapshot.content, format: dto.source_snapshot.format}\n : null,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n isTemporary: dto.id.startsWith('temp-'),\n };\n}\n\nexport function toWorkflowRunAttempt(dto: WorkflowRunAttemptDto): WorkflowRunAttempt {\n return new WorkflowRunAttempt({\n id: dto.id,\n workflowRunId: dto.workflow_run_id,\n attempt: dto.attempt,\n status: dto.status,\n createdAt: dto.created_at,\n startedAt: dto.started_at ?? null,\n finishedAt: dto.finished_at ?? null,\n rerunMode: dto.rerun_mode,\n });\n}\n\nexport function toWorkflowRunRecord(dto: WorkflowRunResponseDto): WorkflowRunRecord {\n return {\n ...toWorkflowRun(dto),\n status: dto.status,\n latestAttempt: dto.latest_attempt,\n runAttempt: new WorkflowRunAttemptSummary({\n workflowRunId: dto.id,\n attempt: dto.current_attempt,\n status: dto.status,\n createdAt: dto.created_at,\n startedAt: dto.started_at ?? null,\n finishedAt: dto.finished_at ?? null,\n }),\n };\n}\n\nexport function toWorkflowRunListItem(dto: WorkflowRunListItemDto): WorkflowRunListItem {\n const hasDisplayStatusCounts = dto.job_display_status_counts !== undefined;\n const statusCounts = (dto.job_display_status_counts ?? dto.job_status_counts).map(\n ({status, count}) => ({status, count}),\n );\n return {\n ...toWorkflowRunRecord(dto),\n jobs: {\n preview: dto.jobs.map((job) => ({\n id: job.id,\n key: job.key,\n name: job.name,\n status: job.status,\n mode: job.mode ?? 'one_shot',\n listenerStatus: job.listener_status ?? 'inactive',\n // The optional display-count field is the rollout capability signal. Pre-display API\n // responses only carry raw verdict counts, so mirror their non-terminal verdict into\n // execution evidence to keep each legacy glyph aligned with those fallback counts.\n executionStatus: hasDisplayStatusCounts\n ? (job.execution_status ?? null)\n : legacyExecutionStatus(job.status),\n position: job.position,\n })),\n statusCounts,\n // Derived rather than sent: the counts already cover every job, and a separate total\n // would be a second source of truth that could disagree with them.\n total: statusCounts.reduce((sum, entry) => sum + entry.count, 0),\n },\n };\n}\n\nfunction legacyExecutionStatus(\n status: WorkflowRunListItemDto['jobs'][number]['status'],\n): 'pending' | 'running' | null {\n return status === 'pending' || status === 'running' ? status : null;\n}\n\nexport function toWorkflowRunListPage(dto: WorkflowRunListResponseDto): WorkflowRunListPage {\n return {\n runs: dto.runs.map(toWorkflowRunListItem),\n nextCursor: dto.next_cursor,\n filteredTotalCount: dto.filtered_total_count,\n };\n}\n\nexport function toWorkflowRunDetail(dto: WorkflowRunDetailResponseDto): WorkflowRunDetail {\n return {\n ...toWorkflowRun(dto),\n latestAttempt: dto.latest_attempt,\n runAttempt: toWorkflowRunAttempt(dto.run_attempt),\n jobs: dto.jobs.map(toJob),\n };\n}\n\nexport function toJob(dto: WorkflowRunJobDetailDto): Job {\n return new Job({\n id: dto.id,\n runAttemptId: dto.run_attempt_id,\n key: dto.key,\n name: dto.name,\n mode: dto.mode,\n status: dto.status,\n statusReason: dto.status_reason,\n carriedOver: dto.carried_over,\n outputs: dto.outputs ?? null,\n success: dto.success ?? null,\n runner: dto.runner ?? null,\n evaluationTrace: toEvaluationTrace(dto.evaluation_trace),\n listening: dto.listening ? toJobListening(dto.listening) : null,\n listenerStatus: dto.listener_status,\n resolutionReason: dto.resolution_reason,\n dependencies: dto.dependencies,\n position: dto.position,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n jobExecutions: dto.job_executions.map(toJobExecution),\n });\n}\n\nexport function toJobExecution(dto: WorkflowRunJobExecutionDetailDto): JobExecution {\n return new JobExecution({\n id: dto.id,\n jobId: dto.job_id,\n sequence: dto.sequence,\n name: dto.name,\n status: dto.status,\n statusReason: dto.status_reason,\n statusReasonMessage: dto.status_reason_message ?? null,\n runner: dto.runner ?? null,\n outputs: dto.outputs ?? null,\n triggerEvents: (dto.trigger_events ?? []).map(toWorkflowExecutionEvent),\n queuedAt: dto.queued_at ?? null,\n startedAt: dto.started_at ?? null,\n finishedAt: dto.finished_at ?? null,\n timedOutAt: dto.timed_out_at ?? null,\n evaluationTrace: toEvaluationTrace(dto.evaluation_trace),\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n steps: dto.steps.map(toStep),\n });\n}\n\nexport function toStep(dto: WorkflowRunStepDetailDto): Step {\n return {\n id: dto.id,\n jobExecutionId: dto.job_execution_id,\n key: dto.key,\n name: dto.name,\n sourceLocation: dto.source_location\n ? {startLine: dto.source_location.start_line, endLine: dto.source_location.end_line}\n : null,\n status: dto.status,\n statusReason: dto.status_reason,\n type: dto.type,\n config: dto.config,\n evaluationTrace: toEvaluationTrace(dto.evaluation_trace),\n agentConfig: toAgentStepConfig(dto),\n error: dto.error\n ? {\n message: dto.error.message,\n exitCode: dto.error.exit_code ?? null,\n signal: dto.error.signal,\n reason: dto.error.reason,\n agentConfigIssue: dto.error.agent_config_issue,\n category: dto.error.category,\n }\n : null,\n position: dto.position,\n currentAttempt: dto.current_attempt,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n attempts: dto.attempts.map((attempt) => toStepAttempt(attempt, dto.job_execution_id)),\n };\n}\n\nexport function toStepAttempt(dto: StepAttemptDto, jobExecutionId: string): StepAttempt {\n return new StepAttempt({\n id: dto.id,\n stepId: dto.step_id,\n jobExecutionId,\n attempt: dto.attempt,\n executionOrder: dto.execution_order,\n status: dto.status,\n exitCode: dto.exit_code ?? null,\n output: dto.output ?? null,\n outputs: dto.outputs ?? dto.output ?? null,\n response: dto.response ?? null,\n error: dto.error ?? null,\n gateResult: toStepGateResult(dto.gate_result),\n restartFeedback: dto.restart_feedback ?? null,\n startedAt: dto.started_at,\n finishedAt: dto.finished_at ?? null,\n });\n}\n\nexport function toStepAttemptDetail(dto: StepAttemptDetailResponseDto) {\n return {\n stepId: dto.step_id,\n attempt: dto.attempt,\n authoredConfig: dto.authored_config,\n config: dto.config,\n evaluationTrace: toEvaluationTrace(dto.evaluation_trace),\n };\n}\n\nfunction toJobListening(dto: JobListeningDto): JobListening {\n return {\n on: dto.on,\n until: dto.until,\n timeoutMs: dto.timeout_ms,\n maxExecutions: dto.max_executions,\n batch: dto.batch\n ? {\n debounceMs: dto.batch.debounce_ms,\n maxSize: dto.batch.max_size,\n maxWaitMs: dto.batch.max_wait_ms,\n }\n : null,\n onResolve: dto.on_resolve,\n executionTimeoutMs: dto.execution_timeout_ms,\n name: dto.name,\n };\n}\n\nfunction toWorkflowExecutionEvent(dto: WorkflowExecutionEventDto): WorkflowExecutionEvent {\n return {\n source: dto.source,\n event: dto.event,\n deliveryId: dto.delivery_id,\n receivedAt: dto.received_at,\n project: dto.project,\n repository: dto.repository,\n ref: dto.ref,\n commit: dto.commit,\n data: dto.data,\n };\n}\n\nfunction toStepGateResult(dto: StepGateResultDto): StepGateResult {\n if (dto === null || dto.kind === 'none' || dto.kind === 'not_evaluated') return dto;\n if (dto.kind === 'passed' || dto.kind === 'failed') return {...dto, exitCode: dto.exit_code};\n if (dto.kind === 'uncheckable' || dto.kind === 'evaluation_error')\n return {...dto, exitCode: dto.exit_code};\n return dto;\n}\n\nfunction toEvaluationTrace(trace: EvaluationTraceDto | null): EvaluationTraceEntry[] | null {\n return (\n trace?.map((entry) =>\n 'dropped' in entry\n ? entry\n : {\n expression: entry.expression,\n roots: entry.roots,\n fillTarget: entry.fill_target,\n evaluatedAt: entry.evaluated_at,\n field: entry.field,\n ...(entry.value === undefined ? {} : {value: entry.value}),\n ...(entry.truncated === undefined ? {} : {truncated: entry.truncated}),\n ...(entry.expr_truncated === undefined ? {} : {exprTruncated: entry.expr_truncated}),\n ...(entry.reference === undefined ? {} : {reference: entry.reference}),\n ...(entry.degraded === undefined ? {} : {degraded: entry.degraded}),\n ...(entry.env_key === undefined ? {} : {envKey: entry.env_key}),\n },\n ) ?? null\n );\n}\n\nfunction toAgentStepConfig(dto: WorkflowRunStepDetailDto): Step['agentConfig'] {\n if (dto.type !== 'agent') return null;\n return {\n provider: stringConfigValue(dto.config.provider),\n model: stringConfigValue(dto.config.model),\n thinking: stringConfigValue(dto.config.thinking),\n };\n}\n\nfunction stringConfigValue(value: unknown): string | null {\n return typeof value === 'string' && value.trim() ? value.trim() : null;\n}\n"],"names":["Job","JobExecution","StepAttempt","WorkflowRunAttempt","WorkflowRunAttemptSummary","workflowRunTriggerDisplayLabel","workflowRunTriggerLabel","toWorkflowRun","dto","id","projectId","project_id","definitionId","definition_id","number","name","workflowName","workflow_name","currentAttempt","current_attempt","triggerProvider","trigger_provider","triggerSource","trigger_source","triggerEvent","trigger_event","triggerDisplayLabel","triggerLabel","triggerPayload","trigger_payload","triggerReference","trigger_reference","inputs","sourceSnapshot","source_snapshot","content","format","createdAt","created_at","updatedAt","updated_at","isTemporary","startsWith","toWorkflowRunAttempt","workflowRunId","workflow_run_id","attempt","status","startedAt","started_at","finishedAt","finished_at","rerunMode","rerun_mode","toWorkflowRunRecord","latestAttempt","latest_attempt","runAttempt","toWorkflowRunListItem","hasDisplayStatusCounts","job_display_status_counts","undefined","statusCounts","job_status_counts","map","count","jobs","preview","job","key","mode","listenerStatus","listener_status","executionStatus","execution_status","legacyExecutionStatus","position","total","reduce","sum","entry","toWorkflowRunListPage","runs","nextCursor","next_cursor","filteredTotalCount","filtered_total_count","toWorkflowRunDetail","run_attempt","toJob","runAttemptId","run_attempt_id","statusReason","status_reason","carriedOver","carried_over","outputs","success","runner","evaluationTrace","toEvaluationTrace","evaluation_trace","listening","toJobListening","resolutionReason","resolution_reason","dependencies","jobExecutions","job_executions","toJobExecution","jobId","job_id","sequence","statusReasonMessage","status_reason_message","triggerEvents","trigger_events","toWorkflowExecutionEvent","queuedAt","queued_at","timedOutAt","timed_out_at","steps","toStep","jobExecutionId","job_execution_id","sourceLocation","source_location","startLine","start_line","endLine","end_line","type","config","agentConfig","toAgentStepConfig","error","message","exitCode","exit_code","signal","reason","agentConfigIssue","agent_config_issue","category","attempts","toStepAttempt","stepId","step_id","executionOrder","execution_order","output","response","gateResult","toStepGateResult","gate_result","restartFeedback","restart_feedback","toStepAttemptDetail","authoredConfig","authored_config","on","until","timeoutMs","timeout_ms","maxExecutions","max_executions","batch","debounceMs","debounce_ms","maxSize","max_size","maxWaitMs","max_wait_ms","onResolve","on_resolve","executionTimeoutMs","execution_timeout_ms","source","event","deliveryId","delivery_id","receivedAt","received_at","project","repository","ref","commit","data","kind","trace","expression","roots","fillTarget","fill_target","evaluatedAt","evaluated_at","field","value","truncated","expr_truncated","exprTruncated","reference","degraded","env_key","envKey","provider","stringConfigValue","model","thinking","trim"],"mappings":"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"}