@bastani/atomic 0.9.61-alpha.1 → 0.9.61-alpha.2

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 (61) hide show
  1. package/CHANGELOG.md +54 -4
  2. package/dist/builtin/intercom/index.bundle.mjs +3 -3
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/package.json +1 -1
  5. package/dist/builtin/subagents/CHANGELOG.md +12 -0
  6. package/dist/builtin/subagents/package.json +1 -1
  7. package/dist/builtin/web-access/package.json +1 -1
  8. package/dist/builtin/workflows/CHANGELOG.md +14 -0
  9. package/dist/builtin/workflows/README.md +9 -7
  10. package/dist/builtin/workflows/builtin/{chunk-h6bt0r0g.js → chunk-a2j0x1a6.js} +1 -1
  11. package/dist/builtin/workflows/builtin/{chunk-g3b2zf8r.js → chunk-vzbec50q.js} +1 -1
  12. package/dist/builtin/workflows/builtin/goal.js +1 -1
  13. package/dist/builtin/workflows/builtin/index.js +2 -2
  14. package/dist/builtin/workflows/builtin/ralph.js +1 -1
  15. package/dist/builtin/workflows/package.json +1 -1
  16. package/dist/builtin/workflows/src/extension/index.bundle.mjs +779 -409
  17. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +844 -419
  18. package/dist/builtin/workflows/src/index.js +749 -384
  19. package/dist/builtin/workflows/src/local-worker-entry.mjs +844 -419
  20. package/dist/core/agent-session-retry.d.ts.map +1 -1
  21. package/dist/core/agent-session-retry.js +12 -3
  22. package/dist/core/agent-session-retry.js.map +1 -1
  23. package/dist/core/model-fallback-failures.d.ts +14 -4
  24. package/dist/core/model-fallback-failures.d.ts.map +1 -1
  25. package/dist/core/model-fallback-failures.js +43 -15
  26. package/dist/core/model-fallback-failures.js.map +1 -1
  27. package/dist/core/settings-defaults.d.ts +1 -0
  28. package/dist/core/settings-defaults.d.ts.map +1 -1
  29. package/dist/core/settings-defaults.js +1 -0
  30. package/dist/core/settings-defaults.js.map +1 -1
  31. package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
  32. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  33. package/dist/core/settings-manager-basic-accessors.js +2 -0
  34. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  35. package/dist/core/settings-schema.d.ts +2 -0
  36. package/dist/core/settings-schema.d.ts.map +1 -1
  37. package/dist/core/settings-schema.js +4 -0
  38. package/dist/core/settings-schema.js.map +1 -1
  39. package/dist/core/slash-commands.js +2 -2
  40. package/dist/core/slash-commands.js.map +1 -1
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/modes/interactive/interactive-startup-chat-container.d.ts +2 -0
  45. package/dist/modes/interactive/interactive-startup-chat-container.d.ts.map +1 -1
  46. package/dist/modes/interactive/interactive-startup-chat-container.js +6 -0
  47. package/dist/modes/interactive/interactive-startup-chat-container.js.map +1 -1
  48. package/dist/modes/interactive-engine/remote-renderer.d.ts +27 -5
  49. package/dist/modes/interactive-engine/remote-renderer.d.ts.map +1 -1
  50. package/dist/modes/interactive-engine/remote-renderer.js +76 -16
  51. package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
  52. package/docs/intercom/reference.md +1 -1
  53. package/docs/models/evals.md +30 -2
  54. package/docs/settings.md +3 -0
  55. package/docs/subagents/reference.md +3 -1
  56. package/docs/workflows/api-reference.md +9 -6
  57. package/docs/workflows/builtins.md +1 -1
  58. package/docs/workflows/operations.md +3 -3
  59. package/npm-shrinkwrap.json +32 -32
  60. package/package.json +3 -3
  61. 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
- A local worker pool that keeps going when one child or one worker goes wrong.
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 the pool:** a child that fails to dispatch fails alone instead of closing the whole local worker pool, and a child whose result is recorded keeps it whatever happens to the pool afterwards ([#4159](https://github.com/bastani-inc/atomic/pull/4159))
10
- - **Cleanup trouble is a warning, not a failure:** a worker or tool process group that survives SIGKILL shows as a warning on the root run; the worker is replaced and its child replays on another worker within its three attempts ([#4159](https://github.com/bastani-inc/atomic/pull/4159))
11
- - **Pool faults replay instead of failing:** a child that hits `stale_work_lease`, `worker_lost` or another pool fault replays from its last checkpoint, and fails with the retryable `worker_retry_limit` only after its third attempt ([#4159](https://github.com/bastani-inc/atomic/pull/4159))
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 ([#4159](https://github.com/bastani-inc/atomic/pull/4159))
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…" ([#4166](https://github.com/bastani-inc/atomic/pull/4166), [#4167](https://github.com/bastani-inc/atomic/pull/4167))
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,43 @@ 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
+
40
+ ## [0.9.61-alpha.2] - 2026-11-02
41
+
42
+ A lighter terminal under heavy workflow load, local worker pools that hold their leases, and workflows that can work in any repository's worktree.
43
+
44
+ - **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))
45
+ - **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))
46
+ - **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))
47
+ - **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))
48
+ - **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))
49
+ - **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))
50
+
51
+ ### Added
52
+
53
+ - `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))
54
+ - 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)).
55
+
56
+ ### Changed
57
+
58
+ - 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))
59
+
60
+ ### Fixed
61
+
62
+ - 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))
63
+ - 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))
64
+ - 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))
65
+ - 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))
66
+ - 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)).
67
+ - 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))
68
+ - 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
69
 
20
70
  ## [0.9.61-alpha.1] - 2026-11-02
21
71
 
@@ -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.1",
3
+ "version": "0.9.61-alpha.2",
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": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.61-alpha.1",
3
+ "version": "0.9.61-alpha.2",
4
4
  "private": true,
5
5
  "description": "Atomic's pi-compatible MCP integration for server connections, OAuth, tools, resources, and terminal management.",
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.1",
3
+ "version": "0.9.61-alpha.2",
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.1",
3
+ "version": "0.9.61-alpha.2",
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 the worktree if it is missing, reuses it when it already exists as a same-repository worktree root, defaults workflow `ctx.cwd` to the matching path inside that worktree for `worktreeFromInputs`, and defaults stage/task `cwd` to that worktree path.
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
- - `gitWorktreeDir` must be used from inside a Git repository. Relative paths resolve from the logical invoking repository root; absolute paths are used as-is.
421
- - If the requested path exists, it must be an actual Git worktree/checkout root belonging to the invoking repository. The invoking checkout itself, paths nested beneath it, foreign repositories, and existing subdirectories are rejected so writes do not silently land in the main checkout.
422
- - If the path is missing, the parent directory is created and Git runs `git worktree add --detach <path> <baseBranch>` from the canonical main repository root. `baseBranch` defaults to `HEAD` when omitted. Missing targets whose existing parent resolves through a symlink beneath the invoking checkout are rejected.
423
- - The default execution cwd preserves the caller's repo-relative cwd inside the worktree. 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.
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 repository and target identity 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.
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. Must start inside a Git repo; absolute paths are used as-is, relative paths resolve from the repo root, existing Git worktrees from the invoking repository are reused/shared as-is, and missing paths are created from base_branch."
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. Must start inside a Git repo; absolute paths are used as-is, relative paths resolve from the repo root, existing Git worktrees from the invoking repository are reused/shared as-is, and missing paths are created from base_branch."
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,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  goal_default
3
- } from "./chunk-g3b2zf8r.js";
3
+ } from "./chunk-vzbec50q.js";
4
4
  import"./chunk-zhyqnf5g.js";
5
5
  import"./chunk-2377r57g.js";
6
6
  import"./chunk-z0d03ktm.js";
@@ -16,7 +16,7 @@ import {
16
16
  } from "./chunk-8d40nyz9.js";
17
17
  import {
18
18
  goal_default
19
- } from "./chunk-g3b2zf8r.js";
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-h6bt0r0g.js";
30
+ } from "./chunk-a2j0x1a6.js";
31
31
  import {
32
32
  tournament_default
33
33
  } from "./chunk-2f1shjah.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ralph_default
3
- } from "./chunk-h6bt0r0g.js";
3
+ } from "./chunk-a2j0x1a6.js";
4
4
  import"./chunk-zhyqnf5g.js";
5
5
  import"./chunk-2377r57g.js";
6
6
  import"./chunk-z0d03ktm.js";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/workflows",
3
- "version": "0.9.61-alpha.1",
3
+ "version": "0.9.61-alpha.2",
4
4
  "private": true,
5
5
  "description": "Atomic extension for multi-stage workflow authoring and execution.",
6
6
  "contributors": [