@bastani/atomic 0.9.61-alpha.1 → 0.9.61-alpha.3
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 +68 -4
- package/dist/builtin/intercom/index.bundle.mjs +3 -3
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +12 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +14 -0
- package/dist/builtin/workflows/README.md +9 -7
- package/dist/builtin/workflows/builtin/{chunk-h6bt0r0g.js → chunk-a2j0x1a6.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-g3b2zf8r.js → chunk-vzbec50q.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +1 -1
- package/dist/builtin/workflows/builtin/index.js +2 -2
- package/dist/builtin/workflows/builtin/ralph.js +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +828 -418
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +905 -429
- package/dist/builtin/workflows/src/index.js +798 -393
- package/dist/builtin/workflows/src/local-worker-entry.mjs +905 -429
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +12 -3
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/model-fallback-failures.d.ts +14 -4
- package/dist/core/model-fallback-failures.d.ts.map +1 -1
- package/dist/core/model-fallback-failures.js +43 -15
- package/dist/core/model-fallback-failures.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +1 -0
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +1 -0
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +2 -0
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-schema.d.ts +2 -0
- package/dist/core/settings-schema.d.ts.map +1 -1
- package/dist/core/settings-schema.js +4 -0
- package/dist/core/settings-schema.js.map +1 -1
- package/dist/core/slash-commands.js +2 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-startup-chat-container.d.ts +2 -0
- package/dist/modes/interactive/interactive-startup-chat-container.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup-chat-container.js +6 -0
- package/dist/modes/interactive/interactive-startup-chat-container.js.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.d.ts +8 -0
- package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.js +28 -6
- package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
- package/dist/modes/interactive-engine/remote-renderer.d.ts +33 -5
- package/dist/modes/interactive-engine/remote-renderer.d.ts.map +1 -1
- package/dist/modes/interactive-engine/remote-renderer.js +91 -17
- package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
- package/dist/modes/rpc/queued-writer.d.ts +2 -0
- package/dist/modes/rpc/queued-writer.d.ts.map +1 -1
- package/dist/modes/rpc/queued-writer.js +8 -0
- package/dist/modes/rpc/queued-writer.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +4 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/docs/intercom/reference.md +1 -1
- package/docs/models/evals.md +30 -2
- package/docs/settings.md +3 -0
- package/docs/subagents/reference.md +3 -1
- package/docs/workflows/api-reference.md +9 -6
- package/docs/workflows/builtins.md +1 -1
- package/docs/workflows/operations.md +4 -4
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
- package/schemas/settings.schema.json +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
## [0.9.61] - 2026-11-02
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Local worker pools that hold up under faults and load, a lighter terminal under heavy workflow load, and workflows that can work in any repository's worktree.
|
|
8
8
|
|
|
9
|
-
- **One failing child no longer takes down
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
9
|
+
- **One failing child no longer takes down a pool:** a child that fails to dispatch fails alone, a worker or tool process group that survives SIGKILL is a warning rather than a failure, and pool faults replay the child within its three attempts, and a replay blocked by those groups' quarantined permits fails after a bounded wait instead of waiting forever ([#4159](https://github.com/bastani-inc/atomic/pull/4159), [#4170](https://github.com/bastani-inc/atomic/pull/4170))
|
|
10
|
+
- **Local worker pools keep their leases:** a slow journal or root no longer gets every healthy worker killed at once, and a race in lease recovery no longer fails every child of a pool with `stale_work_lease` ([#4165](https://github.com/bastani-inc/atomic/pull/4165))
|
|
11
|
+
- **A lighter terminal under heavy load:** a workflow run no longer keeps every completed stage's session in memory until it ends, which cut peak heap from 2.8 GB to 0.87 GB in a 600-stage test and shortened GC pauses. Rebuilding the chat no longer flashes "Loading isolated renderer…", and rows keep the state you left them in ([#4166](https://github.com/bastani-inc/atomic/pull/4166), [#4167](https://github.com/bastani-inc/atomic/pull/4167), [#4169](https://github.com/bastani-inc/atomic/pull/4169))
|
|
12
|
+
- **Broadcasts reach pooled stages at once:** stages on local workers get queued and sticky Intercom messages before their first turn, without a 60 s stall or a warning per stage ([#4164](https://github.com/bastani-inc/atomic/pull/4164))
|
|
13
|
+
- **Content-filter refusals fall back:** a provider content-filter refusal, such as OpenAI's 422 `cyber_policy`, moves to the next `fallbackModels` entry instead of retrying the model that refused; turn it off with `retry.fallbackOnContentFilter` ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
14
|
+
- **Workflow worktrees from anywhere:** `git_worktree_dir` can name a worktree of any repository, and a non-empty folder gets its own checkout inside it ([#4162](https://github.com/bastani-inc/atomic/pull/4162))
|
|
15
|
+
- **Gemini 4 Argon in model routing:** automatic model routing now weighs Gemini 4 Argon's published benchmark results ([#4161](https://github.com/bastani-inc/atomic/pull/4161))
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `retry.fallbackOnContentFilter` setting (default `true`). Set it to `false` to keep a provider content-filter refusal on the model that gave it instead of moving to the next `fallbackModels` entry ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
20
|
+
- Recorded Gemini 4 Argon results in the evals snapshot used by automatic model routing: its Artificial Analysis row at high effort, Cognition FrontierCode 1.1 at medium effort, Zapier AutomationBench at high and medium effort, and Google's vendor-reported launch results, including DeepSWE v1.1, Terminal-Bench 4.0 and Terminal-Bench-Science ([#4161](https://github.com/bastani-inc/atomic/pull/4161)).
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- A workflow's `gitWorktreeDir` (the `git_worktree_dir` input of `goal` and `ralph`) that names a non-empty directory which is not a Git checkout is now used as a place to put worktrees: the run gets its own checkout at `<dir>/<4-hex>/<repository-name>`, created from `base_branch` of the invoking repository, and leaves the directory's existing content alone. Every stage, retry and resume of that run uses the same checkout, and other runs pointing at the same directory get their own. An existing empty directory becomes the worktree. Before, both failed with `gitWorktreeDir already exists but is not a Git worktree`. ([#4162](https://github.com/bastani-inc/atomic/pull/4162))
|
|
12
25
|
|
|
13
26
|
### Fixed
|
|
14
27
|
|
|
@@ -16,6 +29,57 @@ A local worker pool that keeps going when one child or one worker goes wrong.
|
|
|
16
29
|
- Cleanup that a local worker pool really cannot confirm is no longer any child's failure. This covers a tool process group that survives SIGKILL and a worker that outlives it. Instead it shows as a warning on the root run and is written to that worker's log, which is kept. The worker is replaced, and its unfinished child replays on another worker within its usual three attempts. Process permits of the surviving groups stay quarantined, and closing the pool still reports them. Worker logs of a pool that failed are kept as well. ([#4159](https://github.com/bastani-inc/atomic/pull/4159))
|
|
17
30
|
- A child on a local worker whose run fails on a fault of the pool, such as `stale_work_lease`, `worker_lost`, `storage_unavailable` or `intercom_unavailable`, is replayed from its last checkpoint within its three attempts instead of ending failed with a recoverable fault recorded as final. After the third attempt it fails with the retryable `worker_retry_limit`, naming the fault. ([#4159](https://github.com/bastani-inc/atomic/pull/4159))
|
|
18
31
|
- A replayed child on a local worker whose `ctx.tool` call fails again, as it did on an earlier attempt, no longer fails with `Pool checkpoint identity conflict`. ([#4159](https://github.com/bastani-inc/atomic/pull/4159))
|
|
32
|
+
- A workflow's `gitWorktreeDir` (the `git_worktree_dir` input of `goal` and `ralph`) can name an existing worktree of any repository, even when the session runs in another repository or outside any Git repository. Before, every launch failed before its first stage with `gitWorktreeDir already exists but does not belong to the invoking Git repository` or `gitWorktreeDir requires the workflow to be invoked from inside a Git repository`. Stages start at the worktree root unless the session is in the same repository. Creating a new worktree still requires starting inside the source repository, and the error now says to pass an existing worktree instead. ([#4162](https://github.com/bastani-inc/atomic/pull/4162))
|
|
33
|
+
- A provider content-filter refusal now moves a main chat, subagent or workflow stage to its next `fallbackModels` entry at once, without retrying the model that refused, and the refusing model is recorded in the fallback history. This covers OpenAI's HTTP 422 `cyber_policy` ("This content was flagged for possible cybersecurity risk"), Anthropic's refusal stop, `content_filter` finish reasons and safety- or policy-blocked requests. Before, Anthropic and `content_filter` refusals were retried on the same model and then failed the turn, subagent or stage, and a 422 `cyber_policy` refusal fell back only because it was not recognized as a refusal ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
34
|
+
- A local worker pool (`workflows.localWorkers`) whose journal or root answers more slowly than the work lease, as on a busy machine or while the root's process pauses, no longer stops every worker at the same moment and replays every child on a new one. A worker waiting for the pool's own answer is no longer taken for a silent one, so it keeps its child and its lease is renewed once the answer comes. ([#4165](https://github.com/bastani-inc/atomic/pull/4165))
|
|
35
|
+
- Lease recovery in a local worker pool no longer fails the whole pool, and with it every unfinished child at once with `stale_work_lease`, when an expired attempt changes hands while recovery acts on it, for example because its worker just exited and its child was released for replay. ([#4165](https://github.com/bastani-inc/atomic/pull/4165))
|
|
36
|
+
- A stage on a local worker (`workflows.localWorkers`) that starts after a sticky Intercom broadcast (`workflow:<rootRunId>/**`) or a name or pattern send to future stages gets those messages before its first turn, under "Messages received before you started" with the real sender, even when the root is too busy to answer. Before, each such stage on a busy root could wait 60 seconds and then print a long "starting without its queued Intercom messages" warning in the chat, listing messages it may already have received. The worker now delivers the stage's queued messages itself and never waits on the root. If the root later fails to record or deliver them, the run's status shows one `Intercom delivery:` line for the whole run, not a warning per stage ([#4164](https://github.com/bastani-inc/atomic/pull/4164)).
|
|
37
|
+
- A workflow run no longer keeps the live session of every stage it completed in memory until the whole run ends. A stage run with `ctx.task`, `ctx.chain` or `ctx.parallel` gives its session back as soon as it completes, and one run with `ctx.stage` once the workflow no longer holds its stage context; its saved transcript still opens from the graph, `/workflow attach` or the stage chat. A session hosting long runs with hundreds of completed stages held gigabytes this way, and the garbage collection that memory caused made the interactive TUI, `/tasks` and queued messages slow to respond. ([#4166](https://github.com/bastani-inc/atomic/pull/4166))
|
|
38
|
+
- In the interactive TUI, rows that the engine renders, such as tool results and extension messages, keep their last frame when the chat is rebuilt (after compaction, `/reload` or switching sessions), instead of showing `Loading isolated renderer…` until a busy engine renders each one again. A rebuilt chat also no longer leaves the renderers of the rows it replaced running in the engine for the rest of the session, and engine messages reach chat rows through one subscription instead of one per row. ([#4167](https://github.com/bastani-inc/atomic/pull/4167))
|
|
39
|
+
- A rebuilt chat in the interactive TUI no longer briefly shows a collapsed tool row with its expanded output when the row was collapsed while its expanded frame was still on its way from the engine. Rows the chat drops while the engine connection is backed up also stay released, instead of being rendered again in the engine by a render request that arrived after their disposal. ([#4169](https://github.com/bastani-inc/atomic/pull/4169))
|
|
40
|
+
- A child on a local worker pool (`workflows.localWorkers`) whose replay needs a tool process permit no longer waits forever when the only capacity left under `admission.limits.process` (or `admission.userLimits.process`) is held by quarantined permits of process groups that survived SIGKILL. Those permits stay quarantined, and capacity held by running work is still waited for as before. A process admission that only quarantined permits block now waits at most 15 seconds for those groups to exit, then fails with the retryable `worker_cleanup_unconfirmed`, naming the groups and the limit. That ends the child's attempt, so it replays within its three attempts and then fails with `worker_retry_limit`, letting the root finish. If the groups exit in time, the replay goes on normally. ([#4170](https://github.com/bastani-inc/atomic/pull/4170))
|
|
41
|
+
|
|
42
|
+
## [0.9.61-alpha.3] - 2026-11-02
|
|
43
|
+
|
|
44
|
+
Replays on a local worker that can no longer wait forever, and a steadier chat renderer.
|
|
45
|
+
|
|
46
|
+
- **Replays can't wait forever on cleanup:** when process groups that survived SIGKILL fill `admission.limits.process`, a child's replay now fails after a bounded wait with a retryable error naming those groups and the limit, instead of waiting indefinitely; the groups' permits stay quarantined ([#4170](https://github.com/bastani-inc/atomic/pull/4170))
|
|
47
|
+
- **Chat rows stay as you left them:** a row released under engine backpressure no longer comes back, and a row you collapse no longer shows its expanded output after the chat is rebuilt ([#4169](https://github.com/bastani-inc/atomic/pull/4169))
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- A rebuilt chat in the interactive TUI no longer briefly shows a collapsed tool row with its expanded output when the row was collapsed while its expanded frame was still on its way from the engine. Rows the chat drops while the engine connection is backed up also stay released, instead of being rendered again in the engine by a render request that arrived after their disposal. ([#4169](https://github.com/bastani-inc/atomic/pull/4169))
|
|
52
|
+
- A child on a local worker pool (`workflows.localWorkers`) whose replay needs a tool process permit no longer waits forever when the only capacity left under `admission.limits.process` (or `admission.userLimits.process`) is held by quarantined permits of process groups that survived SIGKILL. Those permits stay quarantined, and capacity held by running work is still waited for as before. A process admission that only quarantined permits block now waits at most 15 seconds for those groups to exit, then fails with the retryable `worker_cleanup_unconfirmed`, naming the groups and the limit. That ends the child's attempt, so it replays within its three attempts and then fails with `worker_retry_limit`, letting the root finish. If the groups exit in time, the replay goes on normally. ([#4170](https://github.com/bastani-inc/atomic/pull/4170))
|
|
53
|
+
|
|
54
|
+
## [0.9.61-alpha.2] - 2026-11-02
|
|
55
|
+
|
|
56
|
+
A lighter terminal under heavy workflow load, local worker pools that hold their leases, and workflows that can work in any repository's worktree.
|
|
57
|
+
|
|
58
|
+
- **A lighter terminal under heavy load:** a workflow run no longer keeps every completed stage's session in memory until it ends, which cut peak heap from 2.8 GB to 0.87 GB in a 600-stage test and shortened GC pauses. Rebuilding the chat no longer flashes "Loading isolated renderer…" ([#4166](https://github.com/bastani-inc/atomic/pull/4166), [#4167](https://github.com/bastani-inc/atomic/pull/4167))
|
|
59
|
+
- **Local worker pools keep their leases:** a slow journal or root no longer gets every healthy worker killed at once, and a race in lease recovery no longer fails every child of a pool with `stale_work_lease` ([#4165](https://github.com/bastani-inc/atomic/pull/4165))
|
|
60
|
+
- **Broadcasts reach pooled stages at once:** stages on local workers get queued and sticky Intercom messages before their first turn, without a 60 s stall or a warning per stage ([#4164](https://github.com/bastani-inc/atomic/pull/4164))
|
|
61
|
+
- **Content-filter refusals fall back:** a provider content-filter refusal, such as OpenAI's 422 `cyber_policy`, moves to the next `fallbackModels` entry instead of retrying the model that refused; turn it off with `retry.fallbackOnContentFilter` ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
62
|
+
- **Workflow worktrees from anywhere:** `git_worktree_dir` can name a worktree of any repository, and a non-empty folder gets its own checkout inside it ([#4162](https://github.com/bastani-inc/atomic/pull/4162))
|
|
63
|
+
- **Gemini 4 Argon in model routing:** automatic model routing now weighs Gemini 4 Argon's published benchmark results ([#4161](https://github.com/bastani-inc/atomic/pull/4161))
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
|
|
67
|
+
- `retry.fallbackOnContentFilter` setting (default `true`). Set it to `false` to keep a provider content-filter refusal on the model that gave it instead of moving to the next `fallbackModels` entry ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
68
|
+
- Recorded Gemini 4 Argon results in the evals snapshot used by automatic model routing: its Artificial Analysis row at high effort, Cognition FrontierCode 1.1 at medium effort, Zapier AutomationBench at high and medium effort, and Google's vendor-reported launch results, including DeepSWE v1.1, Terminal-Bench 4.0 and Terminal-Bench-Science ([#4161](https://github.com/bastani-inc/atomic/pull/4161)).
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
|
|
72
|
+
- A workflow's `gitWorktreeDir` (the `git_worktree_dir` input of `goal` and `ralph`) that names a non-empty directory which is not a Git checkout is now used as a place to put worktrees: the run gets its own checkout at `<dir>/<4-hex>/<repository-name>`, created from `base_branch` of the invoking repository, and leaves the directory's existing content alone. Every stage, retry and resume of that run uses the same checkout, and other runs pointing at the same directory get their own. An existing empty directory becomes the worktree. Before, both failed with `gitWorktreeDir already exists but is not a Git worktree`. ([#4162](https://github.com/bastani-inc/atomic/pull/4162))
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- A workflow's `gitWorktreeDir` (the `git_worktree_dir` input of `goal` and `ralph`) can name an existing worktree of any repository, even when the session runs in another repository or outside any Git repository. Before, every launch failed before its first stage with `gitWorktreeDir already exists but does not belong to the invoking Git repository` or `gitWorktreeDir requires the workflow to be invoked from inside a Git repository`. Stages start at the worktree root unless the session is in the same repository. Creating a new worktree still requires starting inside the source repository, and the error now says to pass an existing worktree instead. ([#4162](https://github.com/bastani-inc/atomic/pull/4162))
|
|
77
|
+
- A provider content-filter refusal now moves a main chat, subagent or workflow stage to its next `fallbackModels` entry at once, without retrying the model that refused, and the refusing model is recorded in the fallback history. This covers OpenAI's HTTP 422 `cyber_policy` ("This content was flagged for possible cybersecurity risk"), Anthropic's refusal stop, `content_filter` finish reasons and safety- or policy-blocked requests. Before, Anthropic and `content_filter` refusals were retried on the same model and then failed the turn, subagent or stage, and a 422 `cyber_policy` refusal fell back only because it was not recognized as a refusal ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
78
|
+
- A local worker pool (`workflows.localWorkers`) whose journal or root answers more slowly than the work lease, as on a busy machine or while the root's process pauses, no longer stops every worker at the same moment and replays every child on a new one. A worker waiting for the pool's own answer is no longer taken for a silent one, so it keeps its child and its lease is renewed once the answer comes. ([#4165](https://github.com/bastani-inc/atomic/pull/4165))
|
|
79
|
+
- Lease recovery in a local worker pool no longer fails the whole pool, and with it every unfinished child at once with `stale_work_lease`, when an expired attempt changes hands while recovery acts on it, for example because its worker just exited and its child was released for replay. ([#4165](https://github.com/bastani-inc/atomic/pull/4165))
|
|
80
|
+
- A stage on a local worker (`workflows.localWorkers`) that starts after a sticky Intercom broadcast (`workflow:<rootRunId>/**`) or a name or pattern send to future stages gets those messages before its first turn, under "Messages received before you started" with the real sender, even when the root is too busy to answer. Before, each such stage on a busy root could wait 60 seconds and then print a long "starting without its queued Intercom messages" warning in the chat, listing messages it may already have received. The worker now delivers the stage's queued messages itself and never waits on the root. If the root later fails to record or deliver them, the run's status shows one `Intercom delivery:` line for the whole run, not a warning per stage ([#4164](https://github.com/bastani-inc/atomic/pull/4164)).
|
|
81
|
+
- A workflow run no longer keeps the live session of every stage it completed in memory until the whole run ends. A stage run with `ctx.task`, `ctx.chain` or `ctx.parallel` gives its session back as soon as it completes, and one run with `ctx.stage` once the workflow no longer holds its stage context; its saved transcript still opens from the graph, `/workflow attach` or the stage chat. A session hosting long runs with hundreds of completed stages held gigabytes this way, and the garbage collection that memory caused made the interactive TUI, `/tasks` and queued messages slow to respond. ([#4166](https://github.com/bastani-inc/atomic/pull/4166))
|
|
82
|
+
- In the interactive TUI, rows that the engine renders, such as tool results and extension messages, keep their last frame when the chat is rebuilt (after compaction, `/reload` or switching sessions), instead of showing `Loading isolated renderer…` until a busy engine renders each one again. A rebuilt chat also no longer leaves the renderers of the rows it replaced running in the engine for the rest of the session, and engine messages reach chat rows through one subscription instead of one per row. ([#4167](https://github.com/bastani-inc/atomic/pull/4167))
|
|
19
83
|
|
|
20
84
|
## [0.9.61-alpha.1] - 2026-11-02
|
|
21
85
|
|
|
@@ -9100,6 +9100,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
9100
9100
|
return;
|
|
9101
9101
|
}
|
|
9102
9102
|
const generation = runtimeGeneration;
|
|
9103
|
+
let startupDrained = false;
|
|
9104
|
+
let redrainRequested = false;
|
|
9103
9105
|
const deliverPending = async (started = false) => {
|
|
9104
9106
|
const receivedMessageIds = ctx.sessionManager.getBranch().flatMap((entry) => {
|
|
9105
9107
|
if (entry.type !== "custom_message" || entry.customType !== "intercom_message")
|
|
@@ -9107,10 +9109,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
9107
9109
|
const id = entry.details?.message?.id;
|
|
9108
9110
|
return typeof id === "string" ? [id] : [];
|
|
9109
9111
|
});
|
|
9110
|
-
await pendingStageDelivery.deliverPending((from, message) => started ? handleIncomingMessage(ctx, from, message, undefined, false, true) : handleIncomingMessage(ctx, from, message, undefined, true), { sessionId: ctx.sessionManager.getSessionId(), receivedMessageIds });
|
|
9112
|
+
await pendingStageDelivery.deliverPending((from, message) => started || startupDrained ? handleIncomingMessage(ctx, from, message, undefined, false, true) : handleIncomingMessage(ctx, from, message, undefined, true), { sessionId: ctx.sessionManager.getSessionId(), receivedMessageIds });
|
|
9111
9113
|
};
|
|
9112
|
-
let startupDrained = false;
|
|
9113
|
-
let redrainRequested = false;
|
|
9114
9114
|
const redrain = () => {
|
|
9115
9115
|
if (!getLiveContext(ctx, generation))
|
|
9116
9116
|
return;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.9.61-alpha.
|
|
3
|
+
"version": "0.9.61-alpha.3",
|
|
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": [
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.61] - 2026-11-02
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- A subagent whose model refuses the request under a provider content filter, such as OpenAI's HTTP 422 `cyber_policy`, Anthropic's refusal stop or a `content_filter` finish reason, now moves straight to its next `fallbackModels` entry instead of retrying that model and failing. Set `retry.fallbackOnContentFilter: false` to keep the refusal on that model ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
10
|
+
|
|
11
|
+
## [0.9.61-alpha.2] - 2026-11-02
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- A subagent whose model refuses the request under a provider content filter, such as OpenAI's HTTP 422 `cyber_policy`, Anthropic's refusal stop or a `content_filter` finish reason, now moves straight to its next `fallbackModels` entry instead of retrying that model and failing. Set `retry.fallbackOnContentFilter: false` to keep the refusal on that model ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
16
|
+
|
|
5
17
|
## [0.9.60] - 2026-11-01
|
|
6
18
|
|
|
7
19
|
Subagents keep the model you asked for.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.9.61-alpha.
|
|
3
|
+
"version": "0.9.61-alpha.3",
|
|
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.61-alpha.
|
|
3
|
+
"version": "0.9.61-alpha.3",
|
|
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,20 @@ 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.61] - 2026-11-02
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- A stage whose model refuses the request under a provider content filter, such as OpenAI's HTTP 422 `cyber_policy`, Anthropic's refusal stop or a `content_filter` finish reason, now moves straight to its next `fallbackModels` entry instead of retrying that model and failing. Its `modelAttempts` record the refusing model and its error. Set `retry.fallbackOnContentFilter: false` to fail the stage on such a refusal instead ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
14
|
+
- A workflow run no longer keeps the live session of every stage it completed in memory until the whole run ends. A stage run with `ctx.task`, `ctx.chain` or `ctx.parallel` gives its session back as soon as it completes, and one run with `ctx.stage` once the workflow no longer holds its stage context; its saved transcript still opens from the graph, `/workflow attach` or the stage chat. A session hosting long runs with hundreds of completed stages held gigabytes this way, and the garbage collection that memory caused made the interactive TUI, `/tasks` and queued messages slow to respond. ([#4166](https://github.com/bastani-inc/atomic/pull/4166))
|
|
15
|
+
|
|
16
|
+
## [0.9.61-alpha.2] - 2026-11-02
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- A stage whose model refuses the request under a provider content filter, such as OpenAI's HTTP 422 `cyber_policy`, Anthropic's refusal stop or a `content_filter` finish reason, now moves straight to its next `fallbackModels` entry instead of retrying that model and failing. Its `modelAttempts` record the refusing model and its error. Set `retry.fallbackOnContentFilter: false` to fail the stage on such a refusal instead ([#4163](https://github.com/bastani-inc/atomic/pull/4163))
|
|
21
|
+
- A workflow run no longer keeps the live session of every stage it completed in memory until the whole run ends. A stage run with `ctx.task`, `ctx.chain` or `ctx.parallel` gives its session back as soon as it completes, and one run with `ctx.stage` once the workflow no longer holds its stage context; its saved transcript still opens from the graph, `/workflow attach` or the stage chat. A session hosting long runs with hundreds of completed stages held gigabytes this way, and the garbage collection that memory caused made the interactive TUI, `/tasks` and queued messages slow to respond. ([#4166](https://github.com/bastani-inc/atomic/pull/4166))
|
|
22
|
+
|
|
9
23
|
## [0.9.58] - 2026-11-01
|
|
10
24
|
|
|
11
25
|
### Added
|
|
@@ -365,7 +365,7 @@ An author-initiated failed exit returns `{ exited: true, status: "failed" }` to
|
|
|
365
365
|
|
|
366
366
|
### Reusable Git worktrees
|
|
367
367
|
|
|
368
|
-
Use `gitWorktreeDir` when a workflow should run in a reusable Git worktree instead of the invoking checkout. The executor creates
|
|
368
|
+
Use `gitWorktreeDir` when a workflow should run in a reusable Git worktree instead of the invoking checkout. The executor reuses an existing worktree root of any repository, creates a worktree when the path is missing or an empty directory, allocates a run-owned checkout inside a non-empty directory that is not a Git checkout, defaults workflow `ctx.cwd` to the matching path inside that worktree for `worktreeFromInputs`, and defaults stage/task `cwd` to that worktree path.
|
|
369
369
|
|
|
370
370
|
```typescript
|
|
371
371
|
import { workflow } from "@bastani/atomic/workflows";
|
|
@@ -417,15 +417,17 @@ await ctx.parallel([
|
|
|
417
417
|
|
|
418
418
|
Worktree semantics:
|
|
419
419
|
|
|
420
|
-
-
|
|
421
|
-
- If the
|
|
422
|
-
-
|
|
423
|
-
-
|
|
420
|
+
- Relative paths resolve from the logical invoking repository root, or from the invoking cwd when it is not inside a Git repository; absolute paths are used as-is.
|
|
421
|
+
- If the path is an existing Git worktree or checkout root, it is reused as-is, whichever repository it belongs to and even when the workflow starts outside any Git repository. Its repository identity comes from the worktree itself. Subdirectories of an existing checkout are rejected. Every path, whether existing, empty, or missing, is rejected when it is the invoking checkout, is nested beneath it, or lies inside Git metadata (a `.git` directory, a linked worktree's admin directory, or a bare repository). Inside any other repository's working tree only that tree's root is accepted, for reuse: empty, missing, or non-empty paths below it are rejected so no checkout is nested inside another repository. Missing paths and plain container directories outside every Git working tree stay allowed.
|
|
422
|
+
- Creating a worktree requires the workflow to start inside the repository the worktree should come from; otherwise setup fails and suggests passing an existing worktree root instead.
|
|
423
|
+
- If the path is missing or an empty directory, Git runs `git worktree add --detach <path> <baseBranch>` from the canonical main repository root (creating a missing parent directory first). `baseBranch` defaults to `HEAD` when omitted. Missing targets whose existing parent resolves through a symlink beneath the invoking checkout are rejected.
|
|
424
|
+
- If the path is a non-empty directory that is not a Git checkout, it is treated as a worktree root: the run gets its own checkout at `<path>/<4-hex bucket>/<repository-name>`, created detached from `baseBranch` (default `HEAD`) of the invoking repository. Existing content is left untouched, a bucket that already exists is never reused, and a failed creation removes the partial checkout and its bucket. The run's ownership is recorded in the checkout's Git directory, so every stage, retry, and `/workflow resume` of that run reuses the same checkout, while separate runs pointing at the same directory get separate checkouts.
|
|
425
|
+
- The default execution cwd preserves the caller's repo-relative cwd inside the worktree when the caller is in the worktree's repository. For example, invoking a workflow from `repo/packages/api` with `gitWorktreeDir=../repo-wt` uses `../repo-wt/packages/api` for workflow `ctx.cwd` and stage/task execution. A worktree of another repository starts at its root, and an allocated checkout must contain the caller's subdirectory.
|
|
424
426
|
- Symlinked repo/worktree paths preserve their logical spelling in the default cwd, matching Codex-style worktree behavior.
|
|
425
|
-
- An explicit absolute `cwd` inside the invoking checkout is remapped to the corresponding worktree path; an absolute `cwd` already inside the selected worktree is preserved. Relative values resolve from the worktree default cwd and cannot escape it. Foreign paths, lexical traversal, and symlink escapes fail before a session starts.
|
|
427
|
+
- An explicit absolute `cwd` inside the invoking checkout is remapped to the corresponding worktree path when both belong to the same repository; an absolute `cwd` already inside the selected worktree is preserved. Relative values resolve from the worktree default cwd and cannot escape it. Foreign paths, lexical traversal, and symlink escapes fail before a session starts.
|
|
426
428
|
- Relative stage/task outputs follow the effective worktree cwd and cannot traverse or follow symlinks outside the selected worktree. Explicit absolute outputs remain caller-selected.
|
|
427
429
|
|
|
428
|
-
`worktree: true` on an authored `ctx.task(...)` is different: it creates a branch-backed temporary checkout at `<main-root>/.atomic/worktrees/<flattened-name>` using branch `worktree-<flattened-name>` and cleans up both checkout and branch afterward, including failures before the task callback starts. `/` in generated names is flattened to `+`, and creation stays anchored at the canonical main root even when Atomic is launched from a linked worktree. The base ref is an explicit `baseBranch`, then `origin/<default-branch>` (fetched when needed), then `HEAD`. Post-creation setup copies `.atomic/settings.local.json` plus untracked `.atomic/settings.json`, shares the main repository's Husky or populated `.git/hooks` directory through `core.hooksPath`, symlinks configured `worktree.symlinkDirectories`, and copies gitignored files matched by `.worktreeinclude`; tracked checkout content is never overwritten. When no task `cwd` is set, temporary isolation starts from the runner invocation cwd; relative task cwd values resolve from that same invocation cwd. Relative task outputs are persisted under distinct per-task runner-owned temporary artifact directories before cleanup; returned output artifact paths therefore remain readable, including with `outputMode: "file-only"`. Those relative paths cannot traverse or follow symlinks outside their runner-owned output root, and a pre-existing symlink or junction at the trusted artifact root is rejected. It is mutually exclusive with `gitWorktreeDir`, which is intended for named/reusable worktrees that remain available across retries and `/workflow resume`. Durable resume records the original invocation cwd and resolved reusable-worktree metadata, then replays from that original repository context rather than whichever cwd the resumed interactive session currently has. Reusable worktree setup is cached by canonical
|
|
430
|
+
`worktree: true` on an authored `ctx.task(...)` is different: it creates a branch-backed temporary checkout at `<main-root>/.atomic/worktrees/<flattened-name>` using branch `worktree-<flattened-name>` and cleans up both checkout and branch afterward, including failures before the task callback starts. `/` in generated names is flattened to `+`, and creation stays anchored at the canonical main root even when Atomic is launched from a linked worktree. The base ref is an explicit `baseBranch`, then `origin/<default-branch>` (fetched when needed), then `HEAD`. Post-creation setup copies `.atomic/settings.local.json` plus untracked `.atomic/settings.json`, shares the main repository's Husky or populated `.git/hooks` directory through `core.hooksPath`, symlinks configured `worktree.symlinkDirectories`, and copies gitignored files matched by `.worktreeinclude`; tracked checkout content is never overwritten. When no task `cwd` is set, temporary isolation starts from the runner invocation cwd; relative task cwd values resolve from that same invocation cwd. Relative task outputs are persisted under distinct per-task runner-owned temporary artifact directories before cleanup; returned output artifact paths therefore remain readable, including with `outputMode: "file-only"`. Those relative paths cannot traverse or follow symlinks outside their runner-owned output root, and a pre-existing symlink or junction at the trusted artifact root is rejected. It is mutually exclusive with `gitWorktreeDir`, which is intended for named/reusable worktrees that remain available across retries and `/workflow resume`. Durable resume records the original invocation cwd and resolved reusable-worktree metadata, then replays from that original repository context rather than whichever cwd the resumed interactive session currently has. Reusable worktree setup is cached by canonical invoking cwd and target path within a workflow run, independent of equivalent path spelling or `baseBranch`, and the selected checkout identity is revalidated before reuse. Read-only Git repository probes retry a transient timeout once, and slow Git subprocess failures include the exact command, cwd, timeout, elapsed time, exit status/signal, and spawn error details.
|
|
429
431
|
|
|
430
432
|
Worktrees provide checkout and cwd isolation, not an operating-system security sandbox. A process with permission to mutate arbitrary sibling paths can still race filesystem checks; use a container, VM, or another OS-enforced boundary for untrusted code.
|
|
431
433
|
|
|
@@ -896,7 +896,7 @@ var ralph_default = workflow({
|
|
|
896
896
|
}),
|
|
897
897
|
git_worktree_dir: Type2.String({
|
|
898
898
|
default: "",
|
|
899
|
-
description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own.
|
|
899
|
+
description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own. Absolute paths are used as-is; relative paths resolve from the invoking repo root (or the invoking cwd outside a Git repo). An existing Git worktree root of any repository is reused as-is, even from another repository or a non-Git cwd. Creating a worktree requires starting inside the source Git repo: a missing path or an empty directory becomes a new worktree from base_branch, and a non-empty non-Git directory is treated as a worktree root that gets this run's own <dir>/<4-hex>/<repo-name> checkout, reused on resume."
|
|
900
900
|
}),
|
|
901
901
|
create_pr: Type2.Boolean({
|
|
902
902
|
default: false,
|
|
@@ -1118,7 +1118,7 @@ var goal_default = workflow({
|
|
|
1118
1118
|
}),
|
|
1119
1119
|
git_worktree_dir: Type2.String({
|
|
1120
1120
|
default: "",
|
|
1121
|
-
description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own.
|
|
1121
|
+
description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own. Absolute paths are used as-is; relative paths resolve from the invoking repo root (or the invoking cwd outside a Git repo). An existing Git worktree root of any repository is reused as-is, even from another repository or a non-Git cwd. Creating a worktree requires starting inside the source Git repo: a missing path or an empty directory becomes a new worktree from base_branch, and a non-empty non-Git directory is treated as a worktree root that gets this run's own <dir>/<4-hex>/<repo-name> checkout, reused on resume."
|
|
1122
1122
|
}),
|
|
1123
1123
|
create_pr: Type2.Boolean({
|
|
1124
1124
|
default: false,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "./chunk-8d40nyz9.js";
|
|
17
17
|
import {
|
|
18
18
|
goal_default
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-vzbec50q.js";
|
|
20
20
|
import"./chunk-zhyqnf5g.js";
|
|
21
21
|
import"./chunk-z0d03ktm.js";
|
|
22
22
|
import {
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
} from "./chunk-37gm3bzk.js";
|
|
28
28
|
import {
|
|
29
29
|
ralph_default
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-a2j0x1a6.js";
|
|
31
31
|
import {
|
|
32
32
|
tournament_default
|
|
33
33
|
} from "./chunk-2f1shjah.js";
|