@bastani/atomic 0.9.14-alpha.4 → 0.9.14-alpha.6

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 (141) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/subagents/src/extension/schemas.ts +5 -0
  7. package/dist/builtin/subagents/src/runs/shared/long-running-guard.ts +3 -1
  8. package/dist/builtin/subagents/src/runs/shared/progress-trend.ts +69 -0
  9. package/dist/builtin/subagents/src/runs/shared/subagent-control.ts +12 -1
  10. package/dist/builtin/subagents/src/shared/types-results.ts +2 -0
  11. package/dist/builtin/web-access/package.json +1 -1
  12. package/dist/builtin/workflows/CHANGELOG.md +47 -1
  13. package/dist/builtin/workflows/README.md +6 -5
  14. package/dist/builtin/workflows/builtin/adversarial-verification-prompts.ts +13 -5
  15. package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +376 -89
  16. package/dist/builtin/workflows/builtin/adversarial-verification.d.ts +30 -6
  17. package/dist/builtin/workflows/builtin/adversarial-verification.ts +14 -9
  18. package/dist/builtin/workflows/builtin/generate-and-filter-prompts.ts +26 -3
  19. package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +18 -14
  20. package/dist/builtin/workflows/builtin/goal-artifacts.ts +9 -8
  21. package/dist/builtin/workflows/builtin/goal-convergence.ts +87 -0
  22. package/dist/builtin/workflows/builtin/goal-ledger.ts +4 -0
  23. package/dist/builtin/workflows/builtin/goal-prompts.ts +2 -0
  24. package/dist/builtin/workflows/builtin/goal-reducer.ts +6 -1
  25. package/dist/builtin/workflows/builtin/goal-reverify.ts +305 -0
  26. package/dist/builtin/workflows/builtin/goal-runner.ts +75 -10
  27. package/dist/builtin/workflows/builtin/goal-schemas.ts +7 -0
  28. package/dist/builtin/workflows/builtin/goal-types.ts +6 -0
  29. package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +94 -6
  30. package/dist/builtin/workflows/builtin/loop-until-done.d.ts +8 -0
  31. package/dist/builtin/workflows/builtin/loop-until-done.ts +15 -0
  32. package/dist/builtin/workflows/builtin/progress-scoring.ts +230 -0
  33. package/dist/builtin/workflows/builtin/ralph-core.ts +11 -0
  34. package/dist/builtin/workflows/builtin/ralph-review-gate.ts +1 -0
  35. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +2 -0
  36. package/dist/builtin/workflows/builtin/ralph-runner.ts +60 -10
  37. package/dist/builtin/workflows/builtin/selection-math.ts +156 -0
  38. package/dist/builtin/workflows/builtin/shared-prompts.ts +5 -0
  39. package/dist/builtin/workflows/builtin/tournament-prompts.ts +57 -75
  40. package/dist/builtin/workflows/builtin/tournament-runner.ts +384 -178
  41. package/dist/builtin/workflows/builtin/tournament.d.ts +46 -17
  42. package/dist/builtin/workflows/builtin/tournament.ts +66 -32
  43. package/dist/builtin/workflows/builtin/verification-criteria.ts +330 -0
  44. package/dist/builtin/workflows/builtin/verification-prompts.ts +206 -0
  45. package/dist/builtin/workflows/builtin/verification-usage.ts +44 -0
  46. package/dist/builtin/workflows/package.json +1 -1
  47. package/dist/builtin/workflows/skills/create-spec/SKILL.md +90 -30
  48. package/dist/builtin/workflows/skills/show-me/LICENSE.txt +21 -0
  49. package/dist/builtin/workflows/skills/show-me/SKILL.md +143 -0
  50. package/dist/builtin/workflows/src/authoring/workflow.ts +8 -0
  51. package/dist/builtin/workflows/src/authoring.d.ts +1 -1
  52. package/dist/builtin/workflows/src/durable/completed-catalog.ts +5 -2
  53. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +1 -1
  54. package/dist/builtin/workflows/src/durable/resume-eligibility.ts +5 -3
  55. package/dist/builtin/workflows/src/durable/run-timing.ts +41 -10
  56. package/dist/builtin/workflows/src/durable/tool-primitive.ts +24 -2
  57. package/dist/builtin/workflows/src/engine/options.ts +1 -0
  58. package/dist/builtin/workflows/src/engine/primitives/workflow.ts +12 -3
  59. package/dist/builtin/workflows/src/engine/run-budget.ts +308 -0
  60. package/dist/builtin/workflows/src/engine/run-returned-status.ts +8 -0
  61. package/dist/builtin/workflows/src/engine/run-tool-node-lifecycle.ts +6 -0
  62. package/dist/builtin/workflows/src/engine/run.ts +124 -2
  63. package/dist/builtin/workflows/src/engine/runtime.ts +9 -0
  64. package/dist/builtin/workflows/src/extension/config-file-loader.ts +6 -0
  65. package/dist/builtin/workflows/src/extension/config-loader.ts +24 -1
  66. package/dist/builtin/workflows/src/extension/dispatcher.ts +6 -5
  67. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +2 -0
  68. package/dist/builtin/workflows/src/extension/index.bundle.mjs +2975 -843
  69. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +51 -4
  70. package/dist/builtin/workflows/src/extension/public-types.ts +3 -1
  71. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +7 -1
  72. package/dist/builtin/workflows/src/extension/runtime.ts +22 -10
  73. package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +5 -0
  74. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +1 -0
  75. package/dist/builtin/workflows/src/extension/workflow-schema.ts +16 -0
  76. package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +44 -1
  77. package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +10 -1
  78. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +21 -9
  79. package/dist/builtin/workflows/src/runs/foreground/executor-continuation.ts +14 -0
  80. package/dist/builtin/workflows/src/runs/foreground/executor-lifecycle.ts +15 -4
  81. package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +62 -5
  82. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +4 -0
  83. package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +2 -0
  84. package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +3 -1
  85. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +10 -1
  86. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +1 -0
  87. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +1 -0
  88. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +7 -0
  89. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +7 -0
  90. package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +1 -0
  91. package/dist/builtin/workflows/src/shared/budget-meter.ts +34 -0
  92. package/dist/builtin/workflows/src/shared/budget.d.ts +67 -0
  93. package/dist/builtin/workflows/src/shared/budget.ts +127 -0
  94. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +92 -8
  95. package/dist/builtin/workflows/src/shared/persistence-restore.ts +11 -1
  96. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +15 -3
  97. package/dist/builtin/workflows/src/shared/returned-run-status.ts +35 -2
  98. package/dist/builtin/workflows/src/shared/store-public-types.ts +4 -1
  99. package/dist/builtin/workflows/src/shared/store-run-methods.ts +8 -1
  100. package/dist/builtin/workflows/src/shared/store-stage-methods.ts +1 -0
  101. package/dist/builtin/workflows/src/shared/store-types.ts +24 -0
  102. package/dist/builtin/workflows/src/shared/types.ts +3 -0
  103. package/dist/builtin/workflows/src/shared/workflow-artifacts.ts +1 -0
  104. package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +3 -0
  105. package/dist/builtin/workflows/src/shared/workflow-authoring-types.ts +3 -0
  106. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  107. package/dist/core/atomic-guide-command.js +1 -0
  108. package/dist/core/atomic-guide-command.js.map +1 -1
  109. package/dist/core/extensions/ui-types.d.ts +13 -3
  110. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  111. package/dist/core/extensions/ui-types.js +15 -3
  112. package/dist/core/extensions/ui-types.js.map +1 -1
  113. package/dist/core/slash-commands.d.ts.map +1 -1
  114. package/dist/core/slash-commands.js +33 -3
  115. package/dist/core/slash-commands.js.map +1 -1
  116. package/dist/main-deferred-startup.d.ts.map +1 -1
  117. package/dist/main-deferred-startup.js +6 -2
  118. package/dist/main-deferred-startup.js.map +1 -1
  119. package/dist/modes/interactive/interactive-startup.js +4 -0
  120. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  121. package/dist/modes/interactive/interactive-tui.d.ts.map +1 -1
  122. package/dist/modes/interactive/interactive-tui.js +19 -1
  123. package/dist/modes/interactive/interactive-tui.js.map +1 -1
  124. package/dist/modes/interactive-engine/isolated-runtime.d.ts +7 -0
  125. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  126. package/dist/modes/interactive-engine/isolated-runtime.js +94 -37
  127. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  128. package/dist/modes/rpc/rpc-client.d.ts +1 -0
  129. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  130. package/dist/modes/rpc/rpc-client.js +15 -2
  131. package/dist/modes/rpc/rpc-client.js.map +1 -1
  132. package/dist/modes/rpc/rpc-input-scheduler.d.ts +3 -2
  133. package/dist/modes/rpc/rpc-input-scheduler.d.ts.map +1 -1
  134. package/dist/modes/rpc/rpc-input-scheduler.js +5 -2
  135. package/dist/modes/rpc/rpc-input-scheduler.js.map +1 -1
  136. package/docs/extensions.md +1 -1
  137. package/docs/quickstart.md +1 -0
  138. package/docs/skills.md +4 -0
  139. package/docs/workflows.md +74 -10
  140. package/npm-shrinkwrap.json +29 -29
  141. package/package.json +2 -2
@@ -1,8 +1,11 @@
1
1
  import { Value } from "typebox/value";
2
+ import { isModelAttempts } from "../durable/dbos-envelope.js";
2
3
  import type { NormalizedSessionEntry as SessionEntry } from "./persistence-restore.js";
3
4
  import { workflowSerializableObjectSchema } from "./serializable.js";
4
5
  import type { Store } from "./store.js";
5
6
  import type {
7
+ RunBudgetSnapshot,
8
+ RunBudgetState,
6
9
  RunStatus,
7
10
  StageSnapshot,
8
11
  StageStatus,
@@ -21,7 +24,7 @@ import {
21
24
  } from "./workflow-failures.js";
22
25
 
23
26
  interface RestoredRunBlockedMetadata {
24
- readonly failedStageId: string;
27
+ readonly failedStageId?: string;
25
28
  readonly error: string;
26
29
  readonly failureKind: WorkflowFailureKind;
27
30
  readonly failureCode?: WorkflowFailureCode;
@@ -30,6 +33,9 @@ interface RestoredRunBlockedMetadata {
30
33
  readonly failureMessage?: string;
31
34
  readonly retryAfterMs?: number;
32
35
  readonly resumable: true;
36
+ readonly endedAt?: number;
37
+ readonly result?: WorkflowOutputValues;
38
+ readonly budgetState?: RunBudgetState;
33
39
  readonly ts: number;
34
40
  }
35
41
 
@@ -78,6 +84,7 @@ export function _buildStageSnapshots(
78
84
  const skippedReason = entry.payload.skippedReason;
79
85
  const sessionId = entry.payload.sessionId;
80
86
  const sessionFile = entry.payload.sessionFile;
87
+ const modelAttempts = entry.payload.modelAttempts;
81
88
  if (typeof stageId !== "string") continue;
82
89
  endedStages.add(stageId);
83
90
  const snap = stageMap.get(stageId);
@@ -97,6 +104,7 @@ export function _buildStageSnapshots(
97
104
  if (typeof skippedReason === "string") snap.skippedReason = skippedReason;
98
105
  if (typeof sessionId === "string") snap.sessionId = sessionId;
99
106
  if (typeof sessionFile === "string") snap.sessionFile = sessionFile;
107
+ if (isModelAttempts(modelAttempts)) snap.modelAttempts = modelAttempts as StageSnapshot["modelAttempts"];
100
108
  Object.assign(snap, replayMetadata(entry.payload), workflowChildMetadata(entry.payload));
101
109
  }
102
110
  }
@@ -145,12 +153,12 @@ function markRestoredBlockedFailureStage(snap: StageSnapshot, blockedMeta: Resto
145
153
  snap.failureMessage = blockedMeta.failureMessage;
146
154
  snap.retryAfterMs = blockedMeta.retryAfterMs;
147
155
  }
148
-
149
156
  function restoreBlockedStageState(
150
157
  stageMap: Map<string, StageSnapshot>,
151
158
  endedStages: ReadonlySet<string>,
152
159
  blockedMeta: RestoredRunBlockedMetadata,
153
160
  ): void {
161
+ if (blockedMeta.failedStageId === undefined) return;
154
162
  for (const [stageId, snap] of stageMap) {
155
163
  if (endedStages.has(stageId)) continue;
156
164
  if (stageId === blockedMeta.failedStageId) {
@@ -189,6 +197,70 @@ export function serializableObjectOrEmpty(value: unknown): WorkflowOutputValues
189
197
  return serializableObject(value) ?? {};
190
198
  }
191
199
 
200
+ function restoreBudgetSnapshot(value: unknown): RunBudgetSnapshot | undefined {
201
+ if (!isRecord(value)) return undefined;
202
+ const maxDurationMs = numericDuration(value.maxDurationMs);
203
+ const maxTokens = numericDuration(value.maxTokens),
204
+ maxCost = numericDuration(value.maxCost);
205
+ const warnAtPercent = numericDuration(value.warnAtPercent);
206
+ if (maxDurationMs === undefined || warnAtPercent === undefined) return undefined;
207
+ return {
208
+ maxDurationMs,
209
+ ...(maxTokens !== undefined ? { maxTokens } : {}),
210
+ ...(maxCost !== undefined ? { maxCost } : {}),
211
+ warnAtPercent,
212
+ };
213
+ }
214
+ export function restoreBudgetState(value: unknown): RunBudgetState | undefined {
215
+ if (!isRecord(value)) return undefined;
216
+ const report = (candidate: unknown, dimension: "duration" | "tokens" | "cost") => {
217
+ if (!isRecord(candidate) || (dimension !== "duration" && dimension !== "tokens" && dimension !== "cost"))
218
+ return undefined;
219
+ const reading = numericDuration(candidate.reading);
220
+ const ceiling = numericDuration(candidate.ceiling);
221
+ const percent = numericDuration(candidate.percent);
222
+ return reading === undefined || ceiling === undefined || percent === undefined
223
+ ? undefined
224
+ : { dimension, reading, ceiling, percent };
225
+ };
226
+ const duration = report(value.duration, "duration") as RunBudgetState["duration"];
227
+ const tokens = report(value.tokens, "tokens") as RunBudgetState["tokens"];
228
+ const cost = report(value.cost, "cost") as RunBudgetState["cost"];
229
+ const warning = isRecord(value.warning)
230
+ ? report(value.warning, value.warning.dimension as "duration" | "tokens" | "cost")
231
+ : undefined;
232
+ const warnings: Partial<Record<"duration" | "tokens" | "cost", RunBudgetState["warning"]>> = {};
233
+ const warningValues = isRecord(value.warnings) ? value.warnings : undefined;
234
+ for (const dimension of ["duration", "tokens", "cost"] as const) {
235
+ const restored = report(warningValues?.[dimension], dimension);
236
+ if (restored !== undefined) warnings[dimension] = restored;
237
+ }
238
+ const requiredNumbers = (candidate: unknown, fields: readonly string[]): boolean =>
239
+ isRecord(candidate) && fields.every((field) => numericDuration(candidate[field]) !== undefined);
240
+ const accountingValue = value.accounting;
241
+ const accounting =
242
+ isRecord(accountingValue) &&
243
+ requiredNumbers(accountingValue, ["tokens", "cost"]) &&
244
+ requiredNumbers(accountingValue.baseline, ["input", "output", "cacheRead", "cacheWrite", "cost"]) &&
245
+ requiredNumbers(accountingValue.perCounter, ["input", "output", "cacheRead", "cacheWrite"])
246
+ ? (accountingValue as RunBudgetState["accounting"])
247
+ : undefined;
248
+ const state = {
249
+ ...(duration !== undefined ? { duration } : {}),
250
+ ...(tokens !== undefined ? { tokens } : {}),
251
+ ...(cost !== undefined ? { cost } : {}),
252
+ ...(warning !== undefined ? { warning } : {}),
253
+ ...(Object.keys(warnings).length > 0 ? { warnings } : {}),
254
+ ...(accounting !== undefined ? { accounting } : {}),
255
+ ...(value.warned === true ? { warned: true } : {}),
256
+ ...(value.wrapUpDelivered === true ? { wrapUpDelivered: true } : {}),
257
+ ...(value.wrapUpCompleted === true ? { wrapUpCompleted: true } : {}),
258
+ ...(value.systemOwnedStop === true ? { systemOwnedStop: true } : {}),
259
+ ...(typeof value.wrapUpSummary === "string" ? { wrapUpSummary: value.wrapUpSummary } : {}),
260
+ ...(isRecord(value.wrapUpUsage) ? { wrapUpUsage: value.wrapUpUsage as RunBudgetState["wrapUpUsage"] } : {}),
261
+ };
262
+ return Object.keys(state).length > 0 ? state : undefined;
263
+ }
192
264
  function isWorkflowChildReplayStatus(status: unknown): status is WorkflowExitStatus {
193
265
  return (
194
266
  status === "completed" ||
@@ -327,19 +399,21 @@ export function findRunBlockedMetadata(
327
399
  const retryAfterMs = numericRetryAfterMs(entry.payload.retryAfterMs);
328
400
  const resumable = entry.payload.resumable;
329
401
  const ts = entry.payload.ts;
402
+ const result = serializableObject(entry.payload.result);
403
+ const budgetState = restoreBudgetState(entry.payload.budgetState);
404
+ const isBudgetStop = budgetState?.systemOwnedStop === true && result?.status === "budget_exceeded";
330
405
  if (
331
- typeof failedStageId !== "string" ||
332
406
  typeof error !== "string" ||
333
407
  typeof failureKind !== "string" ||
334
408
  !isWorkflowFailureKind(failureKind) ||
335
409
  failureRecoverability !== "recoverable" ||
336
410
  resumable !== true ||
337
- typeof ts !== "number"
338
- ) {
411
+ typeof ts !== "number" ||
412
+ (!isBudgetStop && typeof failedStageId !== "string")
413
+ )
339
414
  continue;
340
- }
341
415
  latest = {
342
- failedStageId,
416
+ ...(typeof failedStageId === "string" ? { failedStageId } : {}),
343
417
  error,
344
418
  failureKind,
345
419
  ...(typeof failureCode === "string" && isWorkflowFailureCode(failureCode) ? { failureCode } : {}),
@@ -350,12 +424,14 @@ export function findRunBlockedMetadata(
350
424
  ...(typeof failureMessage === "string" ? { failureMessage } : {}),
351
425
  ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
352
426
  resumable: true,
427
+ ...(typeof entry.payload.endedAt === "number" ? { endedAt: entry.payload.endedAt } : {}),
428
+ ...(result !== undefined ? { result } : {}),
429
+ ...(budgetState !== undefined ? { budgetState } : {}),
353
430
  ts,
354
431
  };
355
432
  }
356
433
  return latest;
357
434
  }
358
-
359
435
  export function restoreTerminalRuns(entries: readonly SessionEntry[], store: Store): void {
360
436
  const started = new Map<
361
437
  string,
@@ -422,6 +498,8 @@ export function restoreTerminalRuns(entries: readonly SessionEntry[], store: Sto
422
498
  ...(runMeta.accumulatedDurationMs !== undefined
423
499
  ? { accumulatedDurationMs: runMeta.accumulatedDurationMs }
424
500
  : {}),
501
+ ...(runMeta.budget !== undefined ? { budget: runMeta.budget } : {}),
502
+ ...(runMeta.budgetState !== undefined ? { budgetState: runMeta.budgetState } : {}),
425
503
  });
426
504
 
427
505
  const error = end.error;
@@ -501,6 +579,8 @@ export function findRunStartMetadata(
501
579
  readonly resumeFromStageId?: string;
502
580
  readonly accumulatedDurationMs?: number;
503
581
  readonly origin?: WorkflowActor;
582
+ readonly budget?: RunBudgetSnapshot;
583
+ readonly budgetState?: RunBudgetState;
504
584
  } {
505
585
  for (const entry of entries) {
506
586
  if (entry.type !== "workflow.run.start" || entry.payload.runId !== runId) continue;
@@ -510,6 +590,8 @@ export function findRunStartMetadata(
510
590
  const resumedFromRunId = entry.payload.resumedFromRunId;
511
591
  const resumeFromStageId = entry.payload.resumeFromStageId;
512
592
  const accumulatedDurationMs = entry.payload.accumulatedDurationMs;
593
+ const budget = restoreBudgetSnapshot(entry.payload.budget);
594
+ const budgetState = restoreBudgetState(entry.payload.budgetState);
513
595
  const origin = entry.payload.origin;
514
596
  return {
515
597
  ...(typeof parentRunId === "string" ? { parentRunId } : {}),
@@ -523,6 +605,8 @@ export function findRunStartMetadata(
523
605
  ? { accumulatedDurationMs }
524
606
  : {}),
525
607
  ...(origin === "user" || origin === "agent" ? { origin } : {}),
608
+ ...(budget !== undefined ? { budget } : {}),
609
+ ...(budgetState !== undefined ? { budgetState } : {}),
526
610
  };
527
611
  }
528
612
  return {};
@@ -217,6 +217,7 @@ export function restoreOnSessionStart(
217
217
  status: "running",
218
218
  stages,
219
219
  startedAt: run.startTs,
220
+ ...(blockedMeta.endedAt !== undefined ? { endedAt: blockedMeta.endedAt } : {}),
220
221
  ...(runMeta.parentRunId !== undefined ? { parentRunId: runMeta.parentRunId } : {}),
221
222
  ...(runMeta.parentStageId !== undefined ? { parentStageId: runMeta.parentStageId } : {}),
222
223
  ...(runMeta.rootRunId !== undefined ? { rootRunId: runMeta.rootRunId } : {}),
@@ -226,6 +227,8 @@ export function restoreOnSessionStart(
226
227
  ...(runMeta.accumulatedDurationMs !== undefined
227
228
  ? { accumulatedDurationMs: runMeta.accumulatedDurationMs }
228
229
  : {}),
230
+ ...(runMeta.budget !== undefined ? { budget: runMeta.budget } : {}),
231
+ ...(blockedMeta.budgetState !== undefined ? { budgetState: blockedMeta.budgetState } : {}),
229
232
  };
230
233
  store.recordRunStart(runSnapshot);
231
234
  store.recordRunBlocked(run.runId, blockedMeta.error, {
@@ -236,9 +239,12 @@ export function restoreOnSessionStart(
236
239
  ? { failureDisposition: blockedMeta.failureDisposition }
237
240
  : {}),
238
241
  ...(blockedMeta.failureMessage !== undefined ? { failureMessage: blockedMeta.failureMessage } : {}),
239
- failedStageId: blockedMeta.failedStageId,
242
+ ...(blockedMeta.failedStageId !== undefined ? { failedStageId: blockedMeta.failedStageId } : {}),
240
243
  resumable: true,
241
244
  ...(blockedMeta.retryAfterMs !== undefined ? { retryAfterMs: blockedMeta.retryAfterMs } : {}),
245
+ ...(blockedMeta.endedAt !== undefined ? { endedAt: blockedMeta.endedAt } : {}),
246
+ ...(blockedMeta.result !== undefined ? { result: blockedMeta.result } : {}),
247
+ ...(blockedMeta.budgetState !== undefined ? { budgetState: blockedMeta.budgetState } : {}),
242
248
  blockedAt: blockedMeta.ts,
243
249
  });
244
250
  continue;
@@ -259,6 +265,8 @@ export function restoreOnSessionStart(
259
265
  ...(runMeta.resumedFromRunId !== undefined ? { resumedFromRunId: runMeta.resumedFromRunId } : {}),
260
266
  ...(runMeta.origin !== undefined ? { origin: runMeta.origin } : {}),
261
267
  ...(runMeta.resumeFromStageId !== undefined ? { resumeFromStageId: runMeta.resumeFromStageId } : {}),
268
+ ...(runMeta.budget !== undefined ? { budget: runMeta.budget } : {}),
269
+ ...(runMeta.budgetState !== undefined ? { budgetState: runMeta.budgetState } : {}),
262
270
  ...(runMeta.accumulatedDurationMs !== undefined
263
271
  ? { accumulatedDurationMs: runMeta.accumulatedDurationMs }
264
272
  : {}),
@@ -284,6 +292,8 @@ export function restoreOnSessionStart(
284
292
  ...(runMeta.resumedFromRunId !== undefined ? { resumedFromRunId: runMeta.resumedFromRunId } : {}),
285
293
  ...(runMeta.origin !== undefined ? { origin: runMeta.origin } : {}),
286
294
  ...(runMeta.resumeFromStageId !== undefined ? { resumeFromStageId: runMeta.resumeFromStageId } : {}),
295
+ ...(runMeta.budget !== undefined ? { budget: runMeta.budget } : {}),
296
+ ...(runMeta.budgetState !== undefined ? { budgetState: runMeta.budgetState } : {}),
287
297
  ...(runMeta.accumulatedDurationMs !== undefined
288
298
  ? { accumulatedDurationMs: runMeta.accumulatedDurationMs }
289
299
  : {}),
@@ -13,7 +13,7 @@ import type {
13
13
  WorkflowFailureDisposition,
14
14
  WorkflowFailureKind,
15
15
  } from "./store-types.js";
16
- import type { WorkflowExitStatus, WorkflowInputValues, WorkflowOutputValues } from "./types.js";
16
+ import type { WorkflowExitStatus, WorkflowInputValues, WorkflowModelAttempt, WorkflowOutputValues } from "./types.js";
17
17
 
18
18
  // ---------------------------------------------------------------------------
19
19
  // Structural API type (subset of ExtensionAPI needed here)
@@ -46,6 +46,8 @@ export interface RunStartPayload {
46
46
  readonly resumeFromStageId?: string;
47
47
  /** Elapsed ms inherited from prior sessions of a resumed run. */
48
48
  readonly accumulatedDurationMs?: number;
49
+ readonly budget?: import("./store-types.js").RunBudgetSnapshot;
50
+ readonly budgetState?: import("./store-types.js").RunBudgetState;
49
51
  readonly ts: number;
50
52
  }
51
53
 
@@ -94,6 +96,7 @@ export interface StageEndPayload {
94
96
  readonly skippedReason?: string;
95
97
  readonly sessionId?: string;
96
98
  readonly sessionFile?: string;
99
+ readonly modelAttempts?: readonly WorkflowModelAttempt[];
97
100
  readonly replayKey?: string;
98
101
  readonly replayedFromStageId?: string;
99
102
  readonly replayed?: boolean;
@@ -124,7 +127,7 @@ export interface RunEndPayload {
124
127
 
125
128
  export interface RunBlockedPayload {
126
129
  readonly runId: string;
127
- readonly failedStageId: string;
130
+ readonly failedStageId?: string;
128
131
  readonly error: string;
129
132
  readonly failureKind: WorkflowFailureKind;
130
133
  readonly failureCode?: WorkflowFailureCode;
@@ -133,6 +136,9 @@ export interface RunBlockedPayload {
133
136
  readonly failureDisposition?: WorkflowFailureDisposition;
134
137
  readonly retryAfterMs?: number;
135
138
  readonly resumable: true;
139
+ readonly endedAt?: number;
140
+ readonly result?: WorkflowOutputValues;
141
+ readonly budgetState?: import("./store-types.js").RunBudgetState;
136
142
  readonly ts: number;
137
143
  }
138
144
 
@@ -157,6 +163,8 @@ export function appendRunStart(api: PersistenceAPI, payload: RunStartPayload): v
157
163
  ...(payload.origin !== undefined ? { origin: payload.origin } : {}),
158
164
  ...(payload.resumeFromStageId !== undefined ? { resumeFromStageId: payload.resumeFromStageId } : {}),
159
165
  ...(payload.accumulatedDurationMs !== undefined ? { accumulatedDurationMs: payload.accumulatedDurationMs } : {}),
166
+ ...(payload.budget !== undefined ? { budget: payload.budget } : {}),
167
+ ...(payload.budgetState !== undefined ? { budgetState: payload.budgetState } : {}),
160
168
  ts: payload.ts,
161
169
  });
162
170
  if (entryId && typeof api.setLabel === "function") {
@@ -210,6 +218,7 @@ export function appendStageEnd(api: PersistenceAPI, payload: StageEndPayload, op
210
218
  ...(payload.skippedReason !== undefined ? { skippedReason: payload.skippedReason } : {}),
211
219
  ...(payload.sessionId !== undefined ? { sessionId: payload.sessionId } : {}),
212
220
  ...(payload.sessionFile !== undefined ? { sessionFile: payload.sessionFile } : {}),
221
+ ...(payload.modelAttempts !== undefined ? { modelAttempts: payload.modelAttempts } : {}),
213
222
  ...(payload.replayKey !== undefined ? { replayKey: payload.replayKey } : {}),
214
223
  ...(payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {}),
215
224
  ...(payload.replayed !== undefined ? { replayed: payload.replayed } : {}),
@@ -277,7 +286,7 @@ export function appendRunBlocked(api: PersistenceAPI, payload: RunBlockedPayload
277
286
  if (typeof api.appendEntry !== "function") return;
278
287
  api.appendEntry("workflow.run.blocked", {
279
288
  runId: payload.runId,
280
- failedStageId: payload.failedStageId,
289
+ ...(payload.failedStageId !== undefined ? { failedStageId: payload.failedStageId } : {}),
281
290
  error: payload.error,
282
291
  failureKind: payload.failureKind,
283
292
  ...(payload.failureCode !== undefined ? { failureCode: payload.failureCode } : {}),
@@ -286,6 +295,9 @@ export function appendRunBlocked(api: PersistenceAPI, payload: RunBlockedPayload
286
295
  ...(payload.failureDisposition !== undefined ? { failureDisposition: payload.failureDisposition } : {}),
287
296
  ...(payload.retryAfterMs !== undefined ? { retryAfterMs: payload.retryAfterMs } : {}),
288
297
  resumable: payload.resumable,
298
+ ...(payload.endedAt !== undefined ? { endedAt: payload.endedAt } : {}),
299
+ ...(payload.result !== undefined ? { result: payload.result } : {}),
300
+ ...(payload.budgetState !== undefined ? { budgetState: payload.budgetState } : {}),
289
301
  ts: payload.ts,
290
302
  });
291
303
  }
@@ -2,7 +2,14 @@ import type { RunEndMetadata } from "./store-public-types.js";
2
2
  import type { RunSnapshot, RunStatus, StageSnapshot, WorkflowFailureKind } from "./store-types.js";
3
3
  import type { WorkflowOutputValues } from "./types.js";
4
4
 
5
- const RETURNED_BLOCKED_STATUSES = new Set(["blocked", "needs_human", "incomplete", "auth_blocked", "active"]);
5
+ const RETURNED_BLOCKED_STATUSES = new Set([
6
+ "blocked",
7
+ "needs_human",
8
+ "incomplete",
9
+ "auth_blocked",
10
+ "budget_exceeded",
11
+ "active",
12
+ ]);
6
13
 
7
14
  export interface StructuredRecoverableWorkflowFailure {
8
15
  readonly error: string;
@@ -47,8 +54,31 @@ export function structuredRecoverableWorkflowFailure(
47
54
  | "failedStageId"
48
55
  | "retryAfterMs"
49
56
  | "stages"
57
+ | "result"
58
+ | "budgetState"
50
59
  >,
51
60
  ): StructuredRecoverableWorkflowFailure | undefined {
61
+ const returnedStatus = normalizeReturnedWorkflowStatus(run.result?.status);
62
+ if (
63
+ returnedStatus === "budget_exceeded" &&
64
+ run.budgetState?.systemOwnedStop === true &&
65
+ run.failureDisposition === "active_blocked" &&
66
+ run.failureRecoverability === "recoverable"
67
+ ) {
68
+ const error = run.error ?? run.failureMessage ?? "Workflow budget exceeded.";
69
+ return {
70
+ error,
71
+ metadata: {
72
+ ...(run.failureCode !== undefined ? { failureCode: run.failureCode } : {}),
73
+ failureRecoverability: "recoverable",
74
+ failureDisposition: "active_blocked",
75
+ failureMessage: run.failureMessage ?? error,
76
+ ...(run.failedStageId !== undefined ? { failedStageId: run.failedStageId } : {}),
77
+ resumable: true,
78
+ ...(run.retryAfterMs !== undefined ? { retryAfterMs: run.retryAfterMs } : {}),
79
+ },
80
+ };
81
+ }
52
82
  const runFailure = structuredRecoverableFailureFromSnapshot(run);
53
83
  if (runFailure !== undefined) return runFailure;
54
84
  if (run.failedStageId === undefined) return undefined;
@@ -69,19 +99,22 @@ export function structuredRecoverableWorkflowFailureText(
69
99
  | "failedStageId"
70
100
  | "retryAfterMs"
71
101
  | "stages"
102
+ | "result"
103
+ | "budgetState"
72
104
  >,
73
105
  ): string | undefined {
74
106
  return structuredRecoverableWorkflowFailure(run)?.error;
75
107
  }
76
108
 
77
109
  export function effectiveRunStatus(run: RunSnapshot): RunStatus {
110
+ const returnedStatus = normalizeReturnedWorkflowStatus(run.result?.status);
78
111
  if (
79
112
  (run.status === "running" || run.status === "completed") &&
80
113
  structuredRecoverableWorkflowFailure(run) !== undefined
81
114
  )
82
115
  return "blocked";
116
+ if (returnedStatus === "budget_exceeded") return run.status;
83
117
  if (run.status !== "completed") return run.status;
84
- const returnedStatus = normalizeReturnedWorkflowStatus(run.result?.status);
85
118
  if (returnedStatus === "failed") return "failed";
86
119
  if (returnedStatus !== undefined && isReturnedBlockedWorkflowStatus(returnedStatus)) return "blocked";
87
120
  return run.status;
@@ -61,9 +61,12 @@ export interface StageControlMetadata {
61
61
 
62
62
  export interface RunBlockedMetadata extends RunEndMetadata {
63
63
  readonly failureRecoverability: "recoverable";
64
- readonly failedStageId: string;
64
+ readonly failedStageId?: string;
65
65
  readonly resumable: true;
66
66
  readonly blockedAt?: number;
67
+ readonly endedAt?: number;
68
+ readonly result?: WorkflowOutputValues;
69
+ readonly budgetState?: import("./store-types.js").RunBudgetState;
67
70
  }
68
71
 
69
72
  export type StagePromptAnswerSource = "workflow_ui" | "workflow_tool";
@@ -141,10 +141,17 @@ export function createRunStoreMethods(context: StoreContext): RunStoreMethods {
141
141
  run.failureRecoverability = metadata.failureRecoverability;
142
142
  run.failureDisposition = metadata.failureDisposition;
143
143
  run.failureMessage = metadata.failureMessage;
144
- run.failedStageId = metadata.failedStageId;
144
+ if (metadata.failedStageId === undefined) delete run.failedStageId;
145
+ else run.failedStageId = metadata.failedStageId;
145
146
  run.resumable = metadata.resumable;
146
147
  run.blockedAt = metadata.blockedAt ?? Date.now();
148
+ if (metadata.endedAt !== undefined) {
149
+ run.endedAt = metadata.endedAt;
150
+ run.durationMs = elapsedRunMs(run, metadata.endedAt);
151
+ }
147
152
  if (metadata.retryAfterMs !== undefined) run.retryAfterMs = metadata.retryAfterMs;
153
+ if (metadata.result !== undefined) run.result = metadata.result;
154
+ if (metadata.budgetState !== undefined) run.budgetState = metadata.budgetState;
148
155
  context.bumpAndNotify();
149
156
  return true;
150
157
  },
@@ -104,6 +104,7 @@ export function createStageStoreMethods(context: StoreContext): StageStoreMethod
104
104
  existing.error = stage.error;
105
105
  if (stage.sessionId !== undefined) existing.sessionId = stage.sessionId;
106
106
  if (stage.sessionFile !== undefined) existing.sessionFile = stage.sessionFile;
107
+ if (stage.modelAttempts !== undefined) existing.modelAttempts = stage.modelAttempts;
107
108
  existing.failureKind = stage.failureKind;
108
109
  existing.failureCode = stage.failureCode;
109
110
  existing.failureRecoverability = stage.failureRecoverability;
@@ -3,6 +3,8 @@
3
3
  * cross-ref: spec §5.5
4
4
  */
5
5
 
6
+ import type { BudgetDimension, BudgetReport, DurationBudgetReport, UsageBudgetReport } from "./budget.js";
7
+ import type { RunMeterCounters } from "./budget-meter.js";
6
8
  import type {
7
9
  WorkflowExitStatus,
8
10
  WorkflowInputValues,
@@ -21,6 +23,25 @@ export type StageStatus =
21
23
  | "failed"
22
24
  | "skipped";
23
25
 
26
+ export type RunBudgetSnapshot = Readonly<Record<"maxDurationMs" | "warnAtPercent", number>> &
27
+ Readonly<Partial<Record<"maxTokens" | "maxCost", number>>>;
28
+ export type RunBudgetUsageBaseline = RunMeterCounters & { readonly cost: number };
29
+ export type RunBudgetAccountingState = Readonly<Record<"tokens" | "cost", number>> & {
30
+ readonly baseline: RunBudgetUsageBaseline;
31
+ readonly perCounter: RunMeterCounters;
32
+ };
33
+ export interface RunBudgetState
34
+ extends Partial<Record<"warned" | "wrapUpDelivered" | "wrapUpCompleted" | "systemOwnedStop", boolean>> {
35
+ readonly duration?: DurationBudgetReport;
36
+ readonly tokens?: UsageBudgetReport & { readonly dimension: "tokens" };
37
+ readonly cost?: UsageBudgetReport & { readonly dimension: "cost" };
38
+ /** Latest warning retained for legacy consumers; `warnings` keeps each dimension. */
39
+ readonly warning?: BudgetReport;
40
+ readonly warnings?: Partial<Record<BudgetDimension, BudgetReport>>;
41
+ readonly accounting?: RunBudgetAccountingState;
42
+ readonly wrapUpSummary?: string;
43
+ readonly wrapUpUsage?: import("./types.js").WorkflowModelUsage;
44
+ }
24
45
  export type ToolNodeStatus = "pending" | "running" | "completed" | "failed" | "cached" | "cancelled";
25
46
 
26
47
  /** First-class, durable graph node created for each ctx.tool invocation. */
@@ -307,6 +328,9 @@ export interface RunSnapshot {
307
328
  readonly stages: StageSnapshot[];
308
329
  /** Durable ctx.tool execution nodes. Optional only for legacy/restored snapshots. */
309
330
  readonly toolNodes?: ToolNodeSnapshot[];
331
+ /** Resolved duration budget and persisted wrap-up state; omitted when unbudgeted. */
332
+ budget?: RunBudgetSnapshot;
333
+ budgetState?: RunBudgetState;
310
334
  startedAt: number;
311
335
  endedAt?: number;
312
336
  durationMs?: number;
@@ -18,6 +18,7 @@ import type { TSchema } from "typebox";
18
18
  import type * as AuthoringContract from "./authoring-contract.js";
19
19
  import type { ToolNodeSnapshot } from "./store-types.js";
20
20
 
21
+ export type { EffectiveBudget, ResolveBudgetLayers, WorkflowBudget } from "./budget.js";
21
22
  export type { AgentSessionEvent, ModelCycleResult, PromptOptions, TSchema, VerbatimCompactionResult };
22
23
 
23
24
  export type StageUserMessageContent = Parameters<AgentSession["sendUserMessage"]>[0];
@@ -108,6 +109,8 @@ export interface WorkflowRunChildOptions<TInputs extends WorkflowInputValues = W
108
109
  readonly inputs?: TInputs;
109
110
  /** Parent boundary stage display name. Defaults to workflow:<workflow-name>. */
110
111
  readonly stageName?: string;
112
+ /** Additional subtree-scoped duration budget; parent run overrides do not flow here. */
113
+ readonly budget?: import("./budget.js").WorkflowBudget;
111
114
  }
112
115
 
113
116
  type WorkflowRequiredKeys<T extends object> = {
@@ -72,6 +72,7 @@ export function workflowRunResumeCandidate(run: RunSnapshot): WorkflowRunResumeC
72
72
  return {
73
73
  ...run,
74
74
  hasPausedState: workflowRunHasPausedState(run),
75
+ budgetSystemOwnedStop: run.budgetState?.systemOwnedStop === true,
75
76
  ...(hasDurableCheckpoint === undefined ? {} : { hasDurableCheckpoint }),
76
77
  ...(artifactsIntact === undefined ? {} : { artifactsIntact }),
77
78
  };
@@ -1,5 +1,6 @@
1
1
  import type { Static, TOptional, TSchema } from "typebox";
2
2
  import type { WorkflowInputSchemaMap, WorkflowInputValues, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowSerializableValue, WorkflowWorktreeInputBinding } from "./authoring-contract.js";
3
+ import type { WorkflowBudget } from "./budget.js";
3
4
  type SchemaKeys<TSchemas> = keyof TSchemas & string;
4
5
  type Simplify<T> = {
5
6
  [K in keyof T]: T[K];
@@ -48,6 +49,8 @@ export interface AuthoredWorkflowSpec<TInputs extends WorkflowInputSchemaMap = R
48
49
  readonly name?: string;
49
50
  readonly autoAttach?: boolean;
50
51
  readonly heartbeatIntervalMinutes?: number;
52
+ /** Optional run budget for this workflow definition. */
53
+ readonly budget?: WorkflowBudget;
51
54
  readonly description: string;
52
55
  readonly inputs?: TInputs;
53
56
  readonly outputs: TOutputs;
@@ -8,6 +8,7 @@ import type {
8
8
  WorkflowSerializableValue,
9
9
  WorkflowWorktreeInputBinding,
10
10
  } from "./authoring-contract.js";
11
+ import type { WorkflowBudget } from "./budget.js";
11
12
 
12
13
  type SchemaKeys<TSchemas> = keyof TSchemas & string;
13
14
  type Simplify<T> = { [K in keyof T]: T[K] } & {};
@@ -98,6 +99,8 @@ export interface AuthoredWorkflowSpec<
98
99
  readonly name?: string;
99
100
  readonly autoAttach?: boolean;
100
101
  readonly heartbeatIntervalMinutes?: number;
102
+ /** Optional run budget for this workflow definition. */
103
+ readonly budget?: WorkflowBudget;
101
104
  readonly description: string;
102
105
  readonly inputs?: TInputs;
103
106
  readonly outputs: TOutputs;
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-guide-command.d.ts","sourceRoot":"","sources":["../../src/core/atomic-guide-command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,gCAAgC,qCAAqC,CAAC;AA4NnF,QAAA,MAAM,cAAc;mBAEZ,UAAU;;oBAET,UAAU;0BACJ,oBAAoB;;;mBAI3B,WAAW;;oBAEV,WAAW;0BACL,iBAAiB;;;mBAIxB,SAAS;;oBAER,SAAS;0BACH,0BAA0B;;;mBAIjC,WAAW;;oBAEV,YAAY;0BACN,sBAAsB;;EASlC,CAAC;AAEJ,KAAK,kBAAkB,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1D,KAAK,sBAAsB,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,sBAAsB,CAAC;AAE9D,eAAO,MAAM,yBAAyB,EAAE,SAAS,qBAAqB,EAErE,CAAC;AAcF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,qBAAqB,CAEvF;AA6BD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAKtE;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAW3F;AAED,iBAAS,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CActD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CAEvF"}
1
+ {"version":3,"file":"atomic-guide-command.d.ts","sourceRoot":"","sources":["../../src/core/atomic-guide-command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,gCAAgC,qCAAqC,CAAC;AA6NnF,QAAA,MAAM,cAAc;mBAEZ,UAAU;;oBAET,UAAU;0BACJ,oBAAoB;;;mBAI3B,WAAW;;oBAEV,WAAW;0BACL,iBAAiB;;;mBAIxB,SAAS;;oBAER,SAAS;0BACH,0BAA0B;;;mBAIjC,WAAW;;oBAEV,YAAY;0BACN,sBAAsB;;EASlC,CAAC;AAEJ,KAAK,kBAAkB,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1D,KAAK,sBAAsB,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,sBAAsB,CAAC;AAE9D,eAAO,MAAM,yBAAyB,EAAE,SAAS,qBAAqB,EAErE,CAAC;AAcF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,qBAAqB,CAEvF;AA6BD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAKtE;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAW3F;AAED,iBAAS,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CActD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CAEvF"}
@@ -54,6 +54,7 @@ Use \`/workflow list\` to see what is available and \`/workflow inputs <name>\`
54
54
  | \`prompt-engineer\` | tighten a vague prompt before a long run | \`/skill:prompt-engineer Draft a sharper implementation prompt for ...\` |
55
55
  | \`subagent\` | learn delegation patterns and exact \`/run\` and \`/parallel\` usage | \`/skill:subagent\` |
56
56
  | \`impeccable\` | critique or refine frontend and product UI | \`/skill:impeccable\` |
57
+ | \`show-me\` | explain a topic visually with concise diagrams, code-shape sketches, or focused HTML artifacts (HumanLayer, MIT) | \`/skill:show-me\` |
57
58
 
58
59
  ## Subagents
59
60