@bastani/atomic 0.9.11-alpha.3 → 0.9.11-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 (74) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/builtin/cursor/package.json +2 -2
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/package.json +1 -1
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/web-access/package.json +1 -1
  7. package/dist/builtin/workflows/CHANGELOG.md +20 -0
  8. package/dist/builtin/workflows/builtin/goal-prompts.ts +8 -3
  9. package/dist/builtin/workflows/builtin/goal.ts +4 -4
  10. package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +1 -1
  11. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +3 -1
  12. package/dist/builtin/workflows/builtin/ralph-runner.ts +2 -0
  13. package/dist/builtin/workflows/builtin/ralph.ts +4 -4
  14. package/dist/builtin/workflows/builtin/shared-prompts.ts +16 -0
  15. package/dist/builtin/workflows/package.json +2 -2
  16. package/dist/builtin/workflows/src/authoring/workflow.ts +1 -0
  17. package/dist/builtin/workflows/src/durable/dbos-lifecycle.ts +27 -1
  18. package/dist/builtin/workflows/src/durable/factory.ts +29 -3
  19. package/dist/builtin/workflows/src/durable/index.ts +2 -0
  20. package/dist/builtin/workflows/src/engine/run-durable-admission.ts +50 -0
  21. package/dist/builtin/workflows/src/engine/run.ts +12 -17
  22. package/dist/builtin/workflows/src/extension/extension-factory.ts +16 -1
  23. package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +16 -2
  24. package/dist/builtin/workflows/src/extension/index.bundle.mjs +71724 -0
  25. package/dist/builtin/workflows/src/extension/runtime.ts +5 -3
  26. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +4 -1
  27. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +3 -1
  28. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +1 -0
  29. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +1 -0
  30. package/dist/builtin/workflows/src/shared/types.ts +7 -0
  31. package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +1 -0
  32. package/dist/builtin/workflows/src/shared/workflow-authoring-types.ts +1 -0
  33. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +6 -8
  34. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +2 -0
  35. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +4 -0
  36. package/dist/cli/args.d.ts +8 -0
  37. package/dist/cli/args.d.ts.map +1 -1
  38. package/dist/cli/args.js +16 -0
  39. package/dist/cli/args.js.map +1 -1
  40. package/dist/cli.js +2 -0
  41. package/dist/cli.js.map +1 -1
  42. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
  43. package/dist/modes/interactive/components/chat-session-host-rendering.js +5 -1
  44. package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
  45. package/dist/modes/interactive/components/footer.d.ts +7 -1
  46. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  47. package/dist/modes/interactive/components/footer.js +12 -6
  48. package/dist/modes/interactive/components/footer.js.map +1 -1
  49. package/dist/modes/interactive-engine/engine-monitor.d.ts +8 -1
  50. package/dist/modes/interactive-engine/engine-monitor.d.ts.map +1 -1
  51. package/dist/modes/interactive-engine/engine-monitor.js +13 -15
  52. package/dist/modes/interactive-engine/engine-monitor.js.map +1 -1
  53. package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -1
  54. package/dist/modes/rpc/rpc-client-process.js +3 -0
  55. package/dist/modes/rpc/rpc-client-process.js.map +1 -1
  56. package/dist/modes/rpc/rpc-extension-ui.d.ts +3 -1
  57. package/dist/modes/rpc/rpc-extension-ui.d.ts.map +1 -1
  58. package/dist/modes/rpc/rpc-extension-ui.js +7 -2
  59. package/dist/modes/rpc/rpc-extension-ui.js.map +1 -1
  60. package/dist/modes/rpc/rpc-session-binding.d.ts +1 -0
  61. package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
  62. package/dist/modes/rpc/rpc-session-binding.js +66 -43
  63. package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
  64. package/dist/rpc-entry.js +6 -2
  65. package/dist/rpc-entry.js.map +1 -1
  66. package/dist/utils/compile-cache.d.ts +8 -0
  67. package/dist/utils/compile-cache.d.ts.map +1 -0
  68. package/dist/utils/compile-cache.js +31 -0
  69. package/dist/utils/compile-cache.js.map +1 -0
  70. package/docs/tui.md +2 -0
  71. package/docs/usage.md +7 -0
  72. package/docs/workflows.md +34 -11
  73. package/npm-shrinkwrap.json +23 -23
  74. package/package.json +2 -2
@@ -1,3 +1,4 @@
1
+ import { FooterDataProvider } from "../../core/footer-data-provider.js";
1
2
  import { waitForRawStdoutBackpressure } from "../../core/output-guard.js";
2
3
  import { createRpcExtensionUIContext } from "./rpc-extension-ui.js";
3
4
  export class RpcSessionBinding {
@@ -18,53 +19,73 @@ export class RpcSessionBinding {
18
19
  }
19
20
  async rebindSession() {
20
21
  this.session = this.runtimeHost.session;
22
+ this.disposeSubscriptions();
21
23
  const session = this.session;
22
24
  this.renderService?.bindSession(session);
23
- await session.bindExtensions({
24
- uiContext: createRpcExtensionUIContext({
25
- output: this.output,
26
- pendingExtensionRequests: this.pendingExtensionRequests,
27
- customUi: this.customUi,
28
- sessionPicker: this.sessionPicker,
29
- inputForm: this.inputForm,
30
- }),
31
- mode: this.customUi ? "tui" : "rpc",
32
- commandContextActions: {
33
- waitForIdle: () => this.session.agent.waitForIdle(),
34
- newSession: async (options) => this.runtimeHost.newSession(options),
35
- fork: async (entryId, forkOptions) => {
36
- const result = await this.runtimeHost.fork(entryId, forkOptions);
37
- return { cancelled: result.cancelled };
38
- },
39
- navigateTree: async (targetId, options) => {
40
- const result = await this.session.navigateTree(targetId, {
41
- summarize: options?.summarize,
42
- customInstructions: options?.customInstructions,
43
- replaceInstructions: options?.replaceInstructions,
44
- label: options?.label,
45
- });
46
- return { cancelled: result.cancelled };
47
- },
48
- switchSession: async (sessionPath, options) => {
49
- return this.runtimeHost.switchSession(sessionPath, options);
25
+ this.footerDataProvider = new FooterDataProvider(session.sessionManager.getCwd());
26
+ // Seed the provider count from the current catalog snapshot, mirroring
27
+ // updateProviderCountFromSnapshot() in interactive startup, so the
28
+ // embedded footer shows the (provider) model prefix in multi-provider
29
+ // sessions instead of defaulting to 0.
30
+ const models = session.scopedModels.length > 0
31
+ ? session.scopedModels.map((scoped) => scoped.model)
32
+ : session.modelRegistry.getAvailable();
33
+ this.footerDataProvider.setAvailableProviderCount(new Set(models.map((model) => model.provider)).size);
34
+ try {
35
+ await session.bindExtensions({
36
+ uiContext: createRpcExtensionUIContext({
37
+ output: this.output,
38
+ pendingExtensionRequests: this.pendingExtensionRequests,
39
+ customUi: this.customUi,
40
+ sessionPicker: this.sessionPicker,
41
+ inputForm: this.inputForm,
42
+ footerDataProvider: this.footerDataProvider,
43
+ }),
44
+ mode: this.customUi ? "tui" : "rpc",
45
+ commandContextActions: {
46
+ waitForIdle: () => this.session.agent.waitForIdle(),
47
+ newSession: async (options) => this.runtimeHost.newSession(options),
48
+ fork: async (entryId, forkOptions) => {
49
+ const result = await this.runtimeHost.fork(entryId, forkOptions);
50
+ return { cancelled: result.cancelled };
51
+ },
52
+ navigateTree: async (targetId, options) => {
53
+ const result = await this.session.navigateTree(targetId, {
54
+ summarize: options?.summarize,
55
+ customInstructions: options?.customInstructions,
56
+ replaceInstructions: options?.replaceInstructions,
57
+ label: options?.label,
58
+ });
59
+ return { cancelled: result.cancelled };
60
+ },
61
+ switchSession: async (sessionPath, options) => {
62
+ return this.runtimeHost.switchSession(sessionPath, options);
63
+ },
64
+ reload: async () => {
65
+ const steeringMode = this.session.steeringMode;
66
+ const followUpMode = this.session.followUpMode;
67
+ if (this.reloadCoordinator)
68
+ await this.reloadCoordinator.reload(this.session);
69
+ else
70
+ await this.session.reload();
71
+ this.session.setSteeringMode(steeringMode);
72
+ this.session.setFollowUpMode(followUpMode);
73
+ },
50
74
  },
51
- reload: async () => {
52
- const steeringMode = this.session.steeringMode;
53
- const followUpMode = this.session.followUpMode;
54
- if (this.reloadCoordinator)
55
- await this.reloadCoordinator.reload(this.session);
56
- else
57
- await this.session.reload();
58
- this.session.setSteeringMode(steeringMode);
59
- this.session.setFollowUpMode(followUpMode);
75
+ shutdownHandler: this.requestShutdown,
76
+ onError: (err) => {
77
+ this.output({ type: "extension_error", extensionPath: err.extensionPath, event: err.event, error: err.error });
60
78
  },
61
- },
62
- shutdownHandler: this.requestShutdown,
63
- onError: (err) => {
64
- this.output({ type: "extension_error", extensionPath: err.extensionPath, event: err.event, error: err.error });
65
- },
66
- });
67
- this.disposeSubscriptions();
79
+ });
80
+ this.footerDataProvider.startGitWatcher();
81
+ }
82
+ catch (error) {
83
+ // Leave no partially-initialized footer state behind if extension
84
+ // binding fails; dispose the provider and rethrow.
85
+ this.footerDataProvider.dispose();
86
+ this.footerDataProvider = undefined;
87
+ throw error;
88
+ }
68
89
  this.unsubscribe = session.subscribe((event) => {
69
90
  this.output(event);
70
91
  });
@@ -76,8 +97,10 @@ export class RpcSessionBinding {
76
97
  disposeSubscriptions() {
77
98
  this.unsubscribe?.();
78
99
  this.unsubscribeBackpressure?.();
100
+ this.footerDataProvider?.dispose();
79
101
  this.unsubscribe = undefined;
80
102
  this.unsubscribeBackpressure = undefined;
103
+ this.footerDataProvider = undefined;
81
104
  }
82
105
  }
83
106
  //# sourceMappingURL=rpc-session-binding.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-session-binding.js","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-session-binding.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentSession } from \"../../core/agent-session.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport { waitForRawStdoutBackpressure } from \"../../core/output-guard.ts\";\nimport type { EngineCustomUiService } from \"../interactive-engine/engine-custom-ui.ts\";\nimport type { EngineInputFormService } from \"../interactive-engine/engine-input-form.ts\";\nimport type { EngineRenderService } from \"../interactive-engine/engine-render-service.ts\";\nimport type { EngineSessionPickerService } from \"../interactive-engine/engine-session-picker.ts\";\nimport { createRpcExtensionUIContext, type RpcPendingExtensionRequests } from \"./rpc-extension-ui.ts\";\nimport type { KeybindingsReloadCoordinator } from \"./rpc-keybindings-reload.ts\";\nimport type { RpcOutput } from \"./rpc-responses.ts\";\n\ninterface RpcSessionBindingOptions {\n\truntimeHost: AgentSessionRuntime;\n\toutput: RpcOutput;\n\tpendingExtensionRequests: RpcPendingExtensionRequests;\n\tcustomUi?: EngineCustomUiService;\n\trenderService?: EngineRenderService;\n\tsessionPicker?: EngineSessionPickerService;\n\tinputForm?: EngineInputFormService;\n\trequestShutdown: () => void;\n\treloadCoordinator?: KeybindingsReloadCoordinator<AgentSession>;\n}\n\nexport class RpcSessionBinding {\n\tprivate session: AgentSession;\n\tprivate unsubscribe?: () => void;\n\tprivate unsubscribeBackpressure?: () => void;\n\tprivate readonly runtimeHost: AgentSessionRuntime;\n\tprivate readonly output: RpcOutput;\n\tprivate readonly pendingExtensionRequests: RpcPendingExtensionRequests;\n\tprivate readonly customUi: EngineCustomUiService | undefined;\n\tprivate readonly renderService: EngineRenderService | undefined;\n\tprivate readonly sessionPicker: EngineSessionPickerService | undefined;\n\tprivate readonly inputForm: EngineInputFormService | undefined;\n\tprivate readonly requestShutdown: () => void;\n\tprivate readonly reloadCoordinator: KeybindingsReloadCoordinator<AgentSession> | undefined;\n\n\tconstructor({ runtimeHost, output, pendingExtensionRequests, requestShutdown, customUi, renderService, sessionPicker, inputForm, reloadCoordinator }: RpcSessionBindingOptions) {\n\t\tthis.runtimeHost = runtimeHost;\n\t\tthis.output = output;\n\t\tthis.pendingExtensionRequests = pendingExtensionRequests;\n\t\tthis.requestShutdown = requestShutdown;\n\t\tthis.customUi = customUi;\n\t\tthis.renderService = renderService;\n\t\tthis.sessionPicker = sessionPicker;\n\t\tthis.inputForm = inputForm;\n\t\tthis.reloadCoordinator = reloadCoordinator;\n\t\tthis.session = runtimeHost.session;\n\t}\n\n\tget currentSession(): AgentSession {\n\t\treturn this.session;\n\t}\n\n\tasync rebindSession(): Promise<void> {\n\t\tthis.session = this.runtimeHost.session;\n\t\tconst session = this.session;\n\t\tthis.renderService?.bindSession(session);\n\n\t\tawait session.bindExtensions({\n\t\t\tuiContext: createRpcExtensionUIContext({\n\t\t\t\toutput: this.output,\n\t\t\t\tpendingExtensionRequests: this.pendingExtensionRequests,\n\t\t\t\tcustomUi: this.customUi,\n\t\t\t\tsessionPicker: this.sessionPicker,\n\t\t\t\tinputForm: this.inputForm,\n\t\t\t}),\n\t\t\tmode: this.customUi ? \"tui\" : \"rpc\",\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => this.session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (options) => this.runtimeHost.newSession(options),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await this.runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, options) => {\n\t\t\t\t\tconst result = await this.session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: options?.summarize,\n\t\t\t\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\t\t\t\tlabel: options?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, options) => {\n\t\t\t\t\treturn this.runtimeHost.switchSession(sessionPath, options);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tconst steeringMode = this.session.steeringMode;\n\t\t\t\t\tconst followUpMode = this.session.followUpMode;\n\t\t\t\t\tif (this.reloadCoordinator) await this.reloadCoordinator.reload(this.session);\n\t\t\t\t\telse await this.session.reload();\n\t\t\t\t\tthis.session.setSteeringMode(steeringMode);\n\t\t\t\t\tthis.session.setFollowUpMode(followUpMode);\n\t\t\t\t},\n\t\t\t},\n\t\t\tshutdownHandler: this.requestShutdown,\n\t\t\tonError: (err) => {\n\t\t\t\tthis.output({ type: \"extension_error\", extensionPath: err.extensionPath, event: err.event, error: err.error });\n\t\t\t},\n\t\t});\n\n\t\tthis.disposeSubscriptions();\n\t\tthis.unsubscribe = session.subscribe((event) => {\n\t\t\tthis.output(event);\n\t\t});\n\t\tthis.unsubscribeBackpressure = session.agent.subscribe(async () => {\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t});\n\t\tthis.reloadCoordinator?.publishCurrentState(session);\n\t}\n\n\tdisposeSubscriptions(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.unsubscribeBackpressure?.();\n\t\tthis.unsubscribe = undefined;\n\t\tthis.unsubscribeBackpressure = undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"rpc-session-binding.js","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-session-binding.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentSession } from \"../../core/agent-session.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport { FooterDataProvider } from \"../../core/footer-data-provider.ts\";\nimport { waitForRawStdoutBackpressure } from \"../../core/output-guard.ts\";\nimport type { EngineCustomUiService } from \"../interactive-engine/engine-custom-ui.ts\";\nimport type { EngineInputFormService } from \"../interactive-engine/engine-input-form.ts\";\nimport type { EngineRenderService } from \"../interactive-engine/engine-render-service.ts\";\nimport type { EngineSessionPickerService } from \"../interactive-engine/engine-session-picker.ts\";\nimport { createRpcExtensionUIContext, type RpcPendingExtensionRequests } from \"./rpc-extension-ui.ts\";\nimport type { KeybindingsReloadCoordinator } from \"./rpc-keybindings-reload.ts\";\nimport type { RpcOutput } from \"./rpc-responses.ts\";\n\ninterface RpcSessionBindingOptions {\n\truntimeHost: AgentSessionRuntime;\n\toutput: RpcOutput;\n\tpendingExtensionRequests: RpcPendingExtensionRequests;\n\tcustomUi?: EngineCustomUiService;\n\trenderService?: EngineRenderService;\n\tsessionPicker?: EngineSessionPickerService;\n\tinputForm?: EngineInputFormService;\n\trequestShutdown: () => void;\n\treloadCoordinator?: KeybindingsReloadCoordinator<AgentSession>;\n}\n\nexport class RpcSessionBinding {\n\tprivate session: AgentSession;\n\tprivate unsubscribe?: () => void;\n\tprivate unsubscribeBackpressure?: () => void;\n\tprivate readonly runtimeHost: AgentSessionRuntime;\n\tprivate readonly output: RpcOutput;\n\tprivate readonly pendingExtensionRequests: RpcPendingExtensionRequests;\n\tprivate readonly customUi: EngineCustomUiService | undefined;\n\tprivate readonly renderService: EngineRenderService | undefined;\n\tprivate readonly sessionPicker: EngineSessionPickerService | undefined;\n\tprivate readonly inputForm: EngineInputFormService | undefined;\n\tprivate readonly requestShutdown: () => void;\n\tprivate readonly reloadCoordinator: KeybindingsReloadCoordinator<AgentSession> | undefined;\n\n\tprivate footerDataProvider: FooterDataProvider | undefined;\n\tconstructor({ runtimeHost, output, pendingExtensionRequests, requestShutdown, customUi, renderService, sessionPicker, inputForm, reloadCoordinator }: RpcSessionBindingOptions) {\n\t\tthis.runtimeHost = runtimeHost;\n\t\tthis.output = output;\n\t\tthis.pendingExtensionRequests = pendingExtensionRequests;\n\t\tthis.requestShutdown = requestShutdown;\n\t\tthis.customUi = customUi;\n\t\tthis.renderService = renderService;\n\t\tthis.sessionPicker = sessionPicker;\n\t\tthis.inputForm = inputForm;\n\t\tthis.reloadCoordinator = reloadCoordinator;\n\t\tthis.session = runtimeHost.session;\n\t}\n\n\tget currentSession(): AgentSession {\n\t\treturn this.session;\n\t}\n\n\tasync rebindSession(): Promise<void> {\n\t\tthis.session = this.runtimeHost.session;\n\t\tthis.disposeSubscriptions();\n\t\tconst session = this.session;\n\t\tthis.renderService?.bindSession(session);\n\t\tthis.footerDataProvider = new FooterDataProvider(session.sessionManager.getCwd());\n\t\t// Seed the provider count from the current catalog snapshot, mirroring\n\t\t// updateProviderCountFromSnapshot() in interactive startup, so the\n\t\t// embedded footer shows the (provider) model prefix in multi-provider\n\t\t// sessions instead of defaulting to 0.\n\t\tconst models = session.scopedModels.length > 0\n\t\t\t? session.scopedModels.map((scoped) => scoped.model)\n\t\t\t: session.modelRegistry.getAvailable();\n\t\tthis.footerDataProvider.setAvailableProviderCount(new Set(models.map((model) => model.provider)).size);\n\n\t\ttry {\n\t\t\tawait session.bindExtensions({\n\t\t\t\tuiContext: createRpcExtensionUIContext({\n\t\t\t\t\toutput: this.output,\n\t\t\t\t\tpendingExtensionRequests: this.pendingExtensionRequests,\n\t\t\t\t\tcustomUi: this.customUi,\n\t\t\t\t\tsessionPicker: this.sessionPicker,\n\t\t\t\t\tinputForm: this.inputForm,\n\t\t\t\t\tfooterDataProvider: this.footerDataProvider,\n\t\t\t\t}),\n\t\t\t\tmode: this.customUi ? \"tui\" : \"rpc\",\n\t\t\t\tcommandContextActions: {\n\t\t\t\t\twaitForIdle: () => this.session.agent.waitForIdle(),\n\t\t\t\t\tnewSession: async (options) => this.runtimeHost.newSession(options),\n\t\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\t\tconst result = await this.runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t\t},\n\t\t\t\t\tnavigateTree: async (targetId, options) => {\n\t\t\t\t\t\tconst result = await this.session.navigateTree(targetId, {\n\t\t\t\t\t\t\tsummarize: options?.summarize,\n\t\t\t\t\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\t\t\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\t\t\t\t\tlabel: options?.label,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t\t},\n\t\t\t\t\tswitchSession: async (sessionPath, options) => {\n\t\t\t\t\t\treturn this.runtimeHost.switchSession(sessionPath, options);\n\t\t\t\t\t},\n\t\t\t\t\treload: async () => {\n\t\t\t\t\t\tconst steeringMode = this.session.steeringMode;\n\t\t\t\t\t\tconst followUpMode = this.session.followUpMode;\n\t\t\t\t\t\tif (this.reloadCoordinator) await this.reloadCoordinator.reload(this.session);\n\t\t\t\t\t\telse await this.session.reload();\n\t\t\t\t\t\tthis.session.setSteeringMode(steeringMode);\n\t\t\t\t\t\tthis.session.setFollowUpMode(followUpMode);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tshutdownHandler: this.requestShutdown,\n\t\t\t\tonError: (err) => {\n\t\t\t\t\tthis.output({ type: \"extension_error\", extensionPath: err.extensionPath, event: err.event, error: err.error });\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.footerDataProvider.startGitWatcher();\n\t\t} catch (error) {\n\t\t\t// Leave no partially-initialized footer state behind if extension\n\t\t\t// binding fails; dispose the provider and rethrow.\n\t\t\tthis.footerDataProvider.dispose();\n\t\t\tthis.footerDataProvider = undefined;\n\t\t\tthrow error;\n\t\t}\n\n\t\tthis.unsubscribe = session.subscribe((event) => {\n\t\t\tthis.output(event);\n\t\t});\n\t\tthis.unsubscribeBackpressure = session.agent.subscribe(async () => {\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t});\n\t\tthis.reloadCoordinator?.publishCurrentState(session);\n\t}\n\n\tdisposeSubscriptions(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.unsubscribeBackpressure?.();\n\t\tthis.footerDataProvider?.dispose();\n\t\tthis.unsubscribe = undefined;\n\t\tthis.unsubscribeBackpressure = undefined;\n\t\tthis.footerDataProvider = undefined;\n\t}\n}\n"]}
package/dist/rpc-entry.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { insertForcedOptionsBeforeTerminator } from "./cli/args.js";
2
3
  import { APP_NAME } from "./config.js";
3
4
  import { configureHttpDispatcher } from "./core/http-dispatcher.js";
4
5
  import { main } from "./main.js";
@@ -7,6 +8,9 @@ process.env[`${APP_NAME.toUpperCase()}_CODING_AGENT`] = "true";
7
8
  process.emitWarning = (() => { });
8
9
  configureHttpDispatcher();
9
10
  // rpc-entry is the dedicated RPC entry point, so --mode rpc must always win
10
- // over any --mode the caller passes (the last --mode in the args wins).
11
- main([...process.argv.slice(2), "--mode", "rpc"]);
11
+ // over any --mode the caller passes (the last --mode in the args wins). The
12
+ // forced flags are inserted before any `--` end-of-options terminator so they
13
+ // are still parsed as options rather than literal message text; caller --mode
14
+ // flags can only appear before the terminator, so last-wins is preserved.
15
+ main(insertForcedOptionsBeforeTerminator(process.argv.slice(2), ["--mode", "rpc"]));
12
16
  //# sourceMappingURL=rpc-entry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-entry.js","sourceRoot":"","sources":["../src/rpc-entry.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,CAAC,KAAK,GAAG,GAAG,QAAQ,MAAM,CAAC;AAClC,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG,MAAM,CAAC;AAC/D,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,EAAE,GAAE,CAAC,CAA+B,CAAC;AAE/D,uBAAuB,EAAE,CAAC;AAE1B,4EAA4E;AAC5E,wEAAwE;AACxE,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { APP_NAME } from \"./config.ts\";\nimport { configureHttpDispatcher } from \"./core/http-dispatcher.ts\";\nimport { main } from \"./main.ts\";\n\nprocess.title = `${APP_NAME}-rpc`;\nprocess.env[`${APP_NAME.toUpperCase()}_CODING_AGENT`] = \"true\";\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nconfigureHttpDispatcher();\n\n// rpc-entry is the dedicated RPC entry point, so --mode rpc must always win\n// over any --mode the caller passes (the last --mode in the args wins).\nmain([...process.argv.slice(2), \"--mode\", \"rpc\"]);\n"]}
1
+ {"version":3,"file":"rpc-entry.js","sourceRoot":"","sources":["../src/rpc-entry.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,mCAAmC,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,CAAC,KAAK,GAAG,GAAG,QAAQ,MAAM,CAAC;AAClC,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG,MAAM,CAAC;AAC/D,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,EAAE,GAAE,CAAC,CAA+B,CAAC;AAE/D,uBAAuB,EAAE,CAAC;AAE1B,4EAA4E;AAC5E,4EAA4E;AAC5E,8EAA8E;AAC9E,8EAA8E;AAC9E,0EAA0E;AAC1E,IAAI,CAAC,mCAAmC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { insertForcedOptionsBeforeTerminator } from \"./cli/args.ts\";\nimport { APP_NAME } from \"./config.ts\";\nimport { configureHttpDispatcher } from \"./core/http-dispatcher.ts\";\nimport { main } from \"./main.ts\";\n\nprocess.title = `${APP_NAME}-rpc`;\nprocess.env[`${APP_NAME.toUpperCase()}_CODING_AGENT`] = \"true\";\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nconfigureHttpDispatcher();\n\n// rpc-entry is the dedicated RPC entry point, so --mode rpc must always win\n// over any --mode the caller passes (the last --mode in the args wins). The\n// forced flags are inserted before any `--` end-of-options terminator so they\n// are still parsed as options rather than literal message text; caller --mode\n// flags can only appear before the terminator, so last-wins is preserved.\nmain(insertForcedOptionsBeforeTerminator(process.argv.slice(2), [\"--mode\", \"rpc\"]));\n"]}
@@ -0,0 +1,8 @@
1
+ export declare function enablePersistentCompileCache(): void;
2
+ /**
3
+ * Persist the compile cache accumulated so far. Called before spawning the
4
+ * interactive engine child so the child's load of the same module graph hits
5
+ * the cache even on the very first run after an install.
6
+ */
7
+ export declare function flushPersistentCompileCache(): void;
8
+ //# sourceMappingURL=compile-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-cache.d.ts","sourceRoot":"","sources":["../../src/utils/compile-cache.ts"],"names":[],"mappings":"AAgBA,wBAAgB,4BAA4B,IAAI,IAAI,CAMnD;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAMlD"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Best-effort wrappers around Node's on-disk V8 compile cache. On Node >= 22.8
3
+ * the cache persists compiled module bytecode across runs, which substantially
4
+ * reduces module-graph load time on platforms with slow cold starts (Windows).
5
+ * Bun and older Node versions do not expose these APIs, so both wrappers are
6
+ * silent no-ops there.
7
+ */
8
+ import nodeModule from "node:module";
9
+ const compileCacheApi = nodeModule;
10
+ export function enablePersistentCompileCache() {
11
+ try {
12
+ compileCacheApi.enableCompileCache?.();
13
+ }
14
+ catch {
15
+ // Best effort: an unwritable cache directory must never break startup.
16
+ }
17
+ }
18
+ /**
19
+ * Persist the compile cache accumulated so far. Called before spawning the
20
+ * interactive engine child so the child's load of the same module graph hits
21
+ * the cache even on the very first run after an install.
22
+ */
23
+ export function flushPersistentCompileCache() {
24
+ try {
25
+ compileCacheApi.flushCompileCache?.();
26
+ }
27
+ catch {
28
+ // Best effort.
29
+ }
30
+ }
31
+ //# sourceMappingURL=compile-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-cache.js","sourceRoot":"","sources":["../../src/utils/compile-cache.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,UAAU,MAAM,aAAa,CAAC;AAOrC,MAAM,eAAe,GAAoB,UAAU,CAAC;AAEpD,MAAM,UAAU,4BAA4B;IAC3C,IAAI,CAAC;QACJ,eAAe,CAAC,kBAAkB,EAAE,EAAE,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACR,uEAAuE;IACxE,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B;IAC1C,IAAI,CAAC;QACJ,eAAe,CAAC,iBAAiB,EAAE,EAAE,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACR,eAAe;IAChB,CAAC;AACF,CAAC","sourcesContent":["/**\n * Best-effort wrappers around Node's on-disk V8 compile cache. On Node >= 22.8\n * the cache persists compiled module bytecode across runs, which substantially\n * reduces module-graph load time on platforms with slow cold starts (Windows).\n * Bun and older Node versions do not expose these APIs, so both wrappers are\n * silent no-ops there.\n */\nimport nodeModule from \"node:module\";\n\ninterface CompileCacheApi {\n\tenableCompileCache?: () => unknown;\n\tflushCompileCache?: () => void;\n}\n\nconst compileCacheApi: CompileCacheApi = nodeModule;\n\nexport function enablePersistentCompileCache(): void {\n\ttry {\n\t\tcompileCacheApi.enableCompileCache?.();\n\t} catch {\n\t\t// Best effort: an unwritable cache directory must never break startup.\n\t}\n}\n\n/**\n * Persist the compile cache accumulated so far. Called before spawning the\n * interactive engine child so the child's load of the same module graph hits\n * the cache even on the very first run after an install.\n */\nexport function flushPersistentCompileCache(): void {\n\ttry {\n\t\tcompileCacheApi.flushCompileCache?.();\n\t} catch {\n\t\t// Best effort.\n\t}\n}\n"]}
package/docs/tui.md CHANGED
@@ -871,6 +871,8 @@ ctx.ui.setFooter((tui, theme, footerData) => ({
871
871
  ctx.ui.setFooter(undefined); // restore default
872
872
  ```
873
873
 
874
+ `ctx.ui.getFooterDataProvider()` exposes the same read-only provider to embedded extension UIs. In isolated interactive mode Atomic maintains the provider inside the engine session, mirrors every `setStatus()` update into it, and uses the session cwd with the same cached Git-branch watcher, so synchronous renderers can read current status and branch data without an RPC round trip or per-render Git process.
875
+
874
876
  Token stats available via `ctx.sessionManager.getBranch()` and `ctx.model`.
875
877
 
876
878
  **Examples:** [custom-footer.ts](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/examples/extensions/custom-footer.ts)
package/docs/usage.md CHANGED
@@ -130,6 +130,12 @@ Treat exported and shared sessions as sensitive: transcripts can contain source
130
130
  atomic [options] [@files...] [messages...]
131
131
  ```
132
132
 
133
+ Use `--` to end option parsing when positional prompt text begins with `-`, `--`, or `@`. Every argument after the terminator is treated as literal message text rather than an option or file argument:
134
+
135
+ ```bash
136
+ atomic --print -- "- leading-dash prompt"
137
+ ```
138
+
133
139
  ### Package Commands
134
140
 
135
141
  ```bash
@@ -290,6 +296,7 @@ atomic --tools read,search,find,ls -p "Review the code"
290
296
  | `ATOMIC_OFFLINE` | Disable startup network operations, including update checks, package update checks, and install/update telemetry |
291
297
  | `ATOMIC_SKIP_VERSION_CHECK` | Skip the Atomic version update check at startup. This prevents the latest-version request |
292
298
  | `ATOMIC_TELEMETRY` | Override install/update telemetry: `1`/`true`/`yes` or `0`/`false`/`no`. This does not disable update checks |
299
+ | `NODE_COMPILE_CACHE` | Override the directory for Node's persistent compile cache, which Atomic enables automatically on Node >= 22.8 to speed up startup (most noticeable on Windows). Set `NODE_DISABLE_COMPILE_CACHE=1` to opt out |
293
300
  | `PI_CACHE_RETENTION` | Provider/upstream-specific prompt-cache retention knob; set to `long` where supported |
294
301
  | `VISUAL`, `EDITOR` | External editor for CTRL+G |
295
302
 
package/docs/workflows.md CHANGED
@@ -110,7 +110,7 @@ List and run it like any other workflow:
110
110
  /workflow <name> key=value ...
111
111
  ```
112
112
 
113
- Named workflow runs execute in the background. After launch, expect a run id and monitor it with `/workflow status <run-id>`, F2, or `/workflow connect <run-id>`.
113
+ Named workflow runs execute in the background. By default, after launch expect a run id and monitor it with `/workflow status <run-id>`, F2, or `/workflow connect <run-id>`. A definition with `autoAttach: true` instead opens the graph overlay as soon as an interactive top-level named launch through `/workflow <name>` or the registered `workflow` tool is accepted. This option does not affect headless launches or nested `ctx.workflow(...)` calls, and existing input-form launch behavior is unchanged.
114
114
 
115
115
  While a workflow is running, the visible below-editor `BACKGROUND` panel advances its elapsed label every second from the moment the run starts; it does not require opening or switching to the orchestrator. Updates repaint the existing mounted panel in place, paused timers stay frozen, and terminal cards retain their short recent-run expiry.
116
116
 
@@ -414,12 +414,12 @@ Inputs:
414
414
 
415
415
  | Input | Type | Required | Default | Description |
416
416
  |---|---|---|---|---|
417
- | `objective` | text | yes | — | Goal-runner objective or delta. Include the desired end state, expected outcome, testing/validation instructions, and any explicit done criteria. |
417
+ | `objective` | text | yes | — | Goal-runner objective or delta. Include the desired end state, expected outcome, testing/validation instructions, and any explicit done criteria. Do not include PR/MR submission instructions here; strip them from the task text and request them via `create_pr=true` instead. |
418
418
  | `acceptance_criteria` | text | no | objective | Original immutable task contract that the run must remain consistent with. When launching a follow-up `goal` run from review findings, pass the ORIGINAL task text here so reviewer suggestions cannot drift or contradict the literal contract. |
419
419
  | `max_turns` | number | no | `10` | Maximum worker/review turns before human follow-up is needed. |
420
420
  | `base_branch` | string | no | `origin/main` | Branch reviewers and the optional final stage compare the current code delta against; also used to create a missing worktree. |
421
- | `git_worktree_dir` | string | no | `""` | Optional reusable Git worktree root. Empty runs in the invoking checkout; non-empty values run Goal stages in the created/reused worktree. |
422
- | `create_pr` | boolean | no | `false` | Safe-by-default PR creation flag. Omitted or `false` skips the final `pull-request` stage and omits `pr_report`; prompt text alone does not opt in, and only strict `true` authorizes the final `pull-request` stage to attempt provider-appropriate PR/MR/review creation after Goal reaches `complete`. |
421
+ | `git_worktree_dir` | string | no | `""` | Optional reusable Git worktree root. Empty runs in the invoking checkout; non-empty values run Goal stages in the created/reused worktree. Set it only when the user explicitly requested worktree isolation — worker stages are instructed never to create git worktrees, clones, or repository copies on their own. |
422
+ | `create_pr` | boolean | no | `false` | Safe-by-default PR creation flag. Omitted or `false` skips the final `pull-request` stage and omits `pr_report`; prompt text alone does not opt in, and only strict `true` authorizes the final `pull-request` stage to attempt provider-appropriate PR/MR/review creation after Goal reaches `complete`. If the delegated task asks to submit a PR/MR/review, remove that instruction from `objective` and set `create_pr=true` instead. |
423
423
 
424
424
  `goal` defaults to 10 worker/review turns. Reviewer quorum is fixed internally at 2 reviewer `complete` votes, and approval is deterministic on each reviewer's self-reported `stop_review_loop` boolean: a reviewer approves exactly when it returns `stop_review_loop=true` with no `reviewer_error` (schema-parse failures count as non-approval), and the reducer completes the run when quorum of those booleans is met without recomputing approval from findings arrays or traceability statuses. The repeated-blocker threshold defaults to 3 consecutive same-blocker turns and is clamped to `max_turns` when you run fewer than 3 turns.
425
425
 
@@ -429,7 +429,7 @@ Run examples:
429
429
  /workflow goal objective="Implement specs/2026-03-rate-limit.md, add the requested regression tests, run bun test packages/api/rate-limit.test.ts, and finish only when burst traffic returns 429 with Retry-After"
430
430
  /workflow goal objective="Update the CLI docs to describe the new --json flag, include one usage example, and verify the docs build still passes" max_turns=3
431
431
  /workflow goal objective="Fix the settings form validation bug; add/adjust the focused test and consider it done when invalid emails show the inline error without submitting"
432
- /workflow goal objective="Implement the focused docs fix, run the docs validation command, and open a PR when complete" create_pr=true
432
+ /workflow goal objective="Implement the focused docs fix and run the docs validation command" create_pr=true
433
433
  /workflow goal objective="Fix the flaky package install test in an isolated worktree and run the focused regression" git_worktree_dir=../atomic-goal-install-wt base_branch=main
434
434
  ```
435
435
 
@@ -449,12 +449,14 @@ Goal worker/reviewer prompts treat the objective and acceptance criteria as the
449
449
 
450
450
  Reviewer findings carry `objective_alignment` (`required_by_objective`, `consistent_with_objective`, `beyond_objective`, or `contradicts_objective`); `beyond_objective` and `contradicts_objective` findings are reported but do not block completion and must not be promoted into follow-up objectives without reconciling them against the acceptance criteria. Severity labels alone never dismiss objective-relevant findings: `required_by_objective` findings block at any priority (P3 included), while `consistent_with_objective` P3 nice-to-haves stay non-blocking.
451
451
 
452
- Review decisions also include `requirements_traceability`, a clause-by-clause evidence map over every explicit objective/acceptance-criteria requirement. Findings and traceability are audit evidence that drive how each reviewer derives its authoritative `stop_review_loop` boolean; the harness gates approval on that boolean alone, and Goal tells reviewers that process-only clauses (reviewer quorum/approval counts, and the authorized post-approval PR/MR/review final action when `create_pr=true`) must never hold the flag at `false`.
452
+ Review decisions also include `requirements_traceability`, a clause-by-clause evidence map over every explicit objective/acceptance-criteria requirement. Findings and traceability are audit evidence that drive how each reviewer derives its authoritative `stop_review_loop` boolean; the harness gates approval on that boolean alone, and Goal tells reviewers that process-only clauses (reviewer quorum/approval counts, and the authorized post-approval PR/MR/review final action when `create_pr=true`) must never hold the flag at `false`. Reviewers must also first prove the code delta actually exists in the review checkout (the invoking cwd or explicitly configured worktree): receipts claiming implemented work over an empty or unrelated delta are a blocking finding rather than grounds for approval, and modifications, renames, or deletions of pre-existing tests require explicit justification.
453
453
 
454
454
  Passing worker-authored tests or snapshots alone is circular evidence unless tied to independent current-state proof.
455
455
 
456
456
  The worker may claim readiness, but it cannot finalize completion. Before implementing, Goal prompts the worker to derive an observable acceptance/contract matrix from the literal objective/acceptance criteria (one row per clause, each mapped to the concrete check that proves it) and to model states, transitions, and invariants explicitly when the work is stateful.
457
457
 
458
+ Delivery is part of readiness: unless the objective or acceptance criteria explicitly forbid committing, worker prompts require committing the work in the current checkout with a descriptive message before claiming readiness — verifying a clean working tree with the repository's version-control status command — and reporting the commit identifier in the receipt. Reviewers back this with the code-delta contract: uncommitted work at claimed readiness is remaining work, and a checkout whose delta is empty or unrelated to the objective can never be approved regardless of what receipts claim. Verification stays with prompts and reviewers using the repository's own version-control tooling, so no single VCS provider is hardcoded into the runner.
459
+
458
460
  Goal consolidates the latest reviewer findings into a deduplicated cross-reviewer batch persisted in the round artifact (`consolidated_findings` in `review-round-latest.json`), and the next worker prompt instructs the worker to plan and repair the whole batch — with durable regression evidence for reproduced findings — rather than fixing one finding per turn. Goal prompts workers and reviewers to verify user-visible behavior end-to-end when practical, using `playwright-cli`-skilled subagents for web/frontend flows that may depend on backend/API behavior and tmux-skilled subagents for TUI or terminal-app scenarios.
459
461
 
460
462
  They must assume credentials/auth/environment access exists until concrete checks plus an actual app/flow launch attempt prove otherwise; reviewers accept skipped E2E only when the worker records the exact attempted commands and observed failure output. Goal reviewers also look for any QA E2E video referenced by the ledger or receipt and must inspect the actual video before treating it as proof.
@@ -500,12 +502,12 @@ Inputs:
500
502
 
501
503
  | Input | Type | Required | Default | Description |
502
504
  |---|---|---|---|---|
503
- | `prompt` | text | yes | — | Task, feature request, issue summary, or spec path to research, execute, refine, and review. |
505
+ | `prompt` | text | yes | — | Task, feature request, issue summary, or spec path to research, execute, refine, and review. Do not include PR/MR submission instructions here; strip them from the task text and request them via `create_pr=true` instead. |
504
506
  | `acceptance_criteria` | text | no | prompt | Original immutable task contract that the run must remain consistent with. When launching a follow-up `ralph` run from review findings, pass the ORIGINAL task text here so reviewer suggestions cannot drift or contradict the literal contract. |
505
507
  | `max_loops` | number | no | `10` | Maximum research/orchestrate/review iterations before the workflow completes or reports the remaining work without reviewer approval. |
506
508
  | `base_branch` | string | no | `origin/main` | Branch reviewers and the optional final stage compare the current code delta against; also used to create a missing worktree. |
507
- | `git_worktree_dir` | string | no | `""` | Optional reusable Git worktree root. Empty runs in the invoking checkout; non-empty values run Ralph stages in the created/reused worktree. |
508
- | `create_pr` | boolean | no | `false` | Safe-by-default PR creation flag. Omitted or `false` skips the final `pull-request` stage and omits `pr_report`; prompt text alone does not opt in, and only strict `true` authorizes the final `pull-request` stage to attempt provider-appropriate PR/MR/review creation. |
509
+ | `git_worktree_dir` | string | no | `""` | Optional reusable Git worktree root. Empty runs in the invoking checkout; non-empty values run Ralph stages in the created/reused worktree. Set it only when the user explicitly requested worktree isolation — orchestrator stages are instructed never to create git worktrees, clones, or repository copies on their own. |
510
+ | `create_pr` | boolean | no | `false` | Safe-by-default PR creation flag. Omitted or `false` skips the final `pull-request` stage and omits `pr_report`; prompt text alone does not opt in, and only strict `true` authorizes the final `pull-request` stage to attempt provider-appropriate PR/MR/review creation. If the delegated task asks to submit a PR/MR/review, remove that instruction from `prompt` and set `create_pr=true` instead. |
509
511
 
510
512
  Run examples:
511
513
 
@@ -533,7 +535,7 @@ If reviewers find issues, the next `research-prompt-refinement` and research sta
533
535
 
534
536
  Ralph findings include the same `objective_alignment` classification used by Goal, and each reviewer derives a single authoritative `stop_review_loop` boolean from that evidence: `required_by_objective` findings mean `false` at any priority (P3 included, because severity labels alone never dismiss objective-relevant findings), `consistent_with_objective` P0/P1/P2 findings mean `false` while P3 remains a non-blocking nice-to-have, and `beyond_objective`/`contradicts_objective` findings are surfaced but non-blocking so they are not silently converted into new requirements.
535
537
 
536
- The loop gate approves deterministically on `stop_review_loop=true` plus a null `reviewer_error` (parse failures count as non-approval) without recomputing approval from the findings arrays. Ralph review decisions also include `requirements_traceability`, a clause-by-clause evidence map over every explicit prompt/acceptance-criteria requirement kept as audit evidence for deriving the flag; reviewers are explicitly told that process-only clauses (reviewer quorum, and the authorized post-approval PR/MR/review final action when `create_pr=true`) must never hold the flag at `false`.
538
+ The loop gate approves deterministically on `stop_review_loop=true` plus a null `reviewer_error` (parse failures count as non-approval) without recomputing approval from the findings arrays. Ralph review decisions also include `requirements_traceability`, a clause-by-clause evidence map over every explicit prompt/acceptance-criteria requirement kept as audit evidence for deriving the flag; reviewers are explicitly told that process-only clauses (reviewer quorum, and the authorized post-approval PR/MR/review final action when `create_pr=true`) must never hold the flag at `false`. Reviewers must also first prove the code delta actually exists in the review checkout (the invoking cwd or explicitly configured worktree): receipts claiming implemented work over an empty or unrelated delta are a blocking finding rather than grounds for approval, and modifications, renames, or deletions of pre-existing tests require explicit justification.
537
539
 
538
540
  Passing worker-authored tests or snapshots is circular evidence unless tied to independent current-state proof. By default Ralph does not start the final `pull-request` stage, and `pr_report` is omitted. Prompt text alone does not opt in. Pass `create_pr=true` only when you explicitly want the final `pull-request` stage to inspect provider credentials and attempt provider-appropriate PR/MR/review creation, such as GitHub `gh`, Azure Repos `az repos pr create`, or Sapling/Phabricator tooling; Ralph's own PR-creation instructions live in that final stage and run only after approval.
539
541
 
@@ -728,6 +730,7 @@ Authoring basics:
728
730
  - `workflow({ ... })` returns the workflow definition directly for discovery; there is no builder terminal step.
729
731
  - Workflow names normalize for lookup: trim, lowercase, convert whitespace/underscore to hyphen, remove other punctuation, and collapse hyphens.
730
732
  - `description` sets the listing text.
733
+ - `autoAttach: true` opens the graph overlay when an interactive top-level named launch through `/workflow <name>` or the registered `workflow` tool is accepted. Only exact `true` is retained on the compiled definition; omission and `false` do not opt a definition into auto-attachment. Existing input-form launch behavior is unchanged.
731
734
  - `inputs` declares typed user inputs.
732
735
  - `worktreeFromInputs` optionally maps input names to workflow-wide reusable Git worktree defaults.
733
736
  - `outputs` declares typed outputs that parent workflows receive from `ctx.workflow(childWorkflow, ...)`.
@@ -1226,6 +1229,14 @@ readonly description: string;
1226
1229
 
1227
1230
  Discovery and inspection surfaces show this required listing text. The compiled definition preserves it unchanged.
1228
1231
 
1232
+ ### `autoAttach`
1233
+
1234
+ ```typescript
1235
+ readonly autoAttach?: boolean;
1236
+ ```
1237
+
1238
+ Exact `true` opts interactive top-level named launches through `/workflow <name>` and the registered `workflow` tool into opening the graph overlay immediately. Omission and `false` do not opt in. This option does not affect headless launches, nested `ctx.workflow(...)` calls, or the existing input-form launch path. Compiled definitions retain this field only as literal `true`.
1239
+
1229
1240
  ### `inputs`
1230
1241
 
1231
1242
  ```typescript
@@ -1301,6 +1312,7 @@ interface WorkflowDefinition<
1301
1312
  readonly name: string;
1302
1313
  readonly normalizedName: string;
1303
1314
  readonly description: string;
1315
+ readonly autoAttach?: true;
1304
1316
  readonly inputs: WorkflowInputSchemaMap;
1305
1317
  readonly outputs?: WorkflowOutputSchemaMap;
1306
1318
  readonly inputBindings?: { readonly worktree?: WorkflowWorktreeInputBinding };
@@ -1343,6 +1355,14 @@ readonly cwd?: string;
1343
1355
 
1344
1356
  Invocation working directory for workflow-owned artifacts. It defaults to the host process cwd when omitted.
1345
1357
 
1358
+ ### `ctx.models`
1359
+
1360
+ ```typescript
1361
+ readonly models?: WorkflowModelCatalogPort;
1362
+ ```
1363
+
1364
+ Model catalog port for the invoking session, when the host provides one. `models.currentModel` is the user-selected session model; leading a stage's model chain with it (bare, without a `:thinking` suffix) runs the stage at the session's model and default thinking level. `models.listModels()` returns the available catalog. The field is absent when no host catalog exists (for example some detached executions), so definitions should treat it as optional and fall back to their own model configuration.
1365
+
1346
1366
  ### `ctx.task(name, options)`
1347
1367
 
1348
1368
  ```typescript
@@ -1588,10 +1608,12 @@ readonly group?: string | true;
1588
1608
 
1589
1609
  Sets the stage session's [Intercom](/intercom) home group so orchestrated stages can be isolated into coordination groups: a stage in group G can only intercom peers in G. Provide a named string to join that group, or boolean `true` to auto-generate one shared UUID group **per `ctx.parallel(...)` set** (minted once and shared across every item in that set — never a fresh id per item), so a whole level of reviewers lands in the same isolated group. Authored workflow values accept the trimmed, case-insensitive string sentinels `"true"` and `"auto"`. Those two names are reserved for automatic grouping; use a different name when you need a literal named group. Omit `group` to inherit per the precedence chain (ultimately `"default"`).
1590
1610
 
1591
- `group` is accepted at every level — run-level defaults (`context`), `stage`/`task`, `parallel` step options, and per parallel itemand resolves most-specific-first: `parallel-item > task/stage > parallel-step > run-level`. The resolved value is injected per-session (race-safe across concurrently running in-process stages, stable across model fallback). Group assignment is **gated on intercom capability**: a stage with `noTools`, a `tools` allowlist that omits `intercom`, or `excludedTools` containing `intercom` is never placed into a group (so an agent is never isolated into a group it cannot use). Subagents spawned by a grouped stage inherit that stage's group by default (see [subagents.md](/subagents)), so a reviewer level and its helper subagents form one isolated group. The subagent-only `contact_supervisor` channel still reaches the supervisor across group boundaries through a broker capability bound to the child/supervisor relationship and restored across reconnects; ordinary client `send` frames never gain cross-group authority from a channel flag.
1611
+ `group` is accepted on `stage`/`task` options, on `ctx.parallel(...)` options, and per parallel stepa step-level `group` overrides the parallel options' `group`. The resolved value is injected per-session (race-safe across concurrently running in-process stages, stable across model fallback). Group assignment is **gated on intercom capability**: a stage with `noTools`, a `tools` allowlist that omits `intercom`, or `excludedTools` containing `intercom` is never placed into a group (so an agent is never isolated into a group it cannot use). Subagents spawned by a grouped stage inherit that stage's group by default (see [subagents.md](/subagents)), so a reviewer level and its helper subagents form one isolated group. The subagent-only `contact_supervisor` channel still reaches the supervisor across group boundaries through a broker capability bound to the child/supervisor relationship and restored across reconnects; ordinary client `send` frames never gain cross-group authority from a channel flag.
1592
1612
 
1593
1613
  The builtin `goal` and `ralph` workflows use this to isolate each reviewer level into its own group (`goal-reviewers-turn-N` / `ralph-reviewers-iter-N`): same-level reviewers coordinate with each other but cannot reach the worker, orchestrator, parent chat, or other levels, which also keeps reviewer intercom chatter out of the main/parent context window.
1594
1614
 
1615
+ **Recommended default:** unless the user requests otherwise, give each workflow invocation its own intercom group. To share one group across every stage of the invocation, mint one invocation-scoped literal name inside the workflow's `run` function (for example `const group = "myflow-" + randomUUID();` from `node:crypto`) and pass it via the `group` option on each stage, task, or parallel step; note that `group: true` is only shared per `ctx.parallel(...)` set and mints a fresh UUID per non-parallel stage, so it isolates stages from each other rather than grouping the whole run. Ungrouped sessions all collapse into the shared `"default"` group, so an ungrouped workflow's stage and subagent intercom traffic — including async subagent-result notices — can reach the parent chat and other concurrent runs. The shipped workflow prompt guidance instructs agents to isolate invocations this way by default.
1616
+
1595
1617
  ### `model`
1596
1618
 
1597
1619
  ```typescript
@@ -2281,6 +2303,7 @@ Surface behavior:
2281
2303
  - **Reserved keys** - `ctrl+d` and `q` do not navigate workflow surfaces; `ctrl+d` keeps its ordinary editor or prompt behavior where applicable, and `q` remains printable in text-owning prompts. Existing `esc`, `ctrl+c`, and graph `h` close/hide controls are unchanged.
2282
2304
  - **Wheel and trackpad** - While the workflow graph is active, vertical wheel/trackpad gestures pan it up and down, and horizontal gestures pan wide graphs left and right when the terminal exposes horizontal wheel events; these gestures remain scoped to the graph instead of leaking into the main chat or terminal scrollback. Attached stage chats capture mouse/trackpad wheel events by default so scrolling stays inside the active stage transcript or prompt instead of falling through to terminal/main-chat scrollback.
2283
2305
  - **Tool and node detail** - Attached stage chats match main chat's tool-detail expansion behavior while keeping expansion state local to the workflow UI context. Press Ctrl+O (the configurable `app.tools.expand` binding) to expand every visible workflow node and tool card, including single, parallel, and chain subagent progress, current tool activity, and artifact paths; press it again to collapse them. The toggle works for active, completed, and archived stage views, including at the supported 40-column terminal minimum. A mounted prompt, custom question, or other input-owning overlay keeps the key instead of changing expansion.
2306
+ - **Footer context** - An attached live stage chat carries the main chat's current-folder and Git-branch identity into its themed footer and mirrors live extension status lines such as the MCP server indicator. Branch changes trigger a repaint through the host's cached footer provider, and extension status changes are read from that same provider rather than recomputed by the workflow UI.
2284
2307
  - **Async statusline** - If an async/background subagent is running while the fullscreen workflow graph is open, the graph statusline mirrors the async summary so the background run remains visible; hide the graph with `h`, leave it with `ctrl+x`, or reconnect later to return to the full below-editor async widget.
2285
2308
  - **Copy mode** - Press `ctrl+t` inside an attached stage chat to toggle **copy mode**: copy mode disables workflow-chat mouse reporting so normal terminal/tmux text selection can work; press `ctrl+t` again to leave copy mode and restore transcript or prompt scrolling. Archived read-only stage transcripts expose the same footer and copy-mode status, so their text can also be selected and copied; `esc` closes the transcript and `ctrl+x` returns to the graph. While copy mode is on, wheel/trackpad gestures are handled by the terminal/tmux and may scroll terminal scrollback, so leave copy mode before using the wheel again.
2286
2309
  - **Run control** - Use `interrupt`, `pause`, and `resume` for resumable live work; `resume` on a non-paused run reopens the saved snapshot or overlay. Use `quit` to pause a live run gracefully while preserving it for `/workflow resume`.
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.11-alpha.3",
3
+ "version": "0.9.11-alpha.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bastani/atomic",
9
- "version": "0.9.11-alpha.3",
9
+ "version": "0.9.11-alpha.4",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@bastani/atomic-natives": "0.9.11-alpha.3",
12
+ "@bastani/atomic-natives": "0.9.11-alpha.4",
13
13
  "@bufbuild/protobuf": "^2.12.1",
14
14
  "@dbos-inc/dbos-sdk": "4.23.6",
15
15
  "@earendil-works/pi-agent-core": "^0.81.1",
@@ -516,16 +516,16 @@
516
516
  }
517
517
  },
518
518
  "node_modules/@bastani/atomic-natives": {
519
- "version": "0.9.11-alpha.3",
520
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.11-alpha.3.tgz",
519
+ "version": "0.9.11-alpha.4",
520
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.11-alpha.4.tgz",
521
521
  "license": "MIT",
522
522
  "optionalDependencies": {
523
- "@bastani/atomic-natives-darwin-arm64": "0.9.11-alpha.3",
524
- "@bastani/atomic-natives-darwin-x64": "0.9.11-alpha.3",
525
- "@bastani/atomic-natives-linux-arm64-gnu": "0.9.11-alpha.3",
526
- "@bastani/atomic-natives-linux-x64-gnu": "0.9.11-alpha.3",
527
- "@bastani/atomic-natives-win32-arm64-msvc": "0.9.11-alpha.3",
528
- "@bastani/atomic-natives-win32-x64-msvc": "0.9.11-alpha.3"
523
+ "@bastani/atomic-natives-darwin-arm64": "0.9.11-alpha.4",
524
+ "@bastani/atomic-natives-darwin-x64": "0.9.11-alpha.4",
525
+ "@bastani/atomic-natives-linux-arm64-gnu": "0.9.11-alpha.4",
526
+ "@bastani/atomic-natives-linux-x64-gnu": "0.9.11-alpha.4",
527
+ "@bastani/atomic-natives-win32-arm64-msvc": "0.9.11-alpha.4",
528
+ "@bastani/atomic-natives-win32-x64-msvc": "0.9.11-alpha.4"
529
529
  },
530
530
  "engines": {
531
531
  "bun": ">=1.3.14",
@@ -533,8 +533,8 @@
533
533
  }
534
534
  },
535
535
  "node_modules/@bastani/atomic-natives-darwin-arm64": {
536
- "version": "0.9.11-alpha.3",
537
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.11-alpha.3.tgz",
536
+ "version": "0.9.11-alpha.4",
537
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.11-alpha.4.tgz",
538
538
  "license": "MIT",
539
539
  "os": [
540
540
  "darwin"
@@ -545,8 +545,8 @@
545
545
  "optional": true
546
546
  },
547
547
  "node_modules/@bastani/atomic-natives-darwin-x64": {
548
- "version": "0.9.11-alpha.3",
549
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.11-alpha.3.tgz",
548
+ "version": "0.9.11-alpha.4",
549
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.11-alpha.4.tgz",
550
550
  "license": "MIT",
551
551
  "os": [
552
552
  "darwin"
@@ -557,8 +557,8 @@
557
557
  "optional": true
558
558
  },
559
559
  "node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
560
- "version": "0.9.11-alpha.3",
561
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.11-alpha.3.tgz",
560
+ "version": "0.9.11-alpha.4",
561
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.11-alpha.4.tgz",
562
562
  "license": "MIT",
563
563
  "os": [
564
564
  "linux"
@@ -572,8 +572,8 @@
572
572
  "optional": true
573
573
  },
574
574
  "node_modules/@bastani/atomic-natives-linux-x64-gnu": {
575
- "version": "0.9.11-alpha.3",
576
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.11-alpha.3.tgz",
575
+ "version": "0.9.11-alpha.4",
576
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.11-alpha.4.tgz",
577
577
  "license": "MIT",
578
578
  "os": [
579
579
  "linux"
@@ -587,8 +587,8 @@
587
587
  "optional": true
588
588
  },
589
589
  "node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
590
- "version": "0.9.11-alpha.3",
591
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.11-alpha.3.tgz",
590
+ "version": "0.9.11-alpha.4",
591
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.11-alpha.4.tgz",
592
592
  "license": "MIT",
593
593
  "os": [
594
594
  "win32"
@@ -599,8 +599,8 @@
599
599
  "optional": true
600
600
  },
601
601
  "node_modules/@bastani/atomic-natives-win32-x64-msvc": {
602
- "version": "0.9.11-alpha.3",
603
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.11-alpha.3.tgz",
602
+ "version": "0.9.11-alpha.4",
603
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.11-alpha.4.tgz",
604
604
  "license": "MIT",
605
605
  "os": [
606
606
  "win32"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.11-alpha.3",
3
+ "version": "0.9.11-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.11-alpha.3",
80
+ "@bastani/atomic-natives": "0.9.11-alpha.4",
81
81
  "@bufbuild/protobuf": "^2.12.1",
82
82
  "@dbos-inc/dbos-sdk": "4.23.6",
83
83
  "@earendil-works/pi-agent-core": "^0.81.1",