@bastani/atomic 0.9.5 → 0.9.6-alpha.1

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 (33) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/builtin/cursor/CHANGELOG.md +6 -0
  3. package/dist/builtin/cursor/package.json +2 -2
  4. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  5. package/dist/builtin/intercom/README.md +3 -3
  6. package/dist/builtin/intercom/index-heavy.ts +0 -17
  7. package/dist/builtin/intercom/index.ts +7 -68
  8. package/dist/builtin/intercom/lazy-heavy-proxy.ts +0 -6
  9. package/dist/builtin/intercom/lifecycle.ts +1 -16
  10. package/dist/builtin/intercom/package.json +1 -1
  11. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  12. package/dist/builtin/mcp/package.json +1 -1
  13. package/dist/builtin/subagents/CHANGELOG.md +7 -0
  14. package/dist/builtin/subagents/README.md +1 -1
  15. package/dist/builtin/subagents/package.json +1 -1
  16. package/dist/builtin/subagents/skills/subagent/SKILL.md +1 -1
  17. package/dist/builtin/subagents/src/extension/prompt-guidance.ts +6 -7
  18. package/dist/builtin/web-access/CHANGELOG.md +6 -0
  19. package/dist/builtin/web-access/package.json +1 -1
  20. package/dist/builtin/workflows/CHANGELOG.md +8 -0
  21. package/dist/builtin/workflows/README.md +3 -3
  22. package/dist/builtin/workflows/builtin/ralph-core.ts +3 -3
  23. package/dist/builtin/workflows/builtin/ralph-runner.ts +20 -20
  24. package/dist/builtin/workflows/package.json +1 -1
  25. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +13 -7
  26. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  27. package/dist/core/atomic-guide-command.js +8 -8
  28. package/dist/core/atomic-guide-command.js.map +1 -1
  29. package/docs/quickstart.md +2 -4
  30. package/docs/subagents.md +1 -1
  31. package/docs/workflows.md +12 -12
  32. package/npm-shrinkwrap.json +23 -23
  33. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.6-alpha.1] - 2026-07-12
6
+
7
+ ### Changed
8
+
9
+ - Restored workflow-first Atomic guidance for non-trivial work with verifiable objectives and synchronized help/docs around rich inline TypeScript workflow authoring, including dynamic branching, fan-out, verification, candidate-selection, human-gate, child-workflow, and bounded-loop patterns.
10
+ - Documented compositional workflow authoring in model prompts and onboarding/help surfaces, including importing bundled workflows from `@bastani/workflows/builtin`, nesting definitions with `ctx.workflow(...)`, and building deeper reusable workflow graphs within `maxDepth`.
11
+ - Restored tool-driven bundled Intercom startup so foreground subagent launches and bridged child session startup no longer connect either session automatically; the model or user must invoke Intercom when coordination is needed.
12
+
5
13
  ## [0.9.5] - 2026-07-11
6
14
 
7
15
  ### Breaking Changes
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.6-alpha.1] - 2026-07-12
6
+
7
+ ### Changed
8
+
9
+ - Published a synchronized Atomic 0.9.6-alpha.1 prerelease for the Cursor provider package; no functional Cursor provider changes were made after 0.9.5.
10
+
5
11
  ## [0.9.5] - 2026-07-11
6
12
 
7
13
  ### Changed
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/cursor",
3
- "version": "0.9.5",
3
+ "version": "0.9.6-alpha.1",
4
4
  "private": true,
5
5
  "description": "Experimental first-party Atomic extension for Cursor OAuth, model discovery, and streaming provider registration.",
6
6
  "contributors": [
@@ -40,7 +40,7 @@
40
40
  }
41
41
  },
42
42
  "dependencies": {
43
- "@bastani/atomic-natives": "0.9.5",
43
+ "@bastani/atomic-natives": "0.9.6-alpha.1",
44
44
  "@bufbuild/protobuf": "^2.12.1",
45
45
  "@earendil-works/pi-ai": "^0.80.6"
46
46
  }
@@ -4,6 +4,12 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.6-alpha.1] - 2026-07-12
8
+
9
+ ### Changed
10
+
11
+ - Restored fully tool-driven Intercom connections: parent and bridged child sessions no longer import or connect to the broker merely because a subagent starts. The runtime now connects only when the model or user invokes an Intercom tool, command, shortcut, or relay.
12
+
7
13
  ## [0.9.5] - 2026-07-11
8
14
 
9
15
  ### Added
@@ -24,7 +24,7 @@ Intercom also integrates with delegated subagents: child agents get a child-only
24
24
 
25
25
  ## In One Minute
26
26
 
27
- Interactive parents lazily connect to the tiny local broker when an Intercom tool is used or immediately before a foreground child launches; the launch waits for inbound handlers and broker readiness so child coordination is available from its first turn. Delegated foreground and background children with supervisor bridge metadata register before agent work begins. The lightweight extension avoids importing the heavy runtime for unused parent sessions, disabled sessions, and noninteractive management-only work, and concurrent tool callers share one import and connection attempt. Definition/control-only subagent actions (`list`, `get`, `create`, `update`, `delete`, `status`, `interrupt`, and `doctor`) do not warm Intercom; `resume` may relaunch or contact a child and therefore retains readiness gating. If optional Intercom import, broker startup, or connection fails, the parent or child session continues with a diagnostic and later calls may retry. Lazy broker state is leased to the active session generation and cleaned up on shutdown or replacement.
27
+ Intercom connections are tool-driven. Parent and delegated child sessions keep the lightweight wrapper unloaded until the model or user invokes an Intercom tool, `/intercom`, or the `ALT+M` overlay. A bridged child receives its deterministic Intercom identity and `contact_supervisor` tool at startup, but invoking that tool establishes its broker connection; merely launching a foreground or background child does not connect either session. Concurrent first-use callers share one import and connection attempt, and lazy broker state is leased to the active session generation and cleaned up on shutdown or replacement.
28
28
 
29
29
  ## Install
30
30
 
@@ -34,7 +34,7 @@ Atomic bundles `@bastani/intercom` as a first-party extension; no separate insta
34
34
  pi install npm:pi-intercom
35
35
  ```
36
36
 
37
- Then restart Atomic or Pi. The extension registers the bundled `intercom` skill at startup. Interactive parents connect lazily on Intercom use or foreground-child launch, while bridged children connect before agent work begins; disabled sessions and noninteractive management-only operations do not load the heavy runtime or start the broker.
37
+ Then restart Atomic or Pi. The extension registers the bundled `intercom` skill and lightweight tools at startup, but it does not connect the session until the model or user invokes Intercom.
38
38
 
39
39
  **Recommended:** Add this snippet to your project's `AGENTS.md` to help agents understand when to coordinate across sessions:
40
40
 
@@ -53,7 +53,7 @@ Coordinate with other local Atomic/pi sessions on related codebases. Use `/skill
53
53
  A session becomes intercom-connected when all of these are true:
54
54
  - the intercom extension is installed/bundled and loaded in that session
55
55
  - `enabled` is not set to `false` in `~/.atomic/agent/intercom/config.json` (Atomic) or the legacy `~/.pi/agent/intercom/config.json` fallback
56
- - the session has started or reloaded after the extension was installed
56
+ - the model or user has invoked an Intercom tool, `/intercom`, or the `ALT+M` overlay in that session
57
57
  - the local broker is running or can be auto-started
58
58
 
59
59
  The session list only shows intercom-connected sessions, not every open Pi process on the machine.
@@ -37,7 +37,6 @@ export default function piIntercomExtension(pi: ExtensionAPI) {
37
37
  let reconnectTimer: NodeJS.Timeout | null = null;
38
38
  let reconnectPromise: Promise<IntercomClient> | null = null;
39
39
  let reconnectPromiseGeneration: number | null = null;
40
- let startupConnectTimer: NodeJS.Timeout | null = null;
41
40
  let reconnectAttempt = 0;
42
41
  let shuttingDown = false;
43
42
  let disposed = true;
@@ -99,10 +98,6 @@ export default function piIntercomExtension(pi: ExtensionAPI) {
99
98
  if (reconnectTimer) clearTimeout(reconnectTimer);
100
99
  reconnectTimer = null;
101
100
  }
102
- function clearStartupConnectTimer(): void {
103
- if (startupConnectTimer) clearTimeout(startupConnectTimer);
104
- startupConnectTimer = null;
105
- }
106
101
  function clearInboundFlushTimer(): void {
107
102
  if (inboundFlushTimer) clearTimeout(inboundFlushTimer);
108
103
  inboundFlushTimer = null;
@@ -425,17 +420,13 @@ export default function piIntercomExtension(pi: ExtensionAPI) {
425
420
  incrementRuntimeGeneration: () => { runtimeGeneration += 1; foregroundDetachHandoff.reset(); return runtimeGeneration; },
426
421
  resetReconnectAttempt: () => { reconnectAttempt = 0; },
427
422
  clearReconnectTimer,
428
- clearStartupConnectTimer,
429
423
  setRuntimeContext: (value) => { runtimeContext = value; },
430
424
  setCurrentSessionId: (value) => { currentSessionId = value; },
431
425
  setCurrentModel: (value) => { currentModel = value; },
432
426
  setSessionStartedAt: (value) => { sessionStartedAt = value; },
433
427
  setAgentRunning: (value) => { agentRunning = value; },
434
428
  activeTools,
435
- setStartupConnectTimer: (value) => { startupConnectTimer = value; },
436
429
  getLiveContext,
437
- ensureConnected,
438
- scheduleReconnect,
439
430
  rejectReplyWaiter,
440
431
  replyTracker,
441
432
  pendingIdleMessages,
@@ -480,12 +471,4 @@ export default function piIntercomExtension(pi: ExtensionAPI) {
480
471
  ensureConnected,
481
472
  syncPresenceIdentity,
482
473
  });
483
- return { enabled: config.enabled,
484
- async awaitAutomaticBrokerReady(): Promise<void> {
485
- if (config.enabled) await ensureConnected("startup");
486
- },
487
- async awaitForegroundBrokerReady(): Promise<void> {
488
- if (config.enabled) await ensureConnected("tool");
489
- },
490
- };
491
474
  }
@@ -1,8 +1,7 @@
1
- import { APP_NAME, getEnvValue, type ExtensionAPI, type ExtensionContext, type SessionStartEvent, type ToolDefinition, type ToolExecutionStartEvent } from "@bastani/atomic";
1
+ import { APP_NAME, getEnvValue, type ExtensionAPI, type ExtensionContext, type SessionStartEvent, type ToolDefinition } from "@bastani/atomic";
2
2
  import { Text } from "@earendil-works/pi-tui";
3
3
  import { Type } from "typebox";
4
4
  import { renderIntercomToolResult } from "./result-renderers.js";
5
- import { loadConfig } from "./config.js";
6
5
  import { executeHeavyTool, runHeavyCommand, type HeavyHandle } from "./lazy-tool-execution.js";
7
6
  import { assertCurrentLifecycleLease, createLifecycleLease, retainSettledLifecycleCleanup, retireLifecycleLease, SerializedLifecycleForwarder, type LifecycleLease } from "./lifecycle-lease.js";
8
7
  import { rejectLazyResultRelay } from "./lazy-subagent-ack.js";
@@ -13,7 +12,6 @@ import {
13
12
  dispatchHandlers,
14
13
  type CapturedHeavy,
15
14
  type ForwardedEventMap,
16
- type HeavyRuntimeReadiness,
17
15
  type ToolRenderResultArgs,
18
16
  } from "./lazy-heavy-proxy.js";
19
17
 
@@ -34,22 +32,9 @@ type ActiveLifecycleState = {
34
32
  modelSelect: LifecycleSnapshot<"model_select"> | null;
35
33
  };
36
34
  interface LightweightIntercomOptions {
37
- importHeavy?: () => Promise<{ default: (pi: ExtensionAPI) => void | HeavyRuntimeReadiness | Promise<void | HeavyRuntimeReadiness> }>;
38
- isEnabled?: () => boolean;
35
+ importHeavy?: () => Promise<{ default: (pi: ExtensionAPI) => void | Promise<void> }>;
39
36
  }
40
37
 
41
- const MANAGEMENT_ONLY_SUBAGENT_ACTIONS = new Set(["list", "get", "create", "update", "delete", "status", "interrupt", "doctor"]);
42
-
43
- function isInteractiveForegroundSubagentStart(event: ToolExecutionStartEvent, ctx: ExtensionContext): boolean {
44
- if (!ctx.hasUI || event.toolName !== "subagent") return false;
45
- if (!event.args || typeof event.args !== "object" || Array.isArray(event.args)) return true;
46
- const args = event.args as { action?: unknown; async?: unknown };
47
- const action = typeof args.action === "string" ? args.action.trim() : "";
48
- if (action && MANAGEMENT_ONLY_SUBAGENT_ACTIONS.has(action)) return false;
49
- return args.async !== true;
50
- }
51
-
52
-
53
38
  const SUBAGENT_CONTROL_INTERCOM_EVENT = "subagent:control-intercom";
54
39
  const SUBAGENT_RESULT_INTERCOM_EVENT = "subagent:result-intercom";
55
40
 
@@ -74,8 +59,6 @@ function renderHeavyToolResult(loadedHeavy: CapturedHeavy | null, name: string,
74
59
  return renderIntercomToolResult(name, args);
75
60
  }
76
61
  export default function intercom(pi: ExtensionAPI, options: LightweightIntercomOptions = {}) {
77
- const enabled = options.isEnabled?.() ?? loadConfig().enabled;
78
- const delegatedSession = hasSubagentIntercomEnv();
79
62
  const delegatedSessionName = readSubagentEnv("INTERCOM_SESSION_NAME");
80
63
  let heavyAttempt: HeavyAttempt | null = null;
81
64
  let loadedHeavy: IntercomHeavyHandle | null = null;
@@ -187,8 +170,7 @@ export default function intercom(pi: ExtensionAPI, options: LightweightIntercomO
187
170
  try {
188
171
  const mod = await (options.importHeavy?.() ?? import("./index-heavy.js"));
189
172
  assertLease(lease);
190
- const runtimeReadiness = await mod.default(createHeavyProxy(pi, captured));
191
- if (runtimeReadiness) captured.runtimeReadiness = runtimeReadiness;
173
+ await mod.default(createHeavyProxy(pi, captured));
192
174
  assertLease(lease);
193
175
  if (!sessionSnapshot && ctx) {
194
176
  sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration, lease };
@@ -214,23 +196,6 @@ export default function intercom(pi: ExtensionAPI, options: LightweightIntercomO
214
196
  );
215
197
  return promise;
216
198
  }
217
- async function registerAutomatically(ctx: ExtensionContext, phase: string, foreground = false): Promise<boolean> {
218
- try {
219
- const handle = await loadHeavy(ctx);
220
- const readiness = handle.heavy.runtimeReadiness;
221
- if (!readiness) throw new Error("Intercom heavy runtime did not expose broker readiness");
222
- if (readiness.enabled) {
223
- if (foreground) await readiness.awaitForegroundBrokerReady();
224
- else await readiness.awaitAutomaticBrokerReady();
225
- }
226
- handle.assertCurrent();
227
- return readiness.enabled;
228
- } catch (error) {
229
- const message = error instanceof Error ? error.message : String(error);
230
- console.error(`Intercom ${phase} failed; session will continue and a later call may retry: ${message}`, error);
231
- return false;
232
- }
233
- }
234
199
  pi.on("session_start", async (event, ctx) => {
235
200
  if (delegatedSessionName && typeof pi.setSessionName === "function") pi.setSessionName(delegatedSessionName);
236
201
  if (activeLease.retired) activeLease = createLifecycleLease<ShutdownSnapshot>(nextLeaseId++, activeLease.cleanupBarrier);
@@ -244,12 +209,7 @@ export default function intercom(pi: ExtensionAPI, options: LightweightIntercomO
244
209
  }
245
210
  const generation = ++lifecycleGeneration;
246
211
  sessionSnapshot = { event, ctx, generation, lease };
247
- if (loadedHeavy) {
248
- await ensureSessionStartReplayed(loadedHeavy.heavy, lease);
249
- return;
250
- }
251
- if (!enabled || (!ctx.hasUI && !delegatedSession)) return;
252
- if (delegatedSession) await registerAutomatically(ctx, "bridged child automatic registration");
212
+ if (loadedHeavy) await ensureSessionStartReplayed(loadedHeavy.heavy, lease);
253
213
  });
254
214
  pi.on("session_shutdown", async (event, ctx) => {
255
215
  const lease = activeLease;
@@ -307,28 +267,7 @@ export default function intercom(pi: ExtensionAPI, options: LightweightIntercomO
307
267
  });
308
268
  pi.on("tool_execution_start", async (event, ctx) => {
309
269
  if (activeLease.retired) return;
310
- const lease = activeLease;
311
- const toolSnapshot: LifecycleSnapshot<"tool_execution_start"> = { event, ctx };
312
- activeLifecycle.activeTools.set(event.toolCallId, toolSnapshot);
313
- if (isInteractiveForegroundSubagentStart(event, ctx) && enabled) {
314
- const session = sessionSnapshot;
315
- const warmHeavy = loadedHeavy?.heavy ?? null;
316
- const warmReplayComplete = warmHeavy !== null
317
- && session?.lease === lease
318
- && replayedGeneration === session.generation;
319
- // Successful readiness gates launch; optional Intercom failures degrade
320
- // without preventing the subagent tool itself from executing.
321
- await registerAutomatically(ctx, "foreground parent warmup", true);
322
- if (warmReplayComplete
323
- && activeLease === lease
324
- && !lease.retired
325
- && sessionSnapshot === session
326
- && activeLifecycle.activeTools.get(event.toolCallId) === toolSnapshot
327
- && loadedHeavy?.heavy === warmHeavy) {
328
- await lifecycleForward.enqueue(() => dispatchHandlers(warmHeavy, "tool_execution_start", event, ctx));
329
- }
330
- return; // Cold initialization replay owns this active tool's delivery.
331
- }
270
+ activeLifecycle.activeTools.set(event.toolCallId, { event, ctx });
332
271
  const heavy = loadedHeavy?.heavy;
333
272
  if (heavy) await lifecycleForward.enqueue(() => dispatchHandlers(heavy, "tool_execution_start", event, ctx));
334
273
  });
@@ -367,8 +306,8 @@ export default function intercom(pi: ExtensionAPI, options: LightweightIntercomO
367
306
  });
368
307
  });
369
308
  }
370
- // Bridged children are registered synchronously by the primary session-start
371
- // handler, before their first agent turn can send or receive intercom messages.
309
+ // Heavy Intercom state stays unloaded until the model or user invokes an
310
+ // Intercom tool, command, shortcut, or relay that needs it.
372
311
  pi.registerTool({
373
312
  name: "intercom",
374
313
  label: "Intercom",
@@ -27,11 +27,6 @@ type LazyLifecycleEvent = keyof ForwardedEventMap;
27
27
  type ForwardedHandler<K extends LazyLifecycleEvent> = ExtensionHandler<ForwardedEventMap[K]>;
28
28
  type ForwardedHandlerMap = { [K in LazyLifecycleEvent]: ForwardedHandler<K>[] };
29
29
  type AnyForwardedHandler = { [K in LazyLifecycleEvent]: ForwardedHandler<K> }[LazyLifecycleEvent];
30
- export interface HeavyRuntimeReadiness {
31
- enabled: boolean;
32
- awaitAutomaticBrokerReady(): Promise<void>;
33
- awaitForegroundBrokerReady(): Promise<void>;
34
- }
35
30
 
36
31
  export type CapturedHeavy = {
37
32
  tools: Map<string, ToolDefinition>;
@@ -39,7 +34,6 @@ export type CapturedHeavy = {
39
34
  handlers: ForwardedHandlerMap;
40
35
  shortcuts: Map<string, CapturedShortcut>;
41
36
  eventHandlers: Map<string, EventHandler[]>;
42
- runtimeReadiness?: HeavyRuntimeReadiness;
43
37
  };
44
38
 
45
39
  export function createForwardedHandlerMap(): ForwardedHandlerMap {
@@ -14,17 +14,13 @@ interface LifecycleDeps {
14
14
  incrementRuntimeGeneration(): number;
15
15
  resetReconnectAttempt(): void;
16
16
  clearReconnectTimer(): void;
17
- clearStartupConnectTimer(): void;
18
17
  setRuntimeContext(ctx: ExtensionContext | null): void;
19
18
  setCurrentSessionId(id: string | null): void;
20
19
  setCurrentModel(model: string): void;
21
20
  setSessionStartedAt(value: number | null): void;
22
21
  setAgentRunning(value: boolean): void;
23
22
  activeTools: Map<string, string>;
24
- setStartupConnectTimer(timer: NodeJS.Timeout | null): void;
25
23
  getLiveContext(ctx?: ExtensionContext | null, generation?: number): ExtensionContext | null;
26
- ensureConnected(reason: "startup"): Promise<IntercomClient>;
27
- scheduleReconnect(): void;
28
24
  rejectReplyWaiter(error: Error): void;
29
25
  replyTracker: ReplyTracker;
30
26
  pendingIdleMessages: InboundMessageEntry[];
@@ -44,7 +40,6 @@ export function registerIntercomLifecycle(pi: ExtensionAPI, deps: LifecycleDeps)
44
40
  deps.setShuttingDown(true);
45
41
  deps.setDisposed(true);
46
42
  deps.incrementRuntimeGeneration();
47
- deps.clearStartupConnectTimer();
48
43
  deps.clearReconnectTimer();
49
44
  deps.rejectReplyWaiter(new Error(reason));
50
45
  deps.replyTracker.reset();
@@ -74,25 +69,15 @@ export function registerIntercomLifecycle(pi: ExtensionAPI, deps: LifecycleDeps)
74
69
  deps.setShuttingDown(false);
75
70
  deps.setDisposed(false);
76
71
  deps.setRuntimeStarted(true);
77
- const startupGeneration = deps.incrementRuntimeGeneration();
72
+ deps.incrementRuntimeGeneration();
78
73
  deps.resetReconnectAttempt();
79
74
  deps.clearReconnectTimer();
80
- deps.clearStartupConnectTimer();
81
75
  deps.setRuntimeContext(ctx);
82
76
  deps.setCurrentSessionId(ctx.sessionManager.getSessionId());
83
77
  deps.setCurrentModel(ctx.model?.id ?? "unknown");
84
78
  deps.setSessionStartedAt(Date.now());
85
79
  deps.setAgentRunning(false);
86
80
  deps.activeTools.clear();
87
- deps.setStartupConnectTimer(setTimeout(() => {
88
- deps.setStartupConnectTimer(null);
89
- if (!deps.getLiveContext(ctx, startupGeneration)) return;
90
- void deps.ensureConnected("startup").catch(() => {
91
- if (!deps.getLiveContext(ctx, startupGeneration)) return;
92
- deps.setClient(null);
93
- deps.scheduleReconnect();
94
- });
95
- }, 0));
96
81
  });
97
82
 
98
83
  pi.on("session_shutdown", async () => {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/intercom",
3
- "version": "0.9.5",
3
+ "version": "0.9.6-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
6
6
  "contributors": [
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.9.6-alpha.1] - 2026-07-12
11
+
12
+ ### Changed
13
+
14
+ - Published a synchronized Atomic 0.9.6-alpha.1 prerelease for the MCP extension; no functional MCP changes were made after 0.9.5.
15
+
10
16
  ## [0.9.5] - 2026-07-11
11
17
 
12
18
  ### Changed
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.5",
3
+ "version": "0.9.6-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension that adapts MCP (Model Context Protocol) servers into the coding agent. Fork of: https://github.com/nicobailon/pi-mcp-adapter",
6
6
  "contributors": [
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.6-alpha.1] - 2026-07-12
6
+
7
+ ### Changed
8
+
9
+ - Aligned model-facing subagent guidance with workflow-first routing: subagents remain focused specialists inside workflow stages or bounded direct delegation, rather than becoming an ad hoc implementation/review/retry pipeline for workflow-fit work.
10
+ - Changed bundled Intercom coordination back to model-driven connection: launching foreground or background children no longer connects the parent or child session automatically; an Intercom tool or UI action must establish each session's broker connection.
11
+
5
12
  ## [0.9.5] - 2026-07-11
6
13
 
7
14
  ### Added
@@ -230,7 +230,7 @@ The child can use one dedicated coordination tool:
230
230
  - `contact_supervisor`: the child contacts the parent/supervisor session that delegated the task. Use `reason: "need_decision"` for blocking decisions or clarification, and `reason: "progress_update"` for short non-blocking updates when a discovery changes the plan. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing or artifact-writing instructions; no-edit wins.
231
231
 
232
232
  Child-side routine completion handoffs are still not expected. With the intercom bridge active, parent-side `pi-subagents` sends grouped completion results through `pi-intercom`: one grouped message per foreground parent `subagent` run and one per completed async result file. Intercom-confirmed foreground delivery returns a compact receipt with artifact/session paths; without that confirmation, the normal full output is preserved. Grouped messages include child intercom targets and full child summaries. The separate in-process completion event keeps its legacy synchronous semantics: emission is accepted unless a listener explicitly rejects it during the call, and no listener is not treated as an error.
233
- When the companion is enabled and available, both foreground and background child sessions register with Intercom during session startup, before agent work can send or receive coordination messages. The interactive parent connects lazily, and a foreground launch waits for its broker/inbound-handler readiness before starting the child. Management-only `list`, `get`, `create`, `update`, `delete`, `status`, `interrupt`, and `doctor` actions do not launch a child and therefore do not force Intercom loading or broker startup; `resume` can relaunch or contact a child and retains readiness gating. If the optional companion cannot import, start its broker, or connect, subagent launch continues with diagnostics and a later call can retry.
233
+ When the companion is enabled and available, the bridge gives eligible children deterministic Intercom identities and coordination tools without connecting them automatically. Parent and child connections remain tool-driven: if a child may need live coordination, the parent model should invoke `intercom({ action: "status" })` before launch, and the child connects when it invokes `contact_supervisor` or `intercom`. Foreground/background launch and management-only actions do not force Intercom loading or broker startup.
234
234
 
235
235
  For foreground runs, Intercom uses a targeted probe/reservation before delivery: only the exact live child can claim its message. Atomic then commits detach for that child and waits for its acknowledgement before placing claimed asks, sends, decisions, interviews, and progress updates in the parent's model-visible steering queue, so cancellation between phases cannot surface an orphaned request. Blocking calls remain alive for an exact threaded reply and then resume; fire-and-forget calls create no waiter. The retained child later replaces its detached status and artifacts with the real result. Cancellation/replacement invalidates stale handshakes, duplicate delivery cannot recommit, and background or unmatched messages retain queued-until-idle behavior.
236
236
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.9.5",
3
+ "version": "0.9.6-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension for delegating tasks to subagents with chains, parallel execution, and background runs. Fork of: https://github.com/nicobailon/pi-subagents",
6
6
  "contributors": [
@@ -423,7 +423,7 @@ subagent({
423
423
 
424
424
  ## Subagent + Intercom Coordination
425
425
 
426
- Atomic subagents work without intercom. When Atomic's bundled intercom companion or upstream `pi-intercom` is installed and enabled, the intercom bridge can automatically give child agents a private coordination channel back to the parent session.
426
+ Atomic subagents work without intercom. When Atomic's bundled intercom companion or upstream `pi-intercom` is installed and enabled, the bridge can give eligible child agents a private coordination tool back to the parent session without connecting either session automatically. If a child may need live coordination, invoke `intercom({ action: "status" })` in the parent before launching it; the child connects when it first invokes `contact_supervisor` or `intercom`.
427
427
 
428
428
  The builtin specialists in this skill do not declare the `intercom` tool, so they finish their pass and return without coordinating. They cannot pause to ask the parent for a decision mid-run; if you need that, write a custom agent that lists `intercom` (or that the runtime bridge can inject `contact_supervisor` into).
429
429
 
@@ -1,10 +1,9 @@
1
1
  export const DEFAULT_PROMPT_GUIDANCE: string[] = [
2
- `**Subagent orchestration**: Use subagents selectively for bounded specialist delegation while the parent remains in control.
3
- - Keep interactive, exploratory, conceptual, and conversation-led work inline when direct discussion and user steering are more useful than delegation.
4
- - Use a single subagent for a focused specialty, a chain for a bounded sequential handoff, or parallel tasks for independent work. Multiple steps, files, tests, validation, or parallelism alone do not require a workflow.
5
- - Delegate noisy or context-heavy command investigation when isolation helps, but run concise commands inline when that is simpler. Do not split work with substantial overlap across independent subagents.
6
- - Use async/background execution selectively for genuinely long-running or independently useful delegated work. Foreground execution is appropriate when the parent needs the result before proceeding; do not duplicate a delegated job while waiting.
7
- - For clearly delegated, well-defined autonomous jobs that are likely long-running/background-oriented or materially need durable stages, checkpoints, resumability, human input, gates, retries, or bounded loops, prefer an appropriate workflow rather than stretching subagent orchestration into an ad hoc workflow.
8
- - Debug conceptual questions or exploratory analysis inline when appropriate. Use the debugger subagent for actual failures that need reproduction, root-cause diagnosis, and a validated fix; additional debugger or research delegates are optional when they add a distinct useful angle.`,
2
+ `**Subagent orchestration**: Use subagents for focused specialist work inside workflows or as bounded delegation when a workflow would be unnecessary overhead.
3
+ - Because workflows are the default for non-trivial structured work with verifiable objectives, do not stretch parent-controlled subagent calls into an ad hoc implementation, review, or retry pipeline; use a workflow and let its stages delegate specialists.
4
+ - Use a single subagent for a focused specialty, a chain for a bounded sequential handoff, or parallel tasks for independent work. Keep substantial-overlap tasks together rather than duplicating investigation across agents.
5
+ - Delegate noisy or context-heavy command investigation when isolation helps, but run concise commands inline when that is simpler.
6
+ - Use async/background execution when delegated work is genuinely long-running or independently useful. Foreground execution is appropriate when the parent needs the result before proceeding; do not duplicate a delegated job while waiting.
7
+ - Use the debugger subagent for actual failures that need reproduction, root-cause diagnosis, and a validated fix; additional debugger or research delegates are optional when they add a distinct useful angle.`,
9
8
  ];
10
9
 
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.6-alpha.1] - 2026-07-12
8
+
9
+ ### Changed
10
+
11
+ - Published a synchronized Atomic 0.9.6-alpha.1 prerelease for the web-access extension; no functional web-access changes were made after 0.9.5.
12
+
7
13
  ## [0.9.5] - 2026-07-11
8
14
 
9
15
  ### Changed
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/web-access",
3
- "version": "0.9.5",
3
+ "version": "0.9.6-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
6
6
  "contributors": [
@@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.9.6-alpha.1] - 2026-07-12
10
+
11
+ ### Changed
12
+
13
+ - Restored workflow-first model routing for non-trivial, structured, and verifiable work while retaining the newer ability to author task-specific TypeScript workflows inline. Prompt guidance now explicitly combines the documented classify/branch, fan-out/synthesis, adversarial verification, generate/filter, tournament, and bounded loop patterns instead of forcing every workflow-fit task into an installed workflow, direct shape, or builtin.
14
+ - Restored Ralph's builtin implementation-stage prompts to require subagent-led investigation, editing, and validation, reversing the selective direct-implementation wording introduced with intent-first routing.
15
+ - Expanded model-facing workflow guidance to treat composition as a first-class design option: custom parents can import reusable project/package workflows or bundled builtin definitions, invoke them through `ctx.workflow(...)`, and nest further child workflows within `maxDepth` while preserving expanded graph visibility, HIL, durability, controls, and declared output contracts.
16
+
9
17
  ## [0.9.5] - 2026-07-11
10
18
 
11
19
  ### Breaking Changes
@@ -5,7 +5,7 @@
5
5
  An open-source Atomic workflow extension: install it, author workflows in TypeScript, run them from chat.
6
6
  </p>
7
7
 
8
- Use the least orchestration that fits the user's intent: keep interactive/exploratory work inline, use bounded single/chain/parallel subagents while the parent remains in control, and use workflows for clearly delegated, well-defined autonomous jobs that are likely long-running/background-oriented or materially need durable stages, artifacts/checkpoints, resumability, HIL, gates, retries, or bounded loops. Multiple steps, files, tests, validation, or parallelism alone do not require a workflow. Loop or stop-condition requests such as `do X until Y`, `repeat until`, `iterate until`, `review/fix until passing`, `run checks and fix until green`, or `keep going until done` are key workflow signals when the user delegates execution because they already define control flow and a completion condition. When workflow execution fits, Atomic may always author a custom TypeScript `workflow({...})` inline with normal coding tools if that shape best achieves the task; it is not limited to installed workflows or direct modes. Named workflows can be builtin, project, user, or package supplied, and direct task/tasks/chain modes cover one-off tracked shapes.
8
+ Default to workflows for non-trivial work and requests with inherent structure plus a verifiable objective; reserve direct chat for tiny deterministic low-risk work. Workflow-first is not builtin-only or monolithic: Atomic can author custom TypeScript `workflow({...})` definitions inline, import reusable project/package workflows or builtins from `@bastani/workflows/builtin`, and nest them with `ctx.workflow(...)`. Imported children may nest further workflows within `maxDepth`, so compose proven research, implementation, design, verification, and approval graphs rather than copying them. Custom parents can also use runtime classification, dynamic fan-out and synthesis, adversarial verification, candidate tournaments, HIL gates, and bounded convergence.
9
9
 
10
10
  <p align="center">
11
11
  <a href="#authoring-api">Authoring API</a>
@@ -552,12 +552,12 @@ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` repo
552
552
 
553
553
  ### `workflow` tool (LLM-callable)
554
554
 
555
- <!-- Keep the description below in sync with WORKFLOW_TOOL_DESCRIPTION in packages/workflows/src/extension/index.ts; integration tests assert this. -->
555
+ <!-- Keep the description below in sync with WORKFLOW_TOOL_DESCRIPTION in packages/workflows/src/extension/workflow-prompts.ts; integration tests assert this. -->
556
556
 
557
557
  ```json
558
558
  {
559
559
  "name": "workflow",
560
- "description": "Run named builtin, project, user, or package workflows, or direct one-off task/tasks/chain workflows; when workflow execution fits but another shape would better achieve the task, author a custom TypeScript workflow({...}) inline with normal coding tools, reload it, and run it; discover with list/get/inputs, inspect status/stages/stage details, send prompt answers or steering, pause/resume/interrupt/kill runs, and reload workflow resources. For large stage handoffs, write context to files/artifacts, pass paths via reads, and prompt downstream agents to 'Read the file at <path>...' instead of injecting large previous text. For transcripts, prefer status/stages/stage to get sessionFile/transcriptPath, quote the exact path without rewriting separators (Windows backslashes are valid), then search it with rg/grep and read small ranges; transcript is path-only by default when sessionFile/transcriptPath exists, explicit tail/limit returns bounded previews, and missing transcript paths fall back to a small preview.",
560
+ "description": "Run named builtin, project, user, or package workflows, or direct one-off task/tasks/chain workflows; custom definitions may import reusable project/package workflows or builtin definitions from @bastani/workflows/builtin and nest them with ctx.workflow(...), including deeper composition within the configured maxDepth; when workflow execution fits but another shape would better achieve the task, author a custom TypeScript workflow({...}) inline with normal coding tools, reload it, and run it; discover with list/get/inputs, inspect status/stages/stage details, send prompt answers or steering, pause/resume/interrupt/kill runs, and reload workflow resources. For large stage handoffs, write context to files/artifacts, pass paths via reads, and prompt downstream agents to 'Read the file at <path>...' instead of injecting large previous text. For transcripts, prefer status/stages/stage to get sessionFile/transcriptPath, quote the exact path without rewriting separators (Windows backslashes are valid), then search it with rg/grep and read small ranges; transcript is path-only by default when sessionFile/transcriptPath exists, explicit tail/limit returns bounded previews, and missing transcript paths fall back to a small preview.",
561
561
  "parameters": {
562
562
  "workflow": "string (optional) — workflow ID or normalized name",
563
563
  "inputs": "object (optional) — key/value map of workflow inputs",
@@ -434,10 +434,10 @@ export function renderForkedOrchestratorPrompt(args: {
434
434
  [
435
435
  "output_format",
436
436
  [
437
- "After the implementation work is complete, return Markdown with headings:",
437
+ "After subagents have done the work, return Markdown with headings:",
438
438
  "1. Research file — the path you read",
439
- "2. Delegations performed — subagents used and what each completed, or none when direct work was sufficient",
440
- "3. Changes made — concrete completed changes, not intentions",
439
+ "2. Delegations performed — subagents spawned and what each completed",
440
+ "3. Changes made — concrete changes from subagent work, not intentions",
441
441
  "4. Files touched",
442
442
  "5. Validation run / recommended",
443
443
  "6. Deferred work or blockers",