@bastani/atomic 0.9.11-alpha.6 → 0.9.11-alpha.7

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 (140) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/package.json +1 -1
  5. package/dist/builtin/web-access/package.json +1 -1
  6. package/dist/builtin/workflows/package.json +1 -1
  7. package/dist/builtin/workflows/skills/impeccable/SKILL.md +33 -129
  8. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_asset_producer.toml +11 -3
  9. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_documenter.toml +26 -0
  10. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_finish_reviewer.toml +35 -0
  11. package/dist/builtin/workflows/skills/impeccable/reference/android.md +1 -1
  12. package/dist/builtin/workflows/skills/impeccable/reference/animate.md +72 -189
  13. package/dist/builtin/workflows/skills/impeccable/reference/audit.md +10 -9
  14. package/dist/builtin/workflows/skills/impeccable/reference/audit.native.md +2 -2
  15. package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +19 -108
  16. package/dist/builtin/workflows/skills/impeccable/reference/clarify.md +59 -253
  17. package/dist/builtin/workflows/skills/impeccable/reference/colorize.md +51 -222
  18. package/dist/builtin/workflows/skills/impeccable/reference/craft-floor.md +45 -0
  19. package/dist/builtin/workflows/skills/impeccable/reference/craft.md +3 -121
  20. package/dist/builtin/workflows/skills/impeccable/reference/critique.md +28 -20
  21. package/dist/builtin/workflows/skills/impeccable/reference/degraded/asset-producer.md +97 -0
  22. package/dist/builtin/workflows/skills/impeccable/reference/degraded/documenter.md +23 -0
  23. package/dist/builtin/workflows/skills/impeccable/reference/degraded/finish-reviewer.md +32 -0
  24. package/dist/builtin/workflows/skills/impeccable/reference/degraded/manual-edit-applier.md +92 -0
  25. package/dist/builtin/workflows/skills/impeccable/reference/delight.md +47 -279
  26. package/dist/builtin/workflows/skills/impeccable/reference/distill.md +2 -2
  27. package/dist/builtin/workflows/skills/impeccable/reference/doctor.md +53 -0
  28. package/dist/builtin/workflows/skills/impeccable/reference/document.md +60 -73
  29. package/dist/builtin/workflows/skills/impeccable/reference/harden.md +1 -12
  30. package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +17 -4
  31. package/dist/builtin/workflows/skills/impeccable/reference/init.md +64 -163
  32. package/dist/builtin/workflows/skills/impeccable/reference/ios.md +1 -1
  33. package/dist/builtin/workflows/skills/impeccable/reference/layout.md +52 -153
  34. package/dist/builtin/workflows/skills/impeccable/reference/live.md +44 -32
  35. package/dist/builtin/workflows/skills/impeccable/reference/new-work.md +105 -0
  36. package/dist/builtin/workflows/skills/impeccable/reference/{product.md → operate.md} +6 -5
  37. package/dist/builtin/workflows/skills/impeccable/reference/optimize.md +4 -4
  38. package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +1 -4
  39. package/dist/builtin/workflows/skills/impeccable/reference/polish.md +68 -212
  40. package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +3 -3
  41. package/dist/builtin/workflows/skills/impeccable/reference/routing.md +18 -0
  42. package/dist/builtin/workflows/skills/impeccable/reference/shape.md +38 -144
  43. package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +48 -269
  44. package/dist/builtin/workflows/skills/impeccable/reference/visualize.md +38 -0
  45. package/dist/builtin/workflows/skills/impeccable/scripts/command-metadata.json +1 -1
  46. package/dist/builtin/workflows/skills/impeccable/scripts/concept-seed.mjs +584 -0
  47. package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +117 -9
  48. package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +486 -59
  49. package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +16 -45
  50. package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +96 -10
  51. package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +143 -26
  52. package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +181 -12
  53. package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +3187 -182
  54. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +102 -7
  55. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +282 -70
  56. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +183 -15
  57. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +22 -7
  58. package/dist/builtin/workflows/skills/impeccable/scripts/detector/findings.mjs +7 -1
  59. package/dist/builtin/workflows/skills/impeccable/scripts/detector/node/file-system.mjs +16 -2
  60. package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +155 -42
  61. package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +2988 -155
  62. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/constants.mjs +11 -0
  63. package/dist/builtin/workflows/skills/impeccable/scripts/doctor.mjs +336 -0
  64. package/dist/builtin/workflows/skills/impeccable/scripts/generate-image.mjs +232 -0
  65. package/dist/builtin/workflows/skills/impeccable/scripts/hook-admin.mjs +90 -10
  66. package/dist/builtin/workflows/skills/impeccable/scripts/hook-lib.mjs +410 -78
  67. package/dist/builtin/workflows/skills/impeccable/scripts/hook.mjs +25 -8
  68. package/dist/builtin/workflows/skills/impeccable/scripts/lib/artifact-schema.mjs +93 -0
  69. package/dist/builtin/workflows/skills/impeccable/scripts/lib/composition-catalog.mjs +165 -0
  70. package/dist/builtin/workflows/skills/impeccable/scripts/lib/concept-catalog.mjs +329 -0
  71. package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +20 -5
  72. package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-paths.mjs +16 -8
  73. package/dist/builtin/workflows/skills/impeccable/scripts/lib/provider.mjs +1 -0
  74. package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness-deep.mjs +455 -0
  75. package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness-notice.mjs +169 -0
  76. package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness.mjs +457 -0
  77. package/dist/builtin/workflows/skills/impeccable/scripts/lib/surface-briefs.mjs +151 -0
  78. package/dist/builtin/workflows/skills/impeccable/scripts/lib/target-slug.mjs +33 -0
  79. package/dist/builtin/workflows/skills/impeccable/scripts/lib/template-extensions.mjs +146 -0
  80. package/dist/builtin/workflows/skills/impeccable/scripts/live/completion.mjs +10 -1
  81. package/dist/builtin/workflows/skills/impeccable/scripts/live/event-validation.mjs +15 -0
  82. package/dist/builtin/workflows/skills/impeccable/scripts/live/generation-preflight.mjs +149 -0
  83. package/dist/builtin/workflows/skills/impeccable/scripts/live/poll-lanes.mjs +14 -0
  84. package/dist/builtin/workflows/skills/impeccable/scripts/live/session-store.mjs +109 -32
  85. package/dist/builtin/workflows/skills/impeccable/scripts/live/source-lock.mjs +105 -0
  86. package/dist/builtin/workflows/skills/impeccable/scripts/live/source-search.mjs +105 -0
  87. package/dist/builtin/workflows/skills/impeccable/scripts/live/sveltekit-adapter.mjs +8 -6
  88. package/dist/builtin/workflows/skills/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
  89. package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +208 -68
  90. package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +563 -112
  91. package/dist/builtin/workflows/skills/impeccable/scripts/live-commit-manual-edits.mjs +3 -0
  92. package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +198 -13
  93. package/dist/builtin/workflows/skills/impeccable/scripts/live-insert.mjs +24 -6
  94. package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edit-evidence.mjs +6 -1
  95. package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +44 -14
  96. package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +398 -33
  97. package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +9 -5
  98. package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +81 -67
  99. package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +7 -2
  100. package/dist/builtin/workflows/skills/impeccable/scripts/palette.mjs +76 -81
  101. package/dist/builtin/workflows/skills/impeccable/scripts/pin.mjs +2 -2
  102. package/dist/builtin/workflows/skills/impeccable/scripts/serve-question.mjs +890 -0
  103. package/dist/builtin/workflows/skills/impeccable/scripts/surface-brief.mjs +74 -0
  104. package/dist/builtin/workflows/src/extension/index.bundle.mjs +201 -22
  105. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +23 -9
  106. package/dist/builtin/workflows/src/runs/foreground/executor-stage-replay.ts +1 -0
  107. package/dist/builtin/workflows/src/runs/foreground/postmortem-stage-chat.ts +20 -5
  108. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +10 -0
  109. package/dist/builtin/workflows/src/runs/foreground/stage-delivery-activity.ts +86 -0
  110. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +6 -2
  111. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +19 -13
  112. package/dist/builtin/workflows/src/runs/foreground/stage-runner-send-user-message.ts +8 -0
  113. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +16 -0
  114. package/dist/builtin/workflows/src/tui/stage-chat-view-delivery-activity.ts +121 -0
  115. package/dist/builtin/workflows/src/tui/stage-chat-view-live-events.ts +42 -0
  116. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +16 -0
  117. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +4 -0
  118. package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
  119. package/dist/modes/interactive/components/chat-session-host-actions.js +2 -14
  120. package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
  121. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  122. package/dist/modes/interactive/components/chat-session-host-events.js +9 -0
  123. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  124. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts +25 -0
  125. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts.map +1 -1
  126. package/dist/modes/interactive/components/chat-session-host-runtime.js +53 -0
  127. package/dist/modes/interactive/components/chat-session-host-runtime.js.map +1 -1
  128. package/dist/modes/interactive/components/chat-session-host.d.ts +13 -0
  129. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/chat-session-host.js +22 -1
  131. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  132. package/dist/modes/interactive/interactive-agent-events.js +9 -3
  133. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  134. package/docs/tui.md +7 -2
  135. package/docs/workflows.md +1 -1
  136. package/npm-shrinkwrap.json +23 -23
  137. package/package.json +2 -2
  138. package/dist/builtin/workflows/skills/impeccable/reference/brand.md +0 -108
  139. package/dist/builtin/workflows/skills/impeccable/reference/codex.md +0 -105
  140. package/dist/builtin/workflows/skills/impeccable/reference/interaction-design.md +0 -189
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath, pathToFileURL } from 'node:url';
5
+ import { resolveProjectRoot } from './context.mjs';
6
+ import {
7
+ listSurfaceBriefs,
8
+ resolveSurfaceBrief,
9
+ surfaceBriefPathForTarget,
10
+ writeSurfaceBrief,
11
+ } from './lib/surface-briefs.mjs';
12
+
13
+ function summary(brief, projectRoot) {
14
+ return {
15
+ slug: brief.slug,
16
+ path: path.relative(projectRoot, brief.path).split(path.sep).join('/'),
17
+ primaryTarget: brief.primaryTarget,
18
+ relatedTargets: brief.relatedTargets,
19
+ };
20
+ }
21
+
22
+ function main(argv) {
23
+ const [command, target, bodyFile, ...relatedTargets] = argv;
24
+ const projectRoot = resolveProjectRoot(process.cwd(), target ? { targetPath: target } : {});
25
+ if (command === 'path') {
26
+ const filePath = surfaceBriefPathForTarget(target, { projectRoot });
27
+ if (!filePath) throw new Error('surface brief path requires a concrete target');
28
+ process.stdout.write(`${path.relative(process.cwd(), filePath) || filePath}\n`);
29
+ return;
30
+ }
31
+ if (command === 'list') {
32
+ process.stdout.write(`${JSON.stringify(listSurfaceBriefs(projectRoot).map((brief) => summary(brief, projectRoot)), null, 2)}\n`);
33
+ return;
34
+ }
35
+ if (command === 'read') {
36
+ const result = resolveSurfaceBrief(projectRoot, target || null);
37
+ if (result.brief) {
38
+ process.stdout.write(result.brief.text);
39
+ return;
40
+ }
41
+ if (result.candidates.length) process.stderr.write(`${JSON.stringify(result.candidates.map((brief) => summary(brief, projectRoot)), null, 2)}\n`);
42
+ process.exit(2);
43
+ }
44
+ if (command === 'write') {
45
+ if (!target || !bodyFile) throw new Error('usage: surface-brief.mjs write <primary-target> <body-file>');
46
+ const filePath = writeSurfaceBrief({
47
+ projectRoot,
48
+ primaryTarget: target,
49
+ relatedTargets,
50
+ body: fs.readFileSync(bodyFile, 'utf-8'),
51
+ });
52
+ process.stdout.write(`${path.relative(process.cwd(), filePath) || filePath}\n`);
53
+ return;
54
+ }
55
+ throw new Error('usage: surface-brief.mjs <path|list|read|write> [target] [body-file] [related-target ...]');
56
+ }
57
+
58
+ function isMainModule() {
59
+ if (!process.argv[1]) return false;
60
+ try {
61
+ return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(process.argv[1]);
62
+ } catch {
63
+ return import.meta.url === pathToFileURL(process.argv[1]).href;
64
+ }
65
+ }
66
+
67
+ if (isMainModule()) {
68
+ try {
69
+ main(process.argv.slice(2));
70
+ } catch (error) {
71
+ process.stderr.write(`${error?.message || error}\n`);
72
+ process.exit(1);
73
+ }
74
+ }
@@ -41452,16 +41452,95 @@ function isTerminalStageChatState(status) {
41452
41452
  return isTerminalOrNonStreamingStageChatStatus(status);
41453
41453
  }
41454
41454
 
41455
+ // dist/builtin/workflows/src/tui/stage-chat-view-delivery-activity.ts
41456
+ function subscribeStageChatDeliveryActivity(ctx) {
41457
+ const handle = ctx.handle;
41458
+ if (!handle?.subscribeDeliveryActivity)
41459
+ return null;
41460
+ return handle.subscribeDeliveryActivity((event) => {
41461
+ applyStageChatDeliveryActivityEvent(ctx, event);
41462
+ });
41463
+ }
41464
+ function applyStageChatDeliveryActivityEvent(ctx, event) {
41465
+ if (event.type === "delivery_start") {
41466
+ ctx.terminalLifecycleFenced = false;
41467
+ ctx.deliveryLifecycles.set(event.deliveryId, ctx.chatHost.beginExternalPromptLifecycle());
41468
+ return;
41469
+ }
41470
+ if (!ctx.deliveryLifecycles.has(event.deliveryId))
41471
+ return;
41472
+ const generation = ctx.deliveryLifecycles.get(event.deliveryId);
41473
+ ctx.deliveryLifecycles.delete(event.deliveryId);
41474
+ if (!ownsStageChatLifecycleGeneration(ctx, generation)) {
41475
+ ctx.chatHost.settleExternalPromptLifecycle(generation);
41476
+ }
41477
+ if (!hasActiveStageChatDelivery(ctx) && isStageChatContextTerminal(ctx)) {
41478
+ ctx.terminalLifecycleFenced = true;
41479
+ }
41480
+ }
41481
+ function ownsStageChatLifecycleGeneration(ctx, generation) {
41482
+ for (const active of ctx.deliveryLifecycles.values()) {
41483
+ if (active === generation)
41484
+ return true;
41485
+ }
41486
+ return false;
41487
+ }
41488
+ function hasActiveStageChatDelivery(ctx) {
41489
+ return ctx.deliveryLifecycles.size > 0;
41490
+ }
41491
+ function isStageChatContextTerminal(ctx) {
41492
+ return isTerminalStageChatState(ctx.lastObservedRunStatus) || isTerminalStageChatState(ctx.lastObservedStageStatus);
41493
+ }
41494
+ function reconcileStageChatDeliveryLifecycle(ctx) {
41495
+ if (!hasActiveStageChatDelivery(ctx))
41496
+ return;
41497
+ if (ctx.chatHost.isStreaming() && ctx.chatHost.hasAnimationTick())
41498
+ return;
41499
+ const generation = ctx.chatHost.reassertExternalPromptLifecycle();
41500
+ for (const deliveryId of [...ctx.deliveryLifecycles.keys()]) {
41501
+ ctx.deliveryLifecycles.set(deliveryId, generation);
41502
+ }
41503
+ }
41504
+ function invalidateStageChatDeliveryLifecycles(ctx) {
41505
+ ctx.deliveryLifecycles.clear();
41506
+ ctx.terminalLifecycleFenced = true;
41507
+ }
41508
+
41455
41509
  // dist/builtin/workflows/src/tui/stage-chat-view-live-events.ts
41456
41510
  function applyStageChatLiveHandleEvent(ctx, event) {
41511
+ const staleTerminalStart = isStaleTerminalLifecycleStart(ctx, event);
41457
41512
  ctx.chatHost.applyAgentEvent(event);
41513
+ if (staleTerminalStart) {
41514
+ retainTerminalCleanup(ctx);
41515
+ return;
41516
+ }
41517
+ if (isCompactionEndEvent(event))
41518
+ reconcileStageChatDeliveryLifecycle(ctx);
41458
41519
  if (!shouldCleanupAfterLiveEvent(ctx, event))
41459
41520
  return;
41521
+ retainTerminalCleanup(ctx);
41522
+ }
41523
+ function retainTerminalCleanup(ctx) {
41460
41524
  const hadAnimationTick = ctx.chatHost.hasAnimationTick();
41461
41525
  ctx.chatHost.clearBusyForTerminalWorkflowStage();
41462
41526
  if (hadAnimationTick !== ctx.chatHost.hasAnimationTick())
41463
41527
  ctx.requestRender?.();
41464
41528
  }
41529
+ function isStaleTerminalLifecycleStart(ctx, event) {
41530
+ if (!ctx.terminalLifecycleFenced)
41531
+ return false;
41532
+ const type = String(event.type ?? "");
41533
+ if (type !== "agent_start" && type !== "turn_start")
41534
+ return false;
41535
+ if (hasActiveStageChatDelivery(ctx))
41536
+ return false;
41537
+ if (ctx.chatHost.isStreaming())
41538
+ return false;
41539
+ return isCurrentRunOrStageTerminal(ctx);
41540
+ }
41541
+ function isCompactionEndEvent(event) {
41542
+ return String(event.type ?? "") === "compaction_end";
41543
+ }
41465
41544
  function shouldCleanupAfterLiveEvent(ctx, event) {
41466
41545
  if (!isToolExecutionLiveEvent(event))
41467
41546
  return false;
@@ -41550,8 +41629,11 @@ function initializeStageChatView(ctx, opts) {
41550
41629
  ctx.lastObservedStageStatus = undefined;
41551
41630
  ctx.lastObservedRunStatus = undefined;
41552
41631
  ctx.seenNoticeIds = new Set;
41632
+ ctx.deliveryLifecycles = new Map;
41633
+ ctx.terminalLifecycleFenced = false;
41553
41634
  ctx._unsubscribeStore = null;
41554
41635
  ctx._unsubscribeHandle = null;
41636
+ ctx._unsubscribeDeliveryActivity = null;
41555
41637
  ctx._unsubscribeFooterData = null;
41556
41638
  ctx._unregisterStageUiHost = null;
41557
41639
  installFocusHold(ctx);
@@ -41581,6 +41663,7 @@ function initializeStageChatView(ctx, opts) {
41581
41663
  ctx._unsubscribeStore = ctx.store.subscribe(() => handleStoreUpdate(ctx));
41582
41664
  ctx._unsubscribeFooterData = ctx.footerData?.onBranchChange(() => ctx.requestRender?.()) ?? null;
41583
41665
  if (ctx.handle) {
41666
+ ctx._unsubscribeDeliveryActivity = subscribeStageChatDeliveryActivity(ctx);
41584
41667
  ctx._unsubscribeHandle = ctx.handle.subscribe((event) => applyStageChatLiveHandleEvent(ctx, event));
41585
41668
  }
41586
41669
  ctx.chatHost.syncAnimationTick();
@@ -41693,6 +41776,7 @@ function handleStoreUpdate(ctx) {
41693
41776
  }
41694
41777
  if (isTerminalStageChatTransition(ctx.lastObservedStageStatus, currentStageStatus) || isTerminalStageChatTransition(ctx.lastObservedRunStatus, currentRunStatus)) {
41695
41778
  ctx.chatHost.clearBusyForTerminalWorkflowStage();
41779
+ invalidateStageChatDeliveryLifecycles(ctx);
41696
41780
  changed = true;
41697
41781
  }
41698
41782
  ctx.lastObservedRunStatus = currentRunStatus;
@@ -41918,6 +42002,9 @@ function disposeStageChatView(ctx) {
41918
42002
  ctx._unsubscribeStore = null;
41919
42003
  ctx._unsubscribeHandle?.();
41920
42004
  ctx._unsubscribeHandle = null;
42005
+ ctx._unsubscribeDeliveryActivity?.();
42006
+ ctx._unsubscribeDeliveryActivity = null;
42007
+ ctx.deliveryLifecycles.clear();
41921
42008
  ctx._unsubscribeFooterData?.();
41922
42009
  ctx._unsubscribeFooterData = null;
41923
42010
  releaseMountedCustomUi(ctx);
@@ -48600,7 +48687,7 @@ function coordinatedPromptOwnershipObserver(turn) {
48600
48687
  function unsupportedContentError() {
48601
48688
  return new Error("atomic-workflows: this stage session adapter does not support non-string sendUserMessage content; provide a runtime sendUserMessage implementation for text/image blocks.");
48602
48689
  }
48603
- async function sendStageUserMessage(activeSession, content, options, beforeDelivery, promptStarted, admission) {
48690
+ async function sendStageUserMessage(activeSession, content, options, beforeDelivery, promptStarted, admission, activity) {
48604
48691
  const streaming = activeSession.isStreaming || admission?.isOwned(activeSession) === true;
48605
48692
  const deliverAs = streaming ? options?.deliverAs ?? "followUp" : options?.deliverAs;
48606
48693
  if (activeSession.sendUserMessage !== undefined) {
@@ -48608,6 +48695,7 @@ async function sendStageUserMessage(activeSession, content, options, beforeDeliv
48608
48695
  let reportedAction;
48609
48696
  const ownership2 = streaming ? undefined : admission === undefined ? createLocalPromptOwnershipObserver(activeSession, promptStarted) : coordinatedPromptOwnershipObserver(admission.startTurn(activeSession, promptStarted ?? (() => {})));
48610
48697
  ownership2?.arm();
48698
+ const deliveryId2 = streaming ? undefined : activity?.start();
48611
48699
  try {
48612
48700
  const delivery = activeSession.sendUserMessage(content, {
48613
48701
  ...deliverAs === undefined ? {} : { deliverAs },
@@ -48628,6 +48716,7 @@ async function sendStageUserMessage(activeSession, content, options, beforeDeliv
48628
48716
  throw error;
48629
48717
  } finally {
48630
48718
  ownership2?.dispose();
48719
+ activity?.settle(deliveryId2);
48631
48720
  }
48632
48721
  }
48633
48722
  if (typeof content !== "string")
@@ -48642,6 +48731,7 @@ async function sendStageUserMessage(activeSession, content, options, beforeDeliv
48642
48731
  }
48643
48732
  const ownership = admission === undefined ? createLocalPromptOwnershipObserver(activeSession, promptStarted) : coordinatedPromptOwnershipObserver(admission.startTurn(activeSession, promptStarted ?? (() => {})));
48644
48733
  ownership.arm();
48734
+ const deliveryId = activity?.start();
48645
48735
  try {
48646
48736
  const turn = activeSession.prompt(content);
48647
48737
  ownership.observeStreaming();
@@ -48653,6 +48743,7 @@ async function sendStageUserMessage(activeSession, content, options, beforeDeliv
48653
48743
  throw error;
48654
48744
  } finally {
48655
48745
  ownership.dispose();
48746
+ activity?.settle(deliveryId);
48656
48747
  }
48657
48748
  }
48658
48749
 
@@ -48839,6 +48930,52 @@ class StageMessageAdmission {
48839
48930
  }
48840
48931
  }
48841
48932
 
48933
+ // dist/builtin/workflows/src/runs/foreground/stage-delivery-activity.ts
48934
+ class StageDeliveryActivity {
48935
+ listeners = new Set;
48936
+ active = new Set;
48937
+ nextDeliveryId = 0;
48938
+ subscribe(listener) {
48939
+ this.listeners.add(listener);
48940
+ for (const deliveryId of [...this.active]) {
48941
+ if (!this.listeners.has(listener))
48942
+ break;
48943
+ listener({ type: "delivery_start", deliveryId });
48944
+ }
48945
+ return () => {
48946
+ this.listeners.delete(listener);
48947
+ };
48948
+ }
48949
+ start() {
48950
+ const deliveryId = ++this.nextDeliveryId;
48951
+ this.active.add(deliveryId);
48952
+ this.emit({ type: "delivery_start", deliveryId });
48953
+ return deliveryId;
48954
+ }
48955
+ async runWithLease(operation) {
48956
+ const deliveryId = this.start();
48957
+ try {
48958
+ return await operation();
48959
+ } finally {
48960
+ this.settle(deliveryId);
48961
+ }
48962
+ }
48963
+ settle(deliveryId) {
48964
+ if (deliveryId === undefined || !this.active.delete(deliveryId))
48965
+ return;
48966
+ this.emit({ type: "delivery_settled", deliveryId });
48967
+ }
48968
+ dispose() {
48969
+ for (const deliveryId of [...this.active])
48970
+ this.settle(deliveryId);
48971
+ this.listeners.clear();
48972
+ }
48973
+ emit(event) {
48974
+ for (const listener of [...this.listeners])
48975
+ listener(event);
48976
+ }
48977
+ }
48978
+
48842
48979
  // dist/builtin/workflows/src/runs/foreground/stage-runner-unresolved-overflow.ts
48843
48980
  function unresolvedContextOverflowMessage(event) {
48844
48981
  if (event === null || typeof event !== "object")
@@ -49105,6 +49242,7 @@ class StageSessionController {
49105
49242
  sessionSettingsManager;
49106
49243
  replacement = new StageSessionReplacement;
49107
49244
  messageAdmission = new StageMessageAdmission;
49245
+ deliveryActivity = new StageDeliveryActivity;
49108
49246
  constructor(opts, meta, effectiveStageOptions, structuredOutputCapture) {
49109
49247
  this.opts = opts;
49110
49248
  this.meta = meta;
@@ -49168,16 +49306,24 @@ class StageSessionController {
49168
49306
  await session.closeWorkflowStageGeneration?.();
49169
49307
  return session;
49170
49308
  }
49171
- async sendUserMessage(content, options, beforeDelivery) {
49309
+ async sendUserMessage(content, options, beforeDelivery, preparation) {
49172
49310
  return this.messageAdmission.run(async (release) => {
49173
- const pausedDelivery = this.pauseControl.deferRunnerOwnedDelivery(() => this.sendUserMessage(content, options, beforeDelivery));
49311
+ const pausedDelivery = this.pauseControl.deferRunnerOwnedDelivery(() => this.sendUserMessage(content, options, beforeDelivery, preparation));
49174
49312
  if (pausedDelivery !== undefined) {
49175
49313
  release();
49176
49314
  return pausedDelivery;
49177
49315
  }
49178
- return sendStageUserMessage(await this.ensureSession("prompt"), content, options, beforeDelivery, release, this.messageAdmission);
49316
+ preparation?.beforePreparation?.();
49317
+ const sessionFile = preparation?.sessionFile;
49318
+ const deliver = async (activity) => sendStageUserMessage(sessionFile === undefined ? await this.ensureSession("prompt") : await this.ensureSessionFromFile(sessionFile, "prompt"), content, options, beforeDelivery, release, this.messageAdmission, activity);
49319
+ if (this.session === undefined || sessionFile !== undefined)
49320
+ return this.deliveryActivity.runWithLease(() => deliver());
49321
+ return deliver(this.deliveryActivity);
49179
49322
  });
49180
49323
  }
49324
+ subscribeDeliveryActivity(listener) {
49325
+ return this.deliveryActivity.subscribe(listener);
49326
+ }
49181
49327
  sealGeneration() {
49182
49328
  this.generationSealed = true;
49183
49329
  this.sharedOrchestrationContext?.messageAdmission?.boundary.seal();
@@ -49252,6 +49398,7 @@ class StageSessionController {
49252
49398
  this.unsubscribeTerminateWatcher = undefined;
49253
49399
  this.terminatingToolCallIds.clear();
49254
49400
  this.messageAdmission.dispose();
49401
+ this.deliveryActivity.dispose();
49255
49402
  await this.replacement.dispose();
49256
49403
  await disposeStageSession(this.session);
49257
49404
  }
@@ -49739,8 +49886,8 @@ function createStageContext(opts) {
49739
49886
  async sendUserMessage(text, options) {
49740
49887
  await controller.sendUserMessage(text, options);
49741
49888
  },
49742
- async __sendUserMessage(text, options, beforeDelivery) {
49743
- return controller.sendUserMessage(text, options, beforeDelivery);
49889
+ async __sendUserMessage(text, options, beforeDelivery, preparation) {
49890
+ return controller.sendUserMessage(text, options, beforeDelivery, preparation);
49744
49891
  },
49745
49892
  async steer(text) {
49746
49893
  await (await controller.ensureSession()).steer(text);
@@ -49751,6 +49898,9 @@ function createStageContext(opts) {
49751
49898
  subscribe(listener) {
49752
49899
  return controller.subscribe(listener);
49753
49900
  },
49901
+ __subscribeDeliveryActivity(listener) {
49902
+ return controller.subscribeDeliveryActivity(listener);
49903
+ },
49754
49904
  get sessionFile() {
49755
49905
  return controller.currentSession?.sessionFile;
49756
49906
  },
@@ -51274,6 +51424,7 @@ function createReplayStageContext(input) {
51274
51424
  steer: async () => rejectReplayMutation("steer"),
51275
51425
  followUp: async () => rejectReplayMutation("follow up"),
51276
51426
  subscribe: () => () => {},
51427
+ __subscribeDeliveryActivity: () => () => {},
51277
51428
  get sessionFile() {
51278
51429
  return replaySource.sessionFile;
51279
51430
  },
@@ -51371,18 +51522,28 @@ class StageToolExecutionBuffer {
51371
51522
 
51372
51523
  // dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts
51373
51524
  function createStageControlHandle(runtime) {
51374
- const ensureMessagingSession = async () => {
51525
+ const messagePreparation = () => {
51375
51526
  const meta = runtime.innerCtx.__sessionMeta();
51376
- if (meta.sessionId !== undefined || meta.sessionFile !== undefined)
51377
- return;
51527
+ if (meta.sessionId !== undefined || meta.sessionFile !== undefined) {
51528
+ return { beforePreparation: runtime.throwIfStageMutationBlocked };
51529
+ }
51378
51530
  if (runtime.stageSnapshot.sessionFile !== undefined) {
51379
- await runtime.innerCtx.__ensureSessionFromFile(runtime.stageSnapshot.sessionFile);
51380
- runtime.captureStageSessionMeta();
51381
- return;
51531
+ return {
51532
+ sessionFile: runtime.stageSnapshot.sessionFile,
51533
+ beforePreparation: runtime.throwIfStageMutationBlocked
51534
+ };
51382
51535
  }
51383
51536
  if (isTerminalStage(runtime.stageSnapshot)) {
51384
51537
  throw new Error(`atomic-workflows: cannot message stage "${runtime.name}" because no retained session metadata is available.`);
51385
51538
  }
51539
+ return { beforePreparation: runtime.throwIfStageMutationBlocked };
51540
+ };
51541
+ const ensureMessagingSession = async () => {
51542
+ const sessionFile = messagePreparation().sessionFile;
51543
+ if (sessionFile === undefined)
51544
+ return;
51545
+ await runtime.innerCtx.__ensureSessionFromFile(sessionFile);
51546
+ runtime.captureStageSessionMeta();
51386
51547
  };
51387
51548
  const toolExecutions = new StageToolExecutionBuffer;
51388
51549
  const unsubscribeToolExecutions = runtime.innerCtx.subscribe((event) => toolExecutions.record(event));
@@ -51423,14 +51584,13 @@ function createStageControlHandle(runtime) {
51423
51584
  },
51424
51585
  async sendUserMessage(text, options, beforeDelivery) {
51425
51586
  runtime.throwIfStageMutationBlocked();
51426
- await ensureMessagingSession();
51427
- runtime.throwIfStageMutationBlocked();
51587
+ const preparation = messagePreparation();
51428
51588
  const admitDelivery = () => {
51429
51589
  runtime.throwIfStageMutationBlocked();
51430
51590
  beforeDelivery?.();
51431
51591
  };
51432
51592
  try {
51433
- const action = await runtime.innerCtx.__sendUserMessage(text, options, admitDelivery);
51593
+ const action = await runtime.innerCtx.__sendUserMessage(text, options, admitDelivery, preparation);
51434
51594
  if (action === "steer" || action === "followUp") {
51435
51595
  runtime.state.resumeContinuationPending = "queued-user-message";
51436
51596
  }
@@ -51441,10 +51601,10 @@ function createStageControlHandle(runtime) {
51441
51601
  },
51442
51602
  async prompt(text) {
51443
51603
  runtime.throwIfStageMutationBlocked();
51444
- await ensureMessagingSession();
51604
+ const preparation = messagePreparation();
51445
51605
  let action;
51446
51606
  try {
51447
- action = await runtime.innerCtx.__sendUserMessage(text, undefined, runtime.throwIfStageMutationBlocked);
51607
+ action = await runtime.innerCtx.__sendUserMessage(text, undefined, runtime.throwIfStageMutationBlocked, preparation);
51448
51608
  } finally {
51449
51609
  runtime.captureStageSessionMeta();
51450
51610
  }
@@ -51540,6 +51700,9 @@ function createStageControlHandle(runtime) {
51540
51700
  subscribe(listener) {
51541
51701
  return runtime.innerCtx.subscribe(listener);
51542
51702
  },
51703
+ subscribeDeliveryActivity(listener) {
51704
+ return runtime.innerCtx.__subscribeDeliveryActivity(listener);
51705
+ },
51543
51706
  async dispose() {
51544
51707
  unsubscribeToolExecutions();
51545
51708
  toolExecutions.clear();
@@ -61765,11 +61928,19 @@ function createPostMortemStageHandle(runId, stage, sessionFile, adapters, cwd, d
61765
61928
  ...defaultSessionDir !== undefined ? { defaultSessionDir } : {}
61766
61929
  });
61767
61930
  let disposed = false;
61768
- const ensureAttached = async () => {
61931
+ const throwIfClosed = () => {
61769
61932
  if (disposed)
61770
61933
  throw new Error(`Post-mortem stage chat "${stage.name}" is closed.`);
61771
- if (context.__sessionMeta().sessionFile === undefined) {
61772
- await context.__ensureSessionFromFile(sessionFile);
61934
+ };
61935
+ const messagePreparation = () => ({
61936
+ ...context.__sessionMeta().sessionFile === undefined ? { sessionFile } : {},
61937
+ beforePreparation: throwIfClosed
61938
+ });
61939
+ const ensureAttached = async () => {
61940
+ throwIfClosed();
61941
+ const sessionFileToRestore = messagePreparation().sessionFile;
61942
+ if (sessionFileToRestore !== undefined) {
61943
+ await context.__ensureSessionFromFile(sessionFileToRestore);
61773
61944
  }
61774
61945
  };
61775
61946
  return {
@@ -61799,8 +61970,13 @@ function createPostMortemStageHandle(runId, stage, sessionFile, adapters, cwd, d
61799
61970
  await ensureAttached();
61800
61971
  },
61801
61972
  async sendUserMessage(text, options, beforeDelivery) {
61802
- await ensureAttached();
61803
- return context.__sendUserMessage(text, options, beforeDelivery);
61973
+ throwIfClosed();
61974
+ const preparation = messagePreparation();
61975
+ const admitDelivery = () => {
61976
+ throwIfClosed();
61977
+ beforeDelivery?.();
61978
+ };
61979
+ return context.__sendUserMessage(text, options, admitDelivery, preparation);
61804
61980
  },
61805
61981
  async prompt(text) {
61806
61982
  await ensureAttached();
@@ -61823,6 +61999,9 @@ function createPostMortemStageHandle(runId, stage, sessionFile, adapters, cwd, d
61823
61999
  subscribe(listener) {
61824
62000
  return context.subscribe(listener);
61825
62001
  },
62002
+ subscribeDeliveryActivity(listener) {
62003
+ return context.__subscribeDeliveryActivity(listener);
62004
+ },
61826
62005
  async dispose() {
61827
62006
  if (disposed)
61828
62007
  return;
@@ -1,21 +1,31 @@
1
1
  import type { StageControlHandle, AgentSessionEventListener } from "./stage-control-registry.js";
2
2
  import type { LiveStageRuntime } from "./executor-stage-types.js";
3
- import type { StageUserMessageDeliveryAction } from "./stage-runner-types.js";
3
+ import type { StageUserMessageDeliveryAction, StageUserMessagePreparation } from "./stage-runner-types.js";
4
4
  import { isTerminalStage } from "./executor-scheduler.js";
5
5
  import { StageToolExecutionBuffer } from "./stage-tool-execution-buffer.js";
6
6
 
7
7
  export function createStageControlHandle(runtime: LiveStageRuntime): StageControlHandle {
8
- const ensureMessagingSession = async (): Promise<void> => {
8
+ const messagePreparation = (): StageUserMessagePreparation => {
9
9
  const meta = runtime.innerCtx.__sessionMeta();
10
- if (meta.sessionId !== undefined || meta.sessionFile !== undefined) return;
10
+ if (meta.sessionId !== undefined || meta.sessionFile !== undefined) {
11
+ return { beforePreparation: runtime.throwIfStageMutationBlocked };
12
+ }
11
13
  if (runtime.stageSnapshot.sessionFile !== undefined) {
12
- await runtime.innerCtx.__ensureSessionFromFile(runtime.stageSnapshot.sessionFile);
13
- runtime.captureStageSessionMeta();
14
- return;
14
+ return {
15
+ sessionFile: runtime.stageSnapshot.sessionFile,
16
+ beforePreparation: runtime.throwIfStageMutationBlocked,
17
+ };
15
18
  }
16
19
  if (isTerminalStage(runtime.stageSnapshot)) {
17
20
  throw new Error(`atomic-workflows: cannot message stage "${runtime.name}" because no retained session metadata is available.`);
18
21
  }
22
+ return { beforePreparation: runtime.throwIfStageMutationBlocked };
23
+ };
24
+ const ensureMessagingSession = async (): Promise<void> => {
25
+ const sessionFile = messagePreparation().sessionFile;
26
+ if (sessionFile === undefined) return;
27
+ await runtime.innerCtx.__ensureSessionFromFile(sessionFile);
28
+ runtime.captureStageSessionMeta();
19
29
  };
20
30
  const toolExecutions = new StageToolExecutionBuffer();
21
31
  const unsubscribeToolExecutions = runtime.innerCtx.subscribe((event) => toolExecutions.record(event));
@@ -57,8 +67,7 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
57
67
  },
58
68
  async sendUserMessage(text, options, beforeDelivery) {
59
69
  runtime.throwIfStageMutationBlocked();
60
- await ensureMessagingSession();
61
- runtime.throwIfStageMutationBlocked();
70
+ const preparation = messagePreparation();
62
71
  const admitDelivery = (): void => {
63
72
  runtime.throwIfStageMutationBlocked();
64
73
  beforeDelivery?.();
@@ -68,6 +77,7 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
68
77
  text,
69
78
  options,
70
79
  admitDelivery,
80
+ preparation,
71
81
  );
72
82
  if (action === "steer" || action === "followUp") {
73
83
  runtime.state.resumeContinuationPending = "queued-user-message";
@@ -79,13 +89,14 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
79
89
  },
80
90
  async prompt(text: string) {
81
91
  runtime.throwIfStageMutationBlocked();
82
- await ensureMessagingSession();
92
+ const preparation = messagePreparation();
83
93
  let action: StageUserMessageDeliveryAction | undefined;
84
94
  try {
85
95
  action = await runtime.innerCtx.__sendUserMessage(
86
96
  text,
87
97
  undefined,
88
98
  runtime.throwIfStageMutationBlocked,
99
+ preparation,
89
100
  );
90
101
  } finally {
91
102
  runtime.captureStageSessionMeta();
@@ -197,6 +208,9 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
197
208
  subscribe(listener: AgentSessionEventListener) {
198
209
  return runtime.innerCtx.subscribe(listener);
199
210
  },
211
+ subscribeDeliveryActivity(listener) {
212
+ return runtime.innerCtx.__subscribeDeliveryActivity(listener);
213
+ },
200
214
  async dispose() {
201
215
  unsubscribeToolExecutions();
202
216
  toolExecutions.clear();
@@ -100,6 +100,7 @@ export function createReplayStageContext(input: {
100
100
  steer: async () => rejectReplayMutation("steer"),
101
101
  followUp: async () => rejectReplayMutation("follow up"),
102
102
  subscribe: () => () => {},
103
+ __subscribeDeliveryActivity: () => () => {},
103
104
  get sessionFile() { return replaySource.sessionFile; },
104
105
  get sessionId() { return replaySource.sessionId ?? ""; },
105
106
  setModel: async () => rejectReplayMutation("set model"),
@@ -34,6 +34,7 @@ import {
34
34
  type StageControlHandle,
35
35
  type StageControlRegistry,
36
36
  } from "./stage-control-registry.js";
37
+ import type { StageUserMessagePreparation } from "./stage-runner-types.js";
37
38
 
38
39
  /** Why a terminal stage could not be revived as an interactive post-mortem chat. */
39
40
  export type PostMortemUnavailableReason =
@@ -153,10 +154,18 @@ export function createPostMortemStageHandle(
153
154
  ...(defaultSessionDir !== undefined ? { defaultSessionDir } : {}),
154
155
  });
155
156
  let disposed = false;
156
- const ensureAttached = async (): Promise<void> => {
157
+ const throwIfClosed = (): void => {
157
158
  if (disposed) throw new Error(`Post-mortem stage chat "${stage.name}" is closed.`);
158
- if (context.__sessionMeta().sessionFile === undefined) {
159
- await context.__ensureSessionFromFile(sessionFile);
159
+ };
160
+ const messagePreparation = (): StageUserMessagePreparation => ({
161
+ ...(context.__sessionMeta().sessionFile === undefined ? { sessionFile } : {}),
162
+ beforePreparation: throwIfClosed,
163
+ });
164
+ const ensureAttached = async (): Promise<void> => {
165
+ throwIfClosed();
166
+ const sessionFileToRestore = messagePreparation().sessionFile;
167
+ if (sessionFileToRestore !== undefined) {
168
+ await context.__ensureSessionFromFile(sessionFileToRestore);
160
169
  }
161
170
  };
162
171
  return {
@@ -172,8 +181,13 @@ export function createPostMortemStageHandle(
172
181
  get agentSession() { return context.__agentSession(); },
173
182
  async ensureAttached() { await ensureAttached(); },
174
183
  async sendUserMessage(text, options, beforeDelivery) {
175
- await ensureAttached();
176
- return context.__sendUserMessage(text, options, beforeDelivery);
184
+ throwIfClosed();
185
+ const preparation = messagePreparation();
186
+ const admitDelivery = (): void => {
187
+ throwIfClosed();
188
+ beforeDelivery?.();
189
+ };
190
+ return context.__sendUserMessage(text, options, admitDelivery, preparation);
177
191
  },
178
192
  async prompt(text: string) {
179
193
  await ensureAttached();
@@ -194,6 +208,7 @@ export function createPostMortemStageHandle(
194
208
  throw new Error("Post-mortem stage chat cannot pause or resume workflow execution.");
195
209
  },
196
210
  subscribe(listener: AgentSessionEventListener) { return context.subscribe(listener); },
211
+ subscribeDeliveryActivity(listener) { return context.__subscribeDeliveryActivity(listener); },
197
212
  async dispose() {
198
213
  if (disposed) return;
199
214
  disposed = true;
@@ -26,6 +26,7 @@
26
26
  */
27
27
 
28
28
  import type { AgentSession, AgentSessionEvent } from "@bastani/atomic";
29
+ import type { StageDeliveryActivityEvent } from "./stage-delivery-activity.js";
29
30
  import type { StageUserMessageDeliveryAction } from "./stage-runner-types.js";
30
31
 
31
32
  export type StageControlStatus =
@@ -98,6 +99,15 @@ export interface StageControlHandle {
98
99
  * before the session exists are buffered and bound on first attach.
99
100
  */
100
101
  subscribe(listener: AgentSessionEventListener): () => void;
102
+ /**
103
+ * Subscribe to workflow-owned delivery lifecycle facts. Present only for
104
+ * handles backed by a live stage runner. An accepted idle delivery reports
105
+ * `delivery_start` before the public `agent_start` is published, letting an
106
+ * attached chat show Working for the whole turn.
107
+ */
108
+ subscribeDeliveryActivity?(
109
+ listener: (event: StageDeliveryActivityEvent) => void,
110
+ ): () => void;
101
111
  /** Release the underlying SDK session and unregister this direct chat handle. */
102
112
  dispose?(): void | Promise<void>;
103
113
  }