@bastani/atomic 0.9.9-alpha.2 → 0.9.9-alpha.4

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 (79) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/builtin/cursor/CHANGELOG.md +12 -0
  3. package/dist/builtin/cursor/package.json +2 -2
  4. package/dist/builtin/intercom/CHANGELOG.md +13 -0
  5. package/dist/builtin/intercom/README.md +10 -3
  6. package/dist/builtin/intercom/broker/client.ts +2 -0
  7. package/dist/builtin/intercom/broker/send-handler.ts +22 -20
  8. package/dist/builtin/intercom/foreground-detach-handoff.ts +3 -1
  9. package/dist/builtin/intercom/inbound-idle-queue.ts +82 -0
  10. package/dist/builtin/intercom/index-heavy.ts +47 -37
  11. package/dist/builtin/intercom/intercom-tool.ts +6 -4
  12. package/dist/builtin/intercom/intercom-utils.ts +30 -0
  13. package/dist/builtin/intercom/lifecycle.ts +8 -5
  14. package/dist/builtin/intercom/package.json +1 -1
  15. package/dist/builtin/intercom/reply-tracker.ts +19 -19
  16. package/dist/builtin/intercom/session-target.ts +68 -0
  17. package/dist/builtin/intercom/skills/intercom/SKILL.md +7 -4
  18. package/dist/builtin/intercom/source-ownership.ts +34 -0
  19. package/dist/builtin/intercom/subagent-relay.ts +45 -20
  20. package/dist/builtin/intercom/terminal-ordering-barrier.ts +111 -0
  21. package/dist/builtin/intercom/types.ts +5 -0
  22. package/dist/builtin/mcp/CHANGELOG.md +12 -0
  23. package/dist/builtin/mcp/package.json +1 -1
  24. package/dist/builtin/subagents/CHANGELOG.md +12 -0
  25. package/dist/builtin/subagents/package.json +1 -1
  26. package/dist/builtin/subagents/src/extension/startup-maintenance.ts +2 -1
  27. package/dist/builtin/subagents/src/runs/background/notify.ts +53 -9
  28. package/dist/builtin/subagents/src/shared/types-config.ts +1 -0
  29. package/dist/builtin/web-access/CHANGELOG.md +12 -0
  30. package/dist/builtin/web-access/package.json +1 -1
  31. package/dist/builtin/workflows/CHANGELOG.md +14 -0
  32. package/dist/builtin/workflows/README.md +2 -0
  33. package/dist/builtin/workflows/package.json +1 -1
  34. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +102 -48
  35. package/dist/builtin/workflows/src/extension/render-result.ts +11 -2
  36. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +11 -8
  37. package/dist/builtin/workflows/src/extension/workflow-command-surfaces.ts +23 -0
  38. package/dist/builtin/workflows/src/extension/workflow-reload-coordinator.ts +66 -0
  39. package/dist/builtin/workflows/src/extension/workflow-reload-report.ts +39 -0
  40. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +47 -25
  41. package/dist/builtin/workflows/src/extension/workflow-targets.ts +0 -10
  42. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +21 -17
  43. package/dist/builtin/workflows/src/extension/workflow-tool.ts +20 -3
  44. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  45. package/dist/core/agent-session-extension-bindings.js +9 -0
  46. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  47. package/dist/core/agent-session-message-queue.d.ts +4 -1
  48. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  49. package/dist/core/agent-session-message-queue.js +35 -0
  50. package/dist/core/agent-session-message-queue.js.map +1 -1
  51. package/dist/core/agent-session-methods.d.ts +2 -1
  52. package/dist/core/agent-session-methods.d.ts.map +1 -1
  53. package/dist/core/agent-session-methods.js.map +1 -1
  54. package/dist/core/extensions/api-types.d.ts +3 -1
  55. package/dist/core/extensions/api-types.d.ts.map +1 -1
  56. package/dist/core/extensions/api-types.js.map +1 -1
  57. package/dist/core/extensions/index.d.ts +1 -1
  58. package/dist/core/extensions/index.d.ts.map +1 -1
  59. package/dist/core/extensions/index.js.map +1 -1
  60. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  61. package/dist/core/extensions/loader-api.js +4 -0
  62. package/dist/core/extensions/loader-api.js.map +1 -1
  63. package/dist/core/extensions/loader-runtime.d.ts.map +1 -1
  64. package/dist/core/extensions/loader-runtime.js +1 -0
  65. package/dist/core/extensions/loader-runtime.js.map +1 -1
  66. package/dist/core/extensions/message-types.d.ts +3 -0
  67. package/dist/core/extensions/message-types.d.ts.map +1 -1
  68. package/dist/core/extensions/message-types.js.map +1 -1
  69. package/dist/core/extensions/runner.d.ts.map +1 -1
  70. package/dist/core/extensions/runner.js +1 -0
  71. package/dist/core/extensions/runner.js.map +1 -1
  72. package/dist/core/extensions/runtime-types.d.ts +3 -1
  73. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  74. package/dist/core/extensions/runtime-types.js.map +1 -1
  75. package/docs/extensions.md +13 -0
  76. package/docs/subagents.md +2 -0
  77. package/docs/workflows.md +11 -3
  78. package/npm-shrinkwrap.json +23 -23
  79. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-types.js","sourceRoot":"","sources":["../../../src/core/extensions/runtime-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, ImageContent, Model, TextContent } from \"@earendil-works/pi-ai/compat\";\nimport type { KeyId } from \"@earendil-works/pi-tui\";\nimport type { CustomMessage } from \"../messages.ts\";\nimport type { SessionManager } from \"../session-manager.ts\";\nimport type { SlashCommandInfo } from \"../slash-commands.ts\";\nimport type { SourceInfo } from \"../source-info.ts\";\nimport type { BuildSystemPromptOptions } from \"../system-prompt.ts\";\nimport type { RegisteredCommand } from \"./command-types.ts\";\nimport type {\n\tCompactOptions,\n\tContextUsage,\n\tExtensionContext,\n\tReplacedSessionContext,\n} from \"./context-types.ts\";\nimport type { MessageRenderer, SendMessageOptions } from \"./message-types.ts\";\nimport type { ProviderConfig } from \"./provider-types.ts\";\nimport type { ToolDefinition, ToolInfo } from \"./tool-types.ts\";\n\nexport interface RegisteredTool {\n\tdefinition: ToolDefinition;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface ExtensionFlag {\n\tname: string;\n\tdescription?: string;\n\ttype: \"boolean\" | \"string\";\n\tdefault?: boolean | string;\n\textensionPath: string;\n}\n\nexport interface ExtensionShortcut {\n\tshortcut: KeyId;\n\tdescription?: string;\n\thandler: (ctx: ExtensionContext) => Promise<void> | void;\n\textensionPath: string;\n}\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\nexport type SendMessageHandler = <T = unknown>(\n\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\toptions?: SendMessageOptions,\n) => void;\n\nexport type SendUserMessageHandler = (\n\tcontent: string | (TextContent | ImageContent)[],\n\toptions?: { deliverAs?: \"steer\" | \"followUp\" },\n) => void;\n\nexport type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;\n\nexport type SetSessionNameHandler = (name: string) => void;\n\nexport type GetSessionNameHandler = () => string | undefined;\n\nexport type GetActiveToolsHandler = () => string[];\n\nexport type GetAllToolsHandler = () => ToolInfo[];\n\nexport type GetCommandsHandler = () => SlashCommandInfo[];\n\nexport type SetActiveToolsHandler = (toolNames: string[]) => void;\n\nexport type RefreshToolsHandler = () => void;\n\nexport type SetModelHandler = (model: Model<Api>) => Promise<boolean>;\n\nexport type GetThinkingLevelHandler = () => ThinkingLevel;\n\nexport type SetThinkingLevelHandler = (level: ThinkingLevel) => void;\n\nexport type SetLabelHandler = (entryId: string, label: string | undefined) => void;\n\n/**\n * Shared state created by loader, used during registration and runtime.\n * Contains flag values (defaults set during registration, CLI values set after).\n */\nexport interface ExtensionRuntimeState {\n\tflagValues: Map<string, boolean | string>;\n\t/** Provider registrations queued during extension loading, processed when runner binds */\n\tpendingProviderRegistrations: Array<{ name: string; config: ProviderConfig; extensionPath: string }>;\n\t/** Throws when this extension instance is stale after runtime replacement. */\n\tassertActive: () => void;\n\t/** Marks this extension instance as stale after runtime replacement or reload. */\n\tinvalidate: (message?: string) => void;\n\t/**\n\t * Register or unregister a provider.\n\t *\n\t * Before bindCore(): queues registrations / removes from queue.\n\t * After bindCore(): calls ModelRegistry directly for immediate effect.\n\t */\n\tregisterProvider: (name: string, config: ProviderConfig, extensionPath?: string) => void;\n\tunregisterProvider: (name: string, extensionPath?: string) => void;\n}\n\n/**\n * Action implementations for pi.* API methods.\n * Provided to runner.initialize(), copied into the shared runtime.\n */\nexport interface ExtensionActions {\n\tsendMessage: SendMessageHandler;\n\tsendUserMessage: SendUserMessageHandler;\n\tappendEntry: AppendEntryHandler;\n\tsetSessionName: SetSessionNameHandler;\n\tgetSessionName: GetSessionNameHandler;\n\tsetLabel: SetLabelHandler;\n\tgetActiveTools: GetActiveToolsHandler;\n\tgetAllTools: GetAllToolsHandler;\n\tsetActiveTools: SetActiveToolsHandler;\n\trefreshTools: RefreshToolsHandler;\n\tgetCommands: GetCommandsHandler;\n\tsetModel: SetModelHandler;\n\tgetThinkingLevel: GetThinkingLevelHandler;\n\tsetThinkingLevel: SetThinkingLevelHandler;\n}\n\n/**\n * Actions for ExtensionContext (ctx.* in event handlers).\n * Required by all modes.\n */\nexport interface ExtensionContextActions {\n\tgetModel: () => Model<Api> | undefined;\n\tisIdle: () => boolean;\n\tisProjectTrusted: () => boolean;\n\tgetSignal: () => AbortSignal | undefined;\n\tabort: () => void;\n\thasPendingMessages: () => boolean;\n\tshutdown: () => void;\n\tgetContextUsage: () => ContextUsage | undefined;\n\tcompact: (options?: CompactOptions) => void;\n\tgetSystemPrompt: () => string;\n\tgetSystemPromptOptions?: () => BuildSystemPromptOptions;\n}\n\n/**\n * Actions for ExtensionCommandContext (ctx.* in command handlers).\n * Only needed for interactive mode where extension commands are invokable.\n */\nexport interface ExtensionCommandContextActions {\n\twaitForIdle: () => Promise<void>;\n\tnewSession: (options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}) => Promise<{ cancelled: boolean }>;\n\tfork: (\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t) => Promise<{ cancelled: boolean }>;\n\tnavigateTree: (\n\t\ttargetId: string,\n\t\toptions?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string },\n\t) => Promise<{ cancelled: boolean }>;\n\tswitchSession: (\n\t\tsessionPath: string,\n\t\toptions?: { withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t) => Promise<{ cancelled: boolean }>;\n\treload: () => Promise<void>;\n}\n\n/**\n * Full runtime = state + actions.\n * Created by loader with throwing action stubs, completed by runner.initialize().\n */\nexport interface ExtensionRuntime extends ExtensionRuntimeState, ExtensionActions {}\n\n/** Loaded extension with all registered items. */\nexport interface Extension {\n\tpath: string;\n\tresolvedPath: string;\n\tsourceInfo: SourceInfo;\n\thandlers: Map<string, HandlerFn[]>;\n\ttools: Map<string, RegisteredTool>;\n\tmessageRenderers: Map<string, MessageRenderer>;\n\tcommands: Map<string, RegisteredCommand>;\n\tflags: Map<string, ExtensionFlag>;\n\tshortcuts: Map<KeyId, ExtensionShortcut>;\n}\n\n/** Result of loading extensions. */\nexport interface LoadExtensionsResult {\n\textensions: Extension[];\n\terrors: Array<{ path: string; error: string }>;\n\t/** Shared runtime - actions are throwing stubs until runner.initialize() */\n\truntime: ExtensionRuntime;\n}\n\nexport interface ExtensionError {\n\textensionPath: string;\n\tevent: string;\n\terror: string;\n\tstack?: string;\n}\n"]}
1
+ {"version":3,"file":"runtime-types.js","sourceRoot":"","sources":["../../../src/core/extensions/runtime-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, ImageContent, Model, TextContent } from \"@earendil-works/pi-ai/compat\";\nimport type { KeyId } from \"@earendil-works/pi-tui\";\nimport type { CustomMessage } from \"../messages.ts\";\nimport type { SessionManager } from \"../session-manager.ts\";\nimport type { SlashCommandInfo } from \"../slash-commands.ts\";\nimport type { SourceInfo } from \"../source-info.ts\";\nimport type { BuildSystemPromptOptions } from \"../system-prompt.ts\";\nimport type { RegisteredCommand } from \"./command-types.ts\";\nimport type {\n\tCompactOptions,\n\tContextUsage,\n\tExtensionContext,\n\tReplacedSessionContext,\n} from \"./context-types.ts\";\nimport type { MessageRenderer, SendMessageOptions, SendMessagesOptions } from \"./message-types.ts\";\nimport type { ProviderConfig } from \"./provider-types.ts\";\nimport type { ToolDefinition, ToolInfo } from \"./tool-types.ts\";\n\nexport interface RegisteredTool {\n\tdefinition: ToolDefinition;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface ExtensionFlag {\n\tname: string;\n\tdescription?: string;\n\ttype: \"boolean\" | \"string\";\n\tdefault?: boolean | string;\n\textensionPath: string;\n}\n\nexport interface ExtensionShortcut {\n\tshortcut: KeyId;\n\tdescription?: string;\n\thandler: (ctx: ExtensionContext) => Promise<void> | void;\n\textensionPath: string;\n}\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\nexport type SendMessageHandler = <T = unknown>(\n\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\toptions?: SendMessageOptions,\n) => void;\n\nexport type SendMessagesHandler = <T = unknown>(\n\tmessages: Array<Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">>,\n\toptions?: SendMessagesOptions,\n) => void;\n\nexport type SendUserMessageHandler = (\n\tcontent: string | (TextContent | ImageContent)[],\n\toptions?: { deliverAs?: \"steer\" | \"followUp\" },\n) => void;\n\nexport type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;\n\nexport type SetSessionNameHandler = (name: string) => void;\n\nexport type GetSessionNameHandler = () => string | undefined;\n\nexport type GetActiveToolsHandler = () => string[];\n\nexport type GetAllToolsHandler = () => ToolInfo[];\n\nexport type GetCommandsHandler = () => SlashCommandInfo[];\n\nexport type SetActiveToolsHandler = (toolNames: string[]) => void;\n\nexport type RefreshToolsHandler = () => void;\n\nexport type SetModelHandler = (model: Model<Api>) => Promise<boolean>;\n\nexport type GetThinkingLevelHandler = () => ThinkingLevel;\n\nexport type SetThinkingLevelHandler = (level: ThinkingLevel) => void;\n\nexport type SetLabelHandler = (entryId: string, label: string | undefined) => void;\n\n/**\n * Shared state created by loader, used during registration and runtime.\n * Contains flag values (defaults set during registration, CLI values set after).\n */\nexport interface ExtensionRuntimeState {\n\tflagValues: Map<string, boolean | string>;\n\t/** Provider registrations queued during extension loading, processed when runner binds */\n\tpendingProviderRegistrations: Array<{ name: string; config: ProviderConfig; extensionPath: string }>;\n\t/** Throws when this extension instance is stale after runtime replacement. */\n\tassertActive: () => void;\n\t/** Marks this extension instance as stale after runtime replacement or reload. */\n\tinvalidate: (message?: string) => void;\n\t/**\n\t * Register or unregister a provider.\n\t *\n\t * Before bindCore(): queues registrations / removes from queue.\n\t * After bindCore(): calls ModelRegistry directly for immediate effect.\n\t */\n\tregisterProvider: (name: string, config: ProviderConfig, extensionPath?: string) => void;\n\tunregisterProvider: (name: string, extensionPath?: string) => void;\n}\n\n/**\n * Action implementations for pi.* API methods.\n * Provided to runner.initialize(), copied into the shared runtime.\n */\nexport interface ExtensionActions {\n\tsendMessage: SendMessageHandler;\n\tsendMessages: SendMessagesHandler;\n\tsendUserMessage: SendUserMessageHandler;\n\tappendEntry: AppendEntryHandler;\n\tsetSessionName: SetSessionNameHandler;\n\tgetSessionName: GetSessionNameHandler;\n\tsetLabel: SetLabelHandler;\n\tgetActiveTools: GetActiveToolsHandler;\n\tgetAllTools: GetAllToolsHandler;\n\tsetActiveTools: SetActiveToolsHandler;\n\trefreshTools: RefreshToolsHandler;\n\tgetCommands: GetCommandsHandler;\n\tsetModel: SetModelHandler;\n\tgetThinkingLevel: GetThinkingLevelHandler;\n\tsetThinkingLevel: SetThinkingLevelHandler;\n}\n\n/**\n * Actions for ExtensionContext (ctx.* in event handlers).\n * Required by all modes.\n */\nexport interface ExtensionContextActions {\n\tgetModel: () => Model<Api> | undefined;\n\tisIdle: () => boolean;\n\tisProjectTrusted: () => boolean;\n\tgetSignal: () => AbortSignal | undefined;\n\tabort: () => void;\n\thasPendingMessages: () => boolean;\n\tshutdown: () => void;\n\tgetContextUsage: () => ContextUsage | undefined;\n\tcompact: (options?: CompactOptions) => void;\n\tgetSystemPrompt: () => string;\n\tgetSystemPromptOptions?: () => BuildSystemPromptOptions;\n}\n\n/**\n * Actions for ExtensionCommandContext (ctx.* in command handlers).\n * Only needed for interactive mode where extension commands are invokable.\n */\nexport interface ExtensionCommandContextActions {\n\twaitForIdle: () => Promise<void>;\n\tnewSession: (options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}) => Promise<{ cancelled: boolean }>;\n\tfork: (\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t) => Promise<{ cancelled: boolean }>;\n\tnavigateTree: (\n\t\ttargetId: string,\n\t\toptions?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string },\n\t) => Promise<{ cancelled: boolean }>;\n\tswitchSession: (\n\t\tsessionPath: string,\n\t\toptions?: { withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t) => Promise<{ cancelled: boolean }>;\n\treload: () => Promise<void>;\n}\n\n/**\n * Full runtime = state + actions.\n * Created by loader with throwing action stubs, completed by runner.initialize().\n */\nexport interface ExtensionRuntime extends ExtensionRuntimeState, ExtensionActions {}\n\n/** Loaded extension with all registered items. */\nexport interface Extension {\n\tpath: string;\n\tresolvedPath: string;\n\tsourceInfo: SourceInfo;\n\thandlers: Map<string, HandlerFn[]>;\n\ttools: Map<string, RegisteredTool>;\n\tmessageRenderers: Map<string, MessageRenderer>;\n\tcommands: Map<string, RegisteredCommand>;\n\tflags: Map<string, ExtensionFlag>;\n\tshortcuts: Map<KeyId, ExtensionShortcut>;\n}\n\n/** Result of loading extensions. */\nexport interface LoadExtensionsResult {\n\textensions: Extension[];\n\terrors: Array<{ path: string; error: string }>;\n\t/** Shared runtime - actions are throwing stubs until runner.initialize() */\n\truntime: ExtensionRuntime;\n}\n\nexport interface ExtensionError {\n\textensionPath: string;\n\tevent: string;\n\terror: string;\n\tstack?: string;\n}\n"]}
@@ -1401,6 +1401,19 @@ pi.sendMessage({
1401
1401
  - `excludeFromContext: true` - Render and persist the custom message without adding it to LLM context. With no `deliverAs`, this remains display-only even while the agent is streaming.
1402
1402
  - `interruptAbortMessage` - Optional text used to replace generic abort results (for example `Operation aborted`) when `deliverAs: "interrupt"` aborts an active turn.
1403
1403
 
1404
+ ### pi.sendMessages(messages, options?)
1405
+
1406
+ Atomically admit a batch of custom messages in array order. Admission is indivisible, but the resulting model turn remains asynchronous; use this when a prelude and terminal notice must stay contiguous without globally serializing other extension work.
1407
+
1408
+ ```typescript
1409
+ pi.sendMessages([
1410
+ { customType: "worker-update", content: "Ready", display: true },
1411
+ { customType: "worker-terminal", content: "Completed", display: true },
1412
+ ], { triggerTurn: true });
1413
+ ```
1414
+
1415
+ The batch supports `triggerTurn`, `excludeFromContext`, and `deliverAs: "steer" | "followUp" | "nextTurn"`. Interrupt delivery remains a single-message operation.
1416
+
1404
1417
  ### pi.sendUserMessage(content, options?)
1405
1418
 
1406
1419
  Send a user message to the agent. Unlike `sendMessage()` which sends custom messages, this sends an actual user message that appears as if typed by the user. Always triggers a turn.
package/docs/subagents.md CHANGED
@@ -127,6 +127,8 @@ Background runs are detached. Their acknowledgement explicitly says the run was
127
127
 
128
128
  Completion delivery distinguishes two compatibility surfaces. Intercom delivery is confirmation-based and preserves a successful phase across watcher replacement, so another phase can retry without replaying the parent message. The in-process `subagent:async-complete` event remains a synchronous compatibility emission: returning without an explicit synchronous rejection counts as local acceptance even when no listener is installed. Equivalent result-file aliases coalesce by canonical run identity, while aliases that reuse that identity with different user-visible output or parent targets are retained under collision-resistant names in the non-scanned `.undelivered` directory instead of being delivered or deleted as duplicates. Modern results whose status is not terminal are rechecked with capped exponential delays and still recover if terminal status appears later. Delivery failures also back off; after a finite sequence of attempts with no phase progress, Atomic retains the still-owned result in `.undelivered` and logs its path rather than retrying forever or deleting the payload.
129
129
 
130
+ Terminal background notifications preserve each child’s accepted Intercom order. Every broker message retains its sender timestamp and source session ID/name; bridged-child messages additionally carry their source run ID, agent, and child index. The deterministic child Intercom target and result-relay child mapping use the same run/agent/index identity, so duplicate display aliases remain isolated by run ownership. Before a paused, completed, or failed result is delivered, Intercom synchronously claims pre-terminal ordinary messages from those exact child targets and atomically admits the FIFO prelude plus terminal message as one ordered custom-message batch. A process-local bridge complements the extension event bus because lazily activated companion extensions may have distinct loader buses; duplicate bridge/event delivery is deduplicated by exact terminal identity even when the successful dispatch has no prelude. Failed dispatches remain retryable, and a resumed run’s later lifecycle terminal has a distinct identity. Terminal admission does not wait for a separate model turn, unrelated child entries remain independently queued, and exact threaded ask replies retain their correlation and timeout behavior.
131
+
130
132
  When a workflow graph overlay is open, Atomic also publishes the live async subagent summary into the shared status surface. The below-editor async widget remains available when the workflow overlay is hidden, and the overlay statusline keeps the run count/state visible while the graph fills the terminal.
131
133
 
132
134
  ## Context and execution modes
package/docs/workflows.md CHANGED
@@ -781,6 +781,14 @@ export const tableSelectorFactory: WorkflowCustomUiFactory<{ id: string; name: s
781
781
 
782
782
  Workflow files are loaded via [jiti](https://github.com/unjs/jiti), so TypeScript works without compilation.
783
783
 
784
+ ## Reloading workflow resources
785
+
786
+ Run `/workflow reload` after adding, editing, renaming, or deleting workflow modules or changing workflow config. Reload rescans project and user conventional directories, legacy `.pi` locations, configured file/directory paths, and package resources without restarting Atomic. The workflow tool's `reload` action uses the same in-process path.
787
+
788
+ Reload builds a complete replacement registry before publishing it. Concurrent requests are serialized and coalesced, stale discovery from an earlier session cannot overwrite newer state, and a fatal refresh failure retains the previous registry. Reload is safe while workflows are running: existing runs keep the definition and runtime snapshot they started with, while subsequent list/get/inputs/help/completion/invocation calls use the newly published registry.
789
+
790
+ A successful rescan may still contain per-resource diagnostics. Both reload surfaces now show `CONFIG_INVALID`, `IMPORT_FAILED`, `INVALID_DEFINITION`, `PATH_NOT_FOUND`, and duplicate-name diagnostics instead of reporting bare success while silently skipping a resource. Valid sibling workflows remain available. Fix the reported source/path and reload again; no process restart is required.
791
+
784
792
  ## Workflow Configuration
785
793
 
786
794
  Configured workflow paths live in workflow extension config. Project config paths are relative to the project root. Global config paths are relative to `~/.atomic/agent`.
@@ -1025,10 +1033,10 @@ workflow({ action: "reload", reason: "added team workflow" })
1025
1033
 
1026
1034
  Control behavior:
1027
1035
 
1028
- - `runId` accepts full run ids or unique prefixes for lifecycle and inspection actions. Status lists and run pickers show top-level user-launched workflows; nested child runs are implementation details of the expanded parent graph.
1036
+ - `runId` accepts full run ids or unique prefixes for every lifecycle and inspection action, including `status`. The abbreviated IDs printed by status surfaces are valid inputs. Exact IDs take precedence; a prefix shared by multiple runs returns an ambiguity diagnostic with longer matching prefixes instead of selecting the first run. Status lists and run pickers show top-level user-launched workflows; nested child runs are implementation details of the expanded parent graph.
1029
1037
  - `status` / `status <runId>` show terminal `ctx.exit(...)` statuses (`completed`, `skipped`, `cancelled`, or `blocked`) and the optional exit reason when one was supplied.
1030
1038
  - `stages` lists stage summaries, including flattened stages from nested `ctx.workflow(...)` imports and `sessionFile`/`transcriptPath` when a stage has a persisted session. Use `statusFilter: "all"` to include completed, failed, skipped, and pending stages.
1031
- - `stage` returns details for one stage by stage id, unique prefix, or stage name, including nested child stages shown in the expanded graph and the persisted `sessionFile` when available.
1039
+ - `stage` returns details for one stage by stage id, unique prefix, or stage name, including nested child stages shown in the expanded graph and the persisted `sessionFile` when available. Abbreviated stage IDs printed in graph/control messages use this same unique-prefix resolver; collisions return an ambiguity diagnostic rather than selecting a stage.
1032
1040
  - `transcript` is reference-first with a small preview by default: it returns metadata, transcript paths, and up to 5 recent entries. For targeted lookup, quote the exact `sessionFile`/`transcriptPath` value without changing platform separators (preserve Windows backslashes), search it with `rg` or `grep`, then read only small surrounding ranges. Text results include JSON-escaped `sessionFileJson`/`transcriptPathJson` lines for copy-safe path literals. Pass explicit `tail` or `limit` to override the 5-entry preview; `tail` overrides `limit`; `includeToolOutput` includes captured snapshot tool output in snapshot transcript results.
1033
1041
  - `send` delivery modes are `auto`, `answer`, `prompt`, `steer`, `followUp`, and `resume`. Prompt answers can include `promptId` and can carry answer content in `response`, `text`, or `message`; structured UI prompts usually prefer `response`. Follow-up messaging to completed or failed stages reuses the retained `sessionFile` when available so the conversation resumes from the archived stage transcript instead of starting empty; if no session metadata was retained, Atomic refuses the follow-up rather than silently resetting. Arbitrary `ctx.ui.custom<T>` widget prompts require the interactive workflow graph and return a clear unsupported message when targeted through `send`.
1034
1042
  - `delivery: "auto"` first answers a pending prompt, then resumes paused work, then steers a streaming stage, then queues a follow-up.
@@ -1107,7 +1115,7 @@ When Atomic starts with an existing session or resumes one, it shows an informat
1107
1115
  /workflow resume <workflow-id-or-prefix> # Resume unfinished work or open completed detail/chat
1108
1116
  ```
1109
1117
 
1110
- Explicit full IDs take precedence, while prefixes resolve across live, resumable durable, and completed targets as one namespace. Ambiguous prefixes use the existing-style ambiguity diagnostic. A completed backend row with no checkpoints or no usable retained stage conversation is hidden from the picker; an explicit target reports that it is stale or missing required durable checkpoint/session data. A completed run remains inspectable when at least one stage has a usable transcript; missing, empty, directory, context-empty, or partially malformed transcript paths are omitted from stage chat attachment. Validation uses the final retained transcript for a repeated stage replay key, so an obsolete superseded checkpoint path does not hide an otherwise valid completed run. Reopening inspection refreshes a changed authoritative retained-chat handle. Session-cache-only rows are likewise hidden because the backend is authoritative. Cancelled, killed, non-resumable failed, and other terminal non-success states are never added. Normal `/resume`, `atomic -r`, and `--continue` behavior for internal workflow stage sessions is unchanged.
1118
+ Explicit full IDs take precedence, while prefixes resolve across top-level live, resumable durable, and completed targets as one namespace. An exact loadable paused top-level live target resumes directly from in-session state without enumerating the durable completed-history catalog; this keeps explicit live resume responsive even when retained durable history is large and preserves live-over-durable precedence for duplicate IDs. Nested child runs remain excluded from this top-level target namespace even when addressed by an exact ID. Prefixes and other targets continue through the combined catalog so ambiguity and completed-inspection behavior remain unchanged. Ambiguous prefixes use the existing-style ambiguity diagnostic. A completed backend row with no checkpoints or no usable retained stage conversation is hidden from the picker; an explicit target reports that it is stale or missing required durable checkpoint/session data. A completed run remains inspectable when at least one stage has a usable transcript; missing, empty, directory, context-empty, or partially malformed transcript paths are omitted from stage chat attachment. Validation uses the final retained transcript for a repeated stage replay key, so an obsolete superseded checkpoint path does not hide an otherwise valid completed run. Reopening inspection refreshes a changed authoritative retained-chat handle. Session-cache-only rows are likewise hidden because the backend is authoritative. Cancelled, killed, non-resumable failed, and other terminal non-success states are never added. Normal `/resume`, `atomic -r`, and `--continue` behavior for internal workflow stage sessions is unchanged.
1111
1119
 
1112
1120
  ### Cancellation, failure, and retry semantics
1113
1121
 
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.9-alpha.2",
3
+ "version": "0.9.9-alpha.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bastani/atomic",
9
- "version": "0.9.9-alpha.2",
9
+ "version": "0.9.9-alpha.4",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@bastani/atomic-natives": "0.9.9-alpha.2",
12
+ "@bastani/atomic-natives": "0.9.9-alpha.4",
13
13
  "@bufbuild/protobuf": "^2.12.1",
14
14
  "@earendil-works/pi-agent-core": "^0.80.7",
15
15
  "@earendil-works/pi-ai": "^0.80.7",
@@ -515,16 +515,16 @@
515
515
  }
516
516
  },
517
517
  "node_modules/@bastani/atomic-natives": {
518
- "version": "0.9.9-alpha.2",
519
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.9-alpha.2.tgz",
518
+ "version": "0.9.9-alpha.4",
519
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.9-alpha.4.tgz",
520
520
  "license": "MIT",
521
521
  "optionalDependencies": {
522
- "@bastani/atomic-natives-darwin-arm64": "0.9.9-alpha.2",
523
- "@bastani/atomic-natives-darwin-x64": "0.9.9-alpha.2",
524
- "@bastani/atomic-natives-linux-arm64-gnu": "0.9.9-alpha.2",
525
- "@bastani/atomic-natives-linux-x64-gnu": "0.9.9-alpha.2",
526
- "@bastani/atomic-natives-win32-arm64-msvc": "0.9.9-alpha.2",
527
- "@bastani/atomic-natives-win32-x64-msvc": "0.9.9-alpha.2"
522
+ "@bastani/atomic-natives-darwin-arm64": "0.9.9-alpha.4",
523
+ "@bastani/atomic-natives-darwin-x64": "0.9.9-alpha.4",
524
+ "@bastani/atomic-natives-linux-arm64-gnu": "0.9.9-alpha.4",
525
+ "@bastani/atomic-natives-linux-x64-gnu": "0.9.9-alpha.4",
526
+ "@bastani/atomic-natives-win32-arm64-msvc": "0.9.9-alpha.4",
527
+ "@bastani/atomic-natives-win32-x64-msvc": "0.9.9-alpha.4"
528
528
  },
529
529
  "engines": {
530
530
  "bun": ">=1.3.14",
@@ -532,8 +532,8 @@
532
532
  }
533
533
  },
534
534
  "node_modules/@bastani/atomic-natives-darwin-arm64": {
535
- "version": "0.9.9-alpha.2",
536
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.9-alpha.2.tgz",
535
+ "version": "0.9.9-alpha.4",
536
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.9-alpha.4.tgz",
537
537
  "license": "MIT",
538
538
  "os": [
539
539
  "darwin"
@@ -544,8 +544,8 @@
544
544
  "optional": true
545
545
  },
546
546
  "node_modules/@bastani/atomic-natives-darwin-x64": {
547
- "version": "0.9.9-alpha.2",
548
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.9-alpha.2.tgz",
547
+ "version": "0.9.9-alpha.4",
548
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.9-alpha.4.tgz",
549
549
  "license": "MIT",
550
550
  "os": [
551
551
  "darwin"
@@ -556,8 +556,8 @@
556
556
  "optional": true
557
557
  },
558
558
  "node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
559
- "version": "0.9.9-alpha.2",
560
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.9-alpha.2.tgz",
559
+ "version": "0.9.9-alpha.4",
560
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.9-alpha.4.tgz",
561
561
  "license": "MIT",
562
562
  "os": [
563
563
  "linux"
@@ -571,8 +571,8 @@
571
571
  "optional": true
572
572
  },
573
573
  "node_modules/@bastani/atomic-natives-linux-x64-gnu": {
574
- "version": "0.9.9-alpha.2",
575
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.9-alpha.2.tgz",
574
+ "version": "0.9.9-alpha.4",
575
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.9-alpha.4.tgz",
576
576
  "license": "MIT",
577
577
  "os": [
578
578
  "linux"
@@ -586,8 +586,8 @@
586
586
  "optional": true
587
587
  },
588
588
  "node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
589
- "version": "0.9.9-alpha.2",
590
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.9-alpha.2.tgz",
589
+ "version": "0.9.9-alpha.4",
590
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.9-alpha.4.tgz",
591
591
  "license": "MIT",
592
592
  "os": [
593
593
  "win32"
@@ -598,8 +598,8 @@
598
598
  "optional": true
599
599
  },
600
600
  "node_modules/@bastani/atomic-natives-win32-x64-msvc": {
601
- "version": "0.9.9-alpha.2",
602
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.9-alpha.2.tgz",
601
+ "version": "0.9.9-alpha.4",
602
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.9-alpha.4.tgz",
603
603
  "license": "MIT",
604
604
  "os": [
605
605
  "win32"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.9-alpha.2",
3
+ "version": "0.9.9-alpha.4",
4
4
  "description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "atomicConfig": {
@@ -77,7 +77,7 @@
77
77
  "prepublishOnly": "bun run clean && bun run build && bun run shrinkwrap"
78
78
  },
79
79
  "dependencies": {
80
- "@bastani/atomic-natives": "0.9.9-alpha.2",
80
+ "@bastani/atomic-natives": "0.9.9-alpha.4",
81
81
  "@bufbuild/protobuf": "^2.12.1",
82
82
  "@earendil-works/pi-agent-core": "^0.80.7",
83
83
  "@earendil-works/pi-ai": "^0.80.7",