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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.18-alpha.7] - 2026-09-05
6
+
5
7
  ### Added
6
8
 
7
9
  - Fullscreen mouse-wheel scrolling moves five times as far while Alt is held, through the Pi TUI 0.85.1 update ([upstream #9166](https://github.com/earendil-works/pi/pull/9166)).
@@ -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.18-alpha.7] - 2026-09-05
8
+
9
+ ### Fixed
10
+
11
+ - Host sessions that join multiple workflow groups retain workflow broadcast and pending-stage routing after reconnecting. Registration now preserves the startup home group instead of treating the most recently joined group as the session's origin; workflow workers still cannot gain another invocation's control authority through joins or reconnects.
12
+
7
13
  ## [0.9.18-alpha.6] - 2026-09-04
8
14
 
9
15
  ### Breaking Changes
@@ -184,6 +184,11 @@ intercom({
184
184
 
185
185
  To coordinate two plain chat sessions without changing startup config, have each call `intercom({ action: "join", group: "NAME" })`. Joining adds a membership without changing the session ID or removing existing memberships. Calls to `list`, `send`, and `ask` can then reach any session sharing at least one membership. Use `intercom({ action: "groups" })` to discover every available name, connected-session count, and membership marker. Call `intercom({ action: "leave", group: "NAME" })` to remove one membership while keeping the others, or bare `leave` to reset to the original home group. `contact_supervisor` keeps its dedicated capability-based cross-group behavior.
186
186
 
187
+ Joined memberships survive broker reconnects without replacing the session's
188
+ startup identity. An ordinary host can therefore control several joined workflow
189
+ invocations, while a workflow worker cannot gain another invocation's parent-control
190
+ authority by joining its group and reconnecting.
191
+
187
192
  **Worker finds something unexpected — escalates and waits:**
188
193
  ```typescript
189
194
  intercom({
@@ -1183,6 +1183,10 @@ class IntercomBroker {
1183
1183
  if (!isSessionRegistration(clientMessage.session)) {
1184
1184
  throw new Error("Invalid register message");
1185
1185
  }
1186
+ if (clientMessage.registrationGroup !== undefined &&
1187
+ (typeof clientMessage.registrationGroup !== "string" || clientMessage.registrationGroup.trim().length === 0)) {
1188
+ throw new Error("Invalid registration group");
1189
+ }
1186
1190
  if (clientMessage.returnAddress !== undefined &&
1187
1191
  (typeof clientMessage.returnAddress !== "string" || clientMessage.returnAddress.length === 0)) {
1188
1192
  throw new Error("Invalid return address");
@@ -1222,7 +1226,8 @@ class IntercomBroker {
1222
1226
  this.sessions.set(id, {
1223
1227
  socket,
1224
1228
  info,
1225
- registrationGroup: legacyGroup,
1229
+ registrationGroup: typeof clientMessage.registrationGroup === "string"
1230
+ ? normalizeGroup(clientMessage.registrationGroup) : legacyGroup,
1226
1231
  ...(typeof info.name === "string" && info.name.trim().length > 0
1227
1232
  ? { registrationName: info.name.trim() }
1228
1233
  : {}),
@@ -231,6 +231,7 @@ export class IntercomClient extends EventEmitter {
231
231
  supervisor?: SupervisorRegistration,
232
232
  supervisorOwnerToken?: string,
233
233
  messageSource?: Message["source"],
234
+ registrationGroup?: string,
234
235
  ): Promise<void> {
235
236
  if (this.socket) {
236
237
  return Promise.reject(new Error("Already connected"));
@@ -360,6 +361,7 @@ export class IntercomClient extends EventEmitter {
360
361
  writeMessage(socket, {
361
362
  type: "register",
362
363
  session,
364
+ ...(registrationGroup !== undefined ? { registrationGroup } : {}),
363
365
  returnAddress: this.returnAddress,
364
366
  ...(supervisor ? { supervisor } : {}),
365
367
  ...(supervisorOwnerToken ? { supervisorOwnerToken } : {}),
@@ -534,7 +534,7 @@ var init_client = __esm(() => {
534
534
  }
535
535
  return socket;
536
536
  }
537
- connect(session, supervisor, supervisorOwnerToken, messageSource) {
537
+ connect(session, supervisor, supervisorOwnerToken, messageSource, registrationGroup) {
538
538
  if (this.socket) {
539
539
  return Promise.reject(new Error("Already connected"));
540
540
  }
@@ -636,6 +636,7 @@ var init_client = __esm(() => {
636
636
  writeMessage(socket, {
637
637
  type: "register",
638
638
  session,
639
+ ...registrationGroup !== undefined ? { registrationGroup } : {},
639
640
  returnAddress: this.returnAddress,
640
641
  ...supervisor ? { supervisor } : {},
641
642
  ...supervisorOwnerToken ? { supervisorOwnerToken } : {}
@@ -6678,8 +6679,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
6678
6679
  await testOverrides.beforeConnectAttempt?.(reason);
6679
6680
  await spawnBrokerIfNeeded(config.brokerCommand, config.brokerArgs);
6680
6681
  const childMetadata = currentChildOrchestratorMetadata();
6681
- await nextClient.connect(registration, childMetadata?.supervisor, supervisorAuthorizations.ownerToken, readSubagentMessageSource(runtimeContext?.subagentPolicy));
6682
- clientRegistrationGroup = normalizeGroup(registration.group);
6682
+ await nextClient.connect(registration, childMetadata?.supervisor, supervisorAuthorizations.ownerToken, readSubagentMessageSource(runtimeContext?.subagentPolicy), resolveSessionHomeGroup());
6683
+ clientRegistrationGroup = resolveSessionHomeGroup();
6683
6684
  await supervisorAuthorizations.restore(nextClient);
6684
6685
  for (const [runId, route] of pendingStageRoutes) {
6685
6686
  await registerPendingStageRoute(nextClient, runId, route);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/intercom",
3
- "version": "0.9.18-alpha.6",
3
+ "version": "0.9.18-alpha.7",
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": [
@@ -100,6 +100,8 @@ export type ClientMessage =
100
100
  session: Omit<SessionInfo, "id">;
101
101
  /** Internal host-owned identity retained across broker reconnects. */
102
102
  returnAddress?: string;
103
+ /** Immutable session origin; separate from mutable group memberships. Legacy clients use session.group. */
104
+ registrationGroup?: string;
103
105
  supervisor?: SupervisorRegistration;
104
106
  supervisorOwnerToken?: string;
105
107
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.18-alpha.6",
3
+ "version": "0.9.18-alpha.7",
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": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.9.18-alpha.6",
3
+ "version": "0.9.18-alpha.7",
4
4
  "private": true,
5
5
  "description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
6
6
  "contributors": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/web-access",
3
- "version": "0.9.18-alpha.6",
3
+ "version": "0.9.18-alpha.7",
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,8 @@ 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.18-alpha.7] - 2026-09-05
10
+
9
11
  ### Fixed
10
12
 
11
13
  - Pending-stage Intercom settlement now skips unrelated runs with no messages to settle. Genuine sweep failures produce one display-only warning per distinct message in interactive sessions instead of repeated console stack traces; headless sessions retain console diagnostics, and pending messages remain available for recovery.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/workflows",
3
- "version": "0.9.18-alpha.6",
3
+ "version": "0.9.18-alpha.7",
4
4
  "private": true,
5
5
  "description": "Atomic extension for multi-stage workflow authoring and execution.",
6
6
  "contributors": [
@@ -96,6 +96,23 @@ npm run test:scripts # Run the repository script tests under node -
96
96
  npm run test --workspace=@bastani/atomic -- test/specific.test.ts
97
97
  ```
98
98
 
99
+ Root Vitest projects install a fresh in-memory durable backend before every test.
100
+ Durability initialization imports the backend and its process owner rather than
101
+ preloading the DBOS factory or the Atomic host. A test that needs host prototype
102
+ installers must import those real modules explicitly rather than depend on a
103
+ side effect of shared setup. Test-local backend overrides still use the factory's
104
+ injection seam, and the next test receives a fresh backend without resetting
105
+ unrelated initialization or warning state. Keep the global artifact/native setups,
106
+ default isolation, worker sizing and timeout budgets unchanged when measuring
107
+ test cost. See the [CI measurements](https://github.com/bastani-inc/atomic/blob/main/docs/ci.md#current-critical-path-measured-september-5-2026)
108
+ for local gains and the remaining hosted Linux/Windows validation.
109
+
110
+ CI runs the complete root unit and integration suites in independent Linux and
111
+ Windows jobs. Each builds its own native and package prerequisites; both required
112
+ result gates wait for every work job and reject failures, cancellations and skips.
113
+ This trades duplicated setup for earlier integration feedback without changing
114
+ test isolation, coverage or retries.
115
+
99
116
  ## Deterministic installs
100
117
 
101
118
  `@bastani/atomic` ships `packages/coding-agent/npm-shrinkwrap.json` so package-manager installs resolve the same dependency tree every time. Contributors working from a source checkout can validate that the checked-in shrinkwrap is up to date with:
package/docs/intercom.md CHANGED
@@ -169,6 +169,15 @@ intercom({ action: "join", group: "api-review" })
169
169
 
170
170
  Joining is additive: existing memberships remain active, and the broker updates presence without changing the session ID. Use `intercom({ action: "groups" })` to discover all available names and membership markers. `intercom({ action: "leave", group: "api-review" })` removes only that membership; `intercom({ action: "leave" })` resets to the home group resolved at startup. Rejected or unacknowledged changes leave client and inheritance state unchanged. Ordinary delivery requires a shared membership, while `contact_supervisor` retains its capability-based cross-group path.
171
171
 
172
+ An ordinary host session can join several workflow invocation groups and send to
173
+ each group's `workflow:<rootRunId>/**` target, including after a broker reconnect.
174
+ Reconnection preserves the session's startup identity separately from its joined
175
+ memberships; joining a workflow does not turn the host into a workflow worker.
176
+ Groups explicitly left stay absent after reconnect; the startup identity is not
177
+ automatically added back to the membership list.
178
+ Actual workflow workers retain their original invocation boundary across reconnects:
179
+ joining another group does not grant that invocation's parent-control authority.
180
+
172
181
  Sent and received messages are recorded in session history as `intercom_sent` / `intercom_received` entries.
173
182
 
174
183
  ### Targeting Sessions and Pending Workflow Stages
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.18-alpha.6",
3
+ "version": "0.9.18-alpha.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bastani/atomic",
9
- "version": "0.9.18-alpha.6",
9
+ "version": "0.9.18-alpha.7",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@bastani/atomic-natives": "0.9.18-alpha.6",
13
- "@bastani/pi-ai": "0.9.18-alpha.6",
12
+ "@bastani/atomic-natives": "0.9.18-alpha.7",
13
+ "@bastani/pi-ai": "0.9.18-alpha.7",
14
14
  "@dbos-inc/dbos-sdk": "4.25.14",
15
15
  "@earendil-works/pi-agent-core": "0.85.1",
16
16
  "@earendil-works/pi-client": "0.85.1",
@@ -517,18 +517,18 @@
517
517
  }
518
518
  },
519
519
  "node_modules/@bastani/atomic-natives": {
520
- "version": "0.9.18-alpha.6",
521
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.18-alpha.6.tgz",
520
+ "version": "0.9.18-alpha.7",
521
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.18-alpha.7.tgz",
522
522
  "license": "MIT",
523
523
  "optionalDependencies": {
524
- "@bastani/atomic-natives-darwin-arm64": "0.9.18-alpha.6",
525
- "@bastani/atomic-natives-darwin-x64": "0.9.18-alpha.6",
526
- "@bastani/atomic-natives-linux-arm64-gnu": "0.9.18-alpha.6",
527
- "@bastani/atomic-natives-linux-arm64-musl": "0.9.18-alpha.6",
528
- "@bastani/atomic-natives-linux-x64-gnu": "0.9.18-alpha.6",
529
- "@bastani/atomic-natives-linux-x64-musl": "0.9.18-alpha.6",
530
- "@bastani/atomic-natives-win32-arm64-msvc": "0.9.18-alpha.6",
531
- "@bastani/atomic-natives-win32-x64-msvc": "0.9.18-alpha.6"
524
+ "@bastani/atomic-natives-darwin-arm64": "0.9.18-alpha.7",
525
+ "@bastani/atomic-natives-darwin-x64": "0.9.18-alpha.7",
526
+ "@bastani/atomic-natives-linux-arm64-gnu": "0.9.18-alpha.7",
527
+ "@bastani/atomic-natives-linux-arm64-musl": "0.9.18-alpha.7",
528
+ "@bastani/atomic-natives-linux-x64-gnu": "0.9.18-alpha.7",
529
+ "@bastani/atomic-natives-linux-x64-musl": "0.9.18-alpha.7",
530
+ "@bastani/atomic-natives-win32-arm64-msvc": "0.9.18-alpha.7",
531
+ "@bastani/atomic-natives-win32-x64-msvc": "0.9.18-alpha.7"
532
532
  },
533
533
  "engines": {
534
534
  "bun": ">=1.4.0",
@@ -536,8 +536,8 @@
536
536
  }
537
537
  },
538
538
  "node_modules/@bastani/atomic-natives-darwin-arm64": {
539
- "version": "0.9.18-alpha.6",
540
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.18-alpha.6.tgz",
539
+ "version": "0.9.18-alpha.7",
540
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.18-alpha.7.tgz",
541
541
  "license": "MIT",
542
542
  "os": [
543
543
  "darwin"
@@ -548,8 +548,8 @@
548
548
  "optional": true
549
549
  },
550
550
  "node_modules/@bastani/atomic-natives-darwin-x64": {
551
- "version": "0.9.18-alpha.6",
552
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.18-alpha.6.tgz",
551
+ "version": "0.9.18-alpha.7",
552
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.18-alpha.7.tgz",
553
553
  "license": "MIT",
554
554
  "os": [
555
555
  "darwin"
@@ -560,8 +560,8 @@
560
560
  "optional": true
561
561
  },
562
562
  "node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
563
- "version": "0.9.18-alpha.6",
564
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.18-alpha.6.tgz",
563
+ "version": "0.9.18-alpha.7",
564
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.18-alpha.7.tgz",
565
565
  "license": "MIT",
566
566
  "os": [
567
567
  "linux"
@@ -575,8 +575,8 @@
575
575
  "optional": true
576
576
  },
577
577
  "node_modules/@bastani/atomic-natives-linux-arm64-musl": {
578
- "version": "0.9.18-alpha.6",
579
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.18-alpha.6.tgz",
578
+ "version": "0.9.18-alpha.7",
579
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.18-alpha.7.tgz",
580
580
  "license": "MIT",
581
581
  "os": [
582
582
  "linux"
@@ -590,8 +590,8 @@
590
590
  "optional": true
591
591
  },
592
592
  "node_modules/@bastani/atomic-natives-linux-x64-gnu": {
593
- "version": "0.9.18-alpha.6",
594
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.18-alpha.6.tgz",
593
+ "version": "0.9.18-alpha.7",
594
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.18-alpha.7.tgz",
595
595
  "license": "MIT",
596
596
  "os": [
597
597
  "linux"
@@ -605,8 +605,8 @@
605
605
  "optional": true
606
606
  },
607
607
  "node_modules/@bastani/atomic-natives-linux-x64-musl": {
608
- "version": "0.9.18-alpha.6",
609
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.18-alpha.6.tgz",
608
+ "version": "0.9.18-alpha.7",
609
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.18-alpha.7.tgz",
610
610
  "license": "MIT",
611
611
  "os": [
612
612
  "linux"
@@ -620,8 +620,8 @@
620
620
  "optional": true
621
621
  },
622
622
  "node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
623
- "version": "0.9.18-alpha.6",
624
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.18-alpha.6.tgz",
623
+ "version": "0.9.18-alpha.7",
624
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.18-alpha.7.tgz",
625
625
  "license": "MIT",
626
626
  "os": [
627
627
  "win32"
@@ -632,8 +632,8 @@
632
632
  "optional": true
633
633
  },
634
634
  "node_modules/@bastani/atomic-natives-win32-x64-msvc": {
635
- "version": "0.9.18-alpha.6",
636
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.18-alpha.6.tgz",
635
+ "version": "0.9.18-alpha.7",
636
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.18-alpha.7.tgz",
637
637
  "license": "MIT",
638
638
  "os": [
639
639
  "win32"
@@ -644,8 +644,8 @@
644
644
  "optional": true
645
645
  },
646
646
  "node_modules/@bastani/pi-ai": {
647
- "version": "0.9.18-alpha.6",
648
- "resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.18-alpha.6.tgz",
647
+ "version": "0.9.18-alpha.7",
648
+ "resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.18-alpha.7.tgz",
649
649
  "license": "MIT",
650
650
  "dependencies": {
651
651
  "@anthropic-ai/sdk": "0.91.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.18-alpha.6",
3
+ "version": "0.9.18-alpha.7",
4
4
  "description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "atomicConfig": {
@@ -79,8 +79,8 @@
79
79
  "prepublishOnly": "bun run clean && bun run build && bun run shrinkwrap"
80
80
  },
81
81
  "dependencies": {
82
- "@bastani/atomic-natives": "0.9.18-alpha.6",
83
- "@bastani/pi-ai": "0.9.18-alpha.6",
82
+ "@bastani/atomic-natives": "0.9.18-alpha.7",
83
+ "@bastani/pi-ai": "0.9.18-alpha.7",
84
84
  "@dbos-inc/dbos-sdk": "4.25.14",
85
85
  "@earendil-works/pi-agent-core": "0.85.1",
86
86
  "@earendil-works/pi-client": "0.85.1",