@bastani/atomic 0.8.29-alpha.4 → 0.8.30-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/builtin/cursor/CHANGELOG.md +6 -0
  3. package/dist/builtin/cursor/package.json +2 -2
  4. package/dist/builtin/intercom/CHANGELOG.md +7 -1
  5. package/dist/builtin/intercom/package.json +2 -2
  6. package/dist/builtin/mcp/CHANGELOG.md +7 -1
  7. package/dist/builtin/mcp/package.json +3 -3
  8. package/dist/builtin/subagents/CHANGELOG.md +11 -0
  9. package/dist/builtin/subagents/README.md +10 -30
  10. package/dist/builtin/subagents/package.json +4 -4
  11. package/dist/builtin/subagents/skills/subagent/SKILL.md +5 -11
  12. package/dist/builtin/subagents/src/agents/agent-management.ts +0 -5
  13. package/dist/builtin/subagents/src/agents/agent-serializer.ts +7 -3
  14. package/dist/builtin/subagents/src/agents/agents.ts +4 -29
  15. package/dist/builtin/subagents/src/agents/chain-serializer.ts +27 -25
  16. package/dist/builtin/subagents/src/extension/schemas.ts +0 -75
  17. package/dist/builtin/subagents/src/runs/background/async-execution.ts +0 -29
  18. package/dist/builtin/subagents/src/runs/background/run-status.ts +1 -2
  19. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +134 -239
  20. package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +1 -52
  21. package/dist/builtin/subagents/src/runs/foreground/execution.ts +103 -94
  22. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +0 -10
  23. package/dist/builtin/subagents/src/runs/shared/dynamic-fanout.ts +16 -8
  24. package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +0 -1
  25. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +0 -3
  26. package/dist/builtin/subagents/src/runs/shared/structured-output.ts +67 -2
  27. package/dist/builtin/subagents/src/runs/shared/subagent-control.ts +6 -20
  28. package/dist/builtin/subagents/src/runs/shared/subagent-prompt-runtime.ts +1 -1
  29. package/dist/builtin/subagents/src/runs/shared/workflow-graph.ts +2 -6
  30. package/dist/builtin/subagents/src/shared/settings.ts +1 -4
  31. package/dist/builtin/subagents/src/shared/types.ts +1 -156
  32. package/dist/builtin/subagents/src/tui/render.ts +0 -1
  33. package/dist/builtin/web-access/CHANGELOG.md +7 -1
  34. package/dist/builtin/web-access/package.json +2 -2
  35. package/dist/builtin/workflows/CHANGELOG.md +13 -0
  36. package/dist/builtin/workflows/README.md +2 -2
  37. package/dist/builtin/workflows/package.json +2 -2
  38. package/dist/builtin/workflows/src/extension/index.ts +8 -1
  39. package/dist/builtin/workflows/src/extension/wiring.ts +66 -10
  40. package/dist/builtin/workflows/src/runs/foreground/executor.ts +70 -19
  41. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +98 -14
  42. package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +0 -1
  43. package/dist/builtin/workflows/src/shared/persistence-restore.ts +4 -0
  44. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
  45. package/dist/builtin/workflows/src/shared/store.ts +2 -0
  46. package/dist/config.d.ts.map +1 -1
  47. package/dist/config.js +18 -4
  48. package/dist/config.js.map +1 -1
  49. package/dist/core/agent-session.d.ts +2 -2
  50. package/dist/core/agent-session.d.ts.map +1 -1
  51. package/dist/core/agent-session.js +21 -9
  52. package/dist/core/agent-session.js.map +1 -1
  53. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  54. package/dist/core/compaction/branch-summarization.js +2 -2
  55. package/dist/core/compaction/branch-summarization.js.map +1 -1
  56. package/dist/core/compaction/compaction.d.ts +6 -0
  57. package/dist/core/compaction/compaction.d.ts.map +1 -1
  58. package/dist/core/compaction/compaction.js +2 -0
  59. package/dist/core/compaction/compaction.js.map +1 -1
  60. package/dist/core/compaction/context-compaction.d.ts +43 -16
  61. package/dist/core/compaction/context-compaction.d.ts.map +1 -1
  62. package/dist/core/compaction/context-compaction.js +518 -189
  63. package/dist/core/compaction/context-compaction.js.map +1 -1
  64. package/dist/core/extensions/loader.d.ts +4 -2
  65. package/dist/core/extensions/loader.d.ts.map +1 -1
  66. package/dist/core/extensions/loader.js +11 -7
  67. package/dist/core/extensions/loader.js.map +1 -1
  68. package/dist/core/extensions/types.d.ts +14 -3
  69. package/dist/core/extensions/types.d.ts.map +1 -1
  70. package/dist/core/extensions/types.js.map +1 -1
  71. package/dist/core/model-registry.d.ts.map +1 -1
  72. package/dist/core/model-registry.js +2 -1
  73. package/dist/core/model-registry.js.map +1 -1
  74. package/dist/core/package-manager.d.ts +1 -1
  75. package/dist/core/package-manager.d.ts.map +1 -1
  76. package/dist/core/package-manager.js +52 -18
  77. package/dist/core/package-manager.js.map +1 -1
  78. package/dist/core/resource-loader.d.ts +20 -0
  79. package/dist/core/resource-loader.d.ts.map +1 -1
  80. package/dist/core/resource-loader.js +89 -24
  81. package/dist/core/resource-loader.js.map +1 -1
  82. package/dist/core/session-manager.d.ts +14 -1
  83. package/dist/core/session-manager.d.ts.map +1 -1
  84. package/dist/core/session-manager.js +145 -3
  85. package/dist/core/session-manager.js.map +1 -1
  86. package/dist/core/settings-manager.d.ts +9 -0
  87. package/dist/core/settings-manager.d.ts.map +1 -1
  88. package/dist/core/settings-manager.js +16 -0
  89. package/dist/core/settings-manager.js.map +1 -1
  90. package/dist/core/thinking-blocks.d.ts +7 -0
  91. package/dist/core/thinking-blocks.d.ts.map +1 -0
  92. package/dist/core/thinking-blocks.js +16 -0
  93. package/dist/core/thinking-blocks.js.map +1 -0
  94. package/dist/core/tools/bash.d.ts.map +1 -1
  95. package/dist/core/tools/bash.js +4 -0
  96. package/dist/core/tools/bash.js.map +1 -1
  97. package/dist/index.d.ts +2 -2
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +1 -1
  100. package/dist/index.js.map +1 -1
  101. package/dist/main.d.ts.map +1 -1
  102. package/dist/main.js +30 -0
  103. package/dist/main.js.map +1 -1
  104. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  105. package/dist/modes/interactive/components/tree-selector.js +87 -12
  106. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  107. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  108. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  109. package/dist/modes/interactive/interactive-mode.js +37 -18
  110. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  111. package/dist/modes/interactive/theme/theme.d.ts +24 -1
  112. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  113. package/dist/modes/interactive/theme/theme.js +58 -13
  114. package/dist/modes/interactive/theme/theme.js.map +1 -1
  115. package/dist/utils/child-process.d.ts +9 -4
  116. package/dist/utils/child-process.d.ts.map +1 -1
  117. package/dist/utils/child-process.js +42 -10
  118. package/dist/utils/child-process.js.map +1 -1
  119. package/dist/utils/version-check.d.ts.map +1 -1
  120. package/dist/utils/version-check.js +4 -27
  121. package/dist/utils/version-check.js.map +1 -1
  122. package/docs/compaction.md +469 -51
  123. package/docs/containerization.md +37 -37
  124. package/docs/extensions.md +23 -14
  125. package/docs/models.md +6 -4
  126. package/docs/packages.md +2 -0
  127. package/docs/providers.md +1 -1
  128. package/docs/subagents.md +11 -4
  129. package/docs/workflows.md +4 -2
  130. package/examples/extensions/README.md +2 -2
  131. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  132. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  133. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  134. package/examples/extensions/gondolin/package-lock.json +2 -2
  135. package/examples/extensions/gondolin/package.json +1 -1
  136. package/examples/extensions/question.ts +39 -18
  137. package/examples/extensions/questionnaire.ts +49 -28
  138. package/examples/extensions/sandbox/package-lock.json +2 -2
  139. package/examples/extensions/sandbox/package.json +1 -1
  140. package/examples/extensions/with-deps/package-lock.json +2 -2
  141. package/examples/extensions/with-deps/package.json +1 -1
  142. package/package.json +7 -5
  143. package/dist/builtin/subagents/src/runs/shared/acceptance.ts +0 -612
  144. package/dist/builtin/subagents/src/runs/shared/completion-guard.ts +0 -147
@@ -163,16 +163,6 @@ function formatLongRunningFacts(event: ControlEvent): string | undefined {
163
163
 
164
164
  export function formatControlNoticeMessage(event: ControlEvent, childIntercomTarget?: string): string {
165
165
  const runTarget = event.runId;
166
- if (event.reason === "completion_guard") {
167
- return [
168
- `Subagent failed: ${event.agent}`,
169
- `Run: ${runTarget}${event.index !== undefined ? ` step ${event.index + 1}` : ""}`,
170
- `Signal: ${event.message}`,
171
- "Next: read the output artifact or session from the subagent result, then retry with a more explicit implementation prompt or handle the fix directly.",
172
- childIntercomTarget ? `Run intercom target (may be inactive): ${childIntercomTarget}` : undefined,
173
- ].filter((line): line is string => Boolean(line)).join("\n");
174
- }
175
-
176
166
  const nudgeCommand = childIntercomTarget
177
167
  ? `intercom({ action: "send", to: "${childIntercomTarget}", message: "What are you blocked on? Reply with the smallest next step or ask for a decision." })`
178
168
  : undefined;
@@ -207,19 +197,15 @@ export function formatControlNoticeMessage(event: ControlEvent, childIntercomTar
207
197
  }
208
198
 
209
199
  export function formatControlIntercomMessage(event: ControlEvent, childIntercomTarget?: string): string {
210
- const statusLabel = event.reason === "completion_guard"
211
- ? "subagent failed"
212
- : event.type === "active_long_running"
213
- ? "subagent active but long-running"
214
- : "subagent needs attention";
200
+ const statusLabel = event.type === "active_long_running"
201
+ ? "subagent active but long-running"
202
+ : "subagent needs attention";
215
203
  return [
216
204
  statusLabel,
217
205
  "",
218
- event.reason === "completion_guard"
219
- ? `${event.agent} failed in run ${event.runId}.`
220
- : event.type === "active_long_running"
221
- ? `${event.agent} is still active but long-running in run ${event.runId}.`
222
- : `${event.agent} needs attention in run ${event.runId}.`,
206
+ event.type === "active_long_running"
207
+ ? `${event.agent} is still active but long-running in run ${event.runId}.`
208
+ : `${event.agent} needs attention in run ${event.runId}.`,
223
209
  "",
224
210
  formatControlNoticeMessage(event, childIntercomTarget),
225
211
  ].join("\n");
@@ -21,7 +21,7 @@ export const CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS = [
21
21
 
22
22
  export const CHILD_FANOUT_BOUNDARY_INSTRUCTIONS = [
23
23
  "You are a child subagent with explicit fanout responsibility for this assigned task.",
24
- "The parent session owns final orchestration, acceptance, and follow-up implementation launches.",
24
+ "The parent session owns final orchestration, completion decisions, and follow-up implementation launches.",
25
25
  "You may use the `subagent` tool only for the fanout work explicitly requested in this task.",
26
26
  "Do not broaden yourself into general parent orchestration. Do not launch follow-up workers unless the task explicitly asks for that.",
27
27
  "The maxSubagentDepth cap still applies and may block further fanout.",
@@ -5,12 +5,12 @@ export interface WorkflowGraphBuildInput {
5
5
  runId: string;
6
6
  mode?: SubagentRunMode;
7
7
  steps: ChainStep[];
8
- results?: Array<Pick<SingleResult, "exitCode" | "detached" | "interrupted" | "error" | "acceptance">>;
8
+ results?: Array<Pick<SingleResult, "exitCode" | "detached" | "interrupted" | "error">>;
9
9
  currentFlatIndex?: number;
10
10
  currentStepIndex?: number;
11
11
  stepStatuses?: Array<{ status?: string; error?: string }>;
12
12
  dynamicChildren?: Record<number, Array<{ agent: string; label?: string; flatIndex: number; itemKey: string; outputName?: string; structured?: boolean; error?: string }>>;
13
- dynamicGroupStatuses?: Record<number, { status: WorkflowNodeStatus; error?: string; acceptance?: SingleResult["acceptance"] }>;
13
+ dynamicGroupStatuses?: Record<number, { status: WorkflowNodeStatus; error?: string }>;
14
14
  }
15
15
 
16
16
  function normalizeStatus(status: string | undefined): WorkflowNodeStatus | undefined {
@@ -98,7 +98,6 @@ export function buildWorkflowGraphSnapshot(input: WorkflowGraphBuildInput): Work
98
98
  stepIndex,
99
99
  outputName: task.as,
100
100
  structured: Boolean(task.outputSchema),
101
- acceptanceStatus: input.results?.[flatIndex]?.acceptance?.status,
102
101
  error: input.stepStatuses?.[flatIndex]?.error ?? input.results?.[flatIndex]?.error,
103
102
  };
104
103
  children.push(child);
@@ -142,7 +141,6 @@ export function buildWorkflowGraphSnapshot(input: WorkflowGraphBuildInput): Work
142
141
  itemKey: task.itemKey,
143
142
  outputName: task.outputName,
144
143
  structured: task.structured,
145
- acceptanceStatus: input.results?.[task.flatIndex]?.acceptance?.status,
146
144
  error: input.stepStatuses?.[task.flatIndex]?.error ?? input.results?.[task.flatIndex]?.error ?? task.error,
147
145
  };
148
146
  children.push(child);
@@ -159,7 +157,6 @@ export function buildWorkflowGraphSnapshot(input: WorkflowGraphBuildInput): Work
159
157
  stepIndex,
160
158
  outputName: step.collect.as,
161
159
  structured: Boolean(step.collect.outputSchema),
162
- acceptanceStatus: groupOverride?.acceptance?.status,
163
160
  error: groupOverride?.error,
164
161
  dynamic: {
165
162
  sourceOutput: step.expand.from.output,
@@ -188,7 +185,6 @@ export function buildWorkflowGraphSnapshot(input: WorkflowGraphBuildInput): Work
188
185
  stepIndex,
189
186
  outputName: seq.as,
190
187
  structured: Boolean(seq.outputSchema),
191
- acceptanceStatus: input.results?.[flatIndex]?.acceptance?.status,
192
188
  error: input.stepStatuses?.[flatIndex]?.error ?? input.results?.[flatIndex]?.error,
193
189
  });
194
190
  pushPhase(phases, seq.phase, id);
@@ -6,7 +6,7 @@ import * as fs from "node:fs";
6
6
  import * as path from "node:path";
7
7
  import type { AgentConfig } from "../agents/agents.ts";
8
8
  import { normalizeSkillInput } from "../agents/skills.ts";
9
- import { CHAIN_RUNS_DIR, type AcceptanceInput, type JsonSchemaObject, type OutputMode } from "./types.ts";
9
+ import { CHAIN_RUNS_DIR, type JsonSchemaObject, type OutputMode } from "./types.ts";
10
10
  const CHAIN_DIR_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours
11
11
  const INITIAL_PROGRESS_CONTENT = "# Progress\n\n## Status\nIn Progress\n\n## Tasks\n\n## Files Changed\n\n## Notes\n";
12
12
 
@@ -55,7 +55,6 @@ export interface SequentialStep {
55
55
  progress?: boolean;
56
56
  skill?: string | string[] | false;
57
57
  model?: string;
58
- acceptance?: AcceptanceInput;
59
58
  }
60
59
 
61
60
  /** Parallel task item within a parallel step */
@@ -74,7 +73,6 @@ export interface ParallelTaskItem {
74
73
  progress?: boolean;
75
74
  skill?: string | string[] | false;
76
75
  model?: string;
77
- acceptance?: AcceptanceInput;
78
76
  }
79
77
 
80
78
  export interface DynamicExpandSpec {
@@ -103,7 +101,6 @@ export interface DynamicParallelStep {
103
101
  failFast?: boolean;
104
102
  phase?: string;
105
103
  label?: string;
106
- acceptance?: AcceptanceInput;
107
104
  }
108
105
 
109
106
  /** Parallel step: multiple agents running concurrently */
@@ -59,7 +59,6 @@ export interface WorkflowGraphNode {
59
59
  itemKey?: string;
60
60
  outputName?: string;
61
61
  structured?: boolean;
62
- acceptanceStatus?: AcceptanceLedgerStatus;
63
62
  error?: string;
64
63
  }
65
64
 
@@ -138,7 +137,7 @@ export interface ControlEvent {
138
137
  nestedRunId?: string;
139
138
  nestingPath?: NestedRunAddress["path"];
140
139
  message: string;
141
- reason?: "idle" | "completion_guard" | "active_long_running" | "tool_failures" | "time_threshold" | "turn_threshold" | "token_threshold";
140
+ reason?: "idle" | "active_long_running" | "tool_failures" | "time_threshold" | "turn_threshold" | "token_threshold";
142
141
  turns?: number;
143
142
  tokens?: number;
144
143
  toolCount?: number;
@@ -247,151 +246,6 @@ export interface ModelAttempt {
247
246
  usage?: Usage;
248
247
  }
249
248
 
250
- export type AcceptanceLevel = "auto" | "none" | "attested" | "checked" | "verified" | "reviewed";
251
-
252
- export type AcceptanceEvidenceKind =
253
- | "changed-files"
254
- | "tests-added"
255
- | "commands-run"
256
- | "validation-output"
257
- | "residual-risks"
258
- | "no-staged-files"
259
- | "diff-summary"
260
- | "review-findings"
261
- | "manual-notes";
262
-
263
- export interface AcceptanceGate {
264
- id: string;
265
- must: string;
266
- evidence?: AcceptanceEvidenceKind[];
267
- severity?: "required" | "recommended";
268
- }
269
-
270
- export interface AcceptanceVerifyCommand {
271
- id: string;
272
- command: string;
273
- timeoutMs?: number;
274
- cwd?: string;
275
- env?: Record<string, string>;
276
- allowFailure?: boolean;
277
- }
278
-
279
- export interface AcceptanceReviewGate {
280
- agent?: string;
281
- focus?: string;
282
- required?: boolean;
283
- }
284
-
285
- export interface AcceptanceConfig {
286
- level?: AcceptanceLevel;
287
- criteria?: Array<string | AcceptanceGate>;
288
- evidence?: AcceptanceEvidenceKind[];
289
- verify?: AcceptanceVerifyCommand[];
290
- review?: AcceptanceReviewGate | false;
291
- stopRules?: string[];
292
- reason?: string;
293
- }
294
-
295
- export type AcceptanceInput = AcceptanceLevel | false | AcceptanceConfig;
296
-
297
- export interface ResolvedAcceptanceGate extends AcceptanceGate {
298
- id: string;
299
- must: string;
300
- evidence: AcceptanceEvidenceKind[];
301
- severity: "required" | "recommended";
302
- }
303
-
304
- export interface ResolvedAcceptanceConfig {
305
- level: Exclude<AcceptanceLevel, "auto">;
306
- explicit: boolean;
307
- inferredReason: string[];
308
- criteria: ResolvedAcceptanceGate[];
309
- evidence: AcceptanceEvidenceKind[];
310
- verify: AcceptanceVerifyCommand[];
311
- review?: AcceptanceReviewGate | false;
312
- stopRules: string[];
313
- reason?: string;
314
- }
315
-
316
- export interface AcceptanceReport {
317
- criteriaSatisfied?: Array<{
318
- id?: string;
319
- status: "satisfied" | "not-satisfied" | "not-applicable";
320
- evidence: string;
321
- }>;
322
- changedFiles?: string[];
323
- testsAddedOrUpdated?: string[];
324
- commandsRun?: Array<{
325
- command: string;
326
- result: "passed" | "failed" | "not-run";
327
- summary: string;
328
- }>;
329
- validationOutput?: string[];
330
- residualRisks?: string[];
331
- noStagedFiles?: boolean;
332
- diffSummary?: string;
333
- reviewFindings?: string[];
334
- manualNotes?: string;
335
- notes?: string;
336
- }
337
-
338
- export type AcceptanceRuntimeCheckStatus = "passed" | "failed" | "not-applicable";
339
-
340
- export interface AcceptanceRuntimeCheck {
341
- id: string;
342
- status: AcceptanceRuntimeCheckStatus;
343
- message: string;
344
- }
345
-
346
- export interface AcceptanceVerifyResult {
347
- id: string;
348
- command: string;
349
- cwd?: string;
350
- exitCode: number | null;
351
- status: "passed" | "failed" | "timed-out" | "allowed-failure";
352
- stdout?: string;
353
- stderr?: string;
354
- durationMs: number;
355
- }
356
-
357
- export interface AcceptanceReviewResult {
358
- status: "no-blockers" | "blockers" | "needs-parent-decision";
359
- findings: Array<{
360
- severity: "blocker" | "non-blocking";
361
- file?: string;
362
- issue: string;
363
- rationale: string;
364
- }>;
365
- }
366
-
367
- export type AcceptanceLedgerStatus =
368
- | "not-required"
369
- | "claimed"
370
- | "attested"
371
- | "checked"
372
- | "verified"
373
- | "reviewed"
374
- | "accepted"
375
- | "rejected";
376
-
377
- export interface AcceptanceLedger {
378
- status: AcceptanceLedgerStatus;
379
- explicit: boolean;
380
- effectiveAcceptance: ResolvedAcceptanceConfig;
381
- inferredReason: string[];
382
- criteria: ResolvedAcceptanceGate[];
383
- childReport?: AcceptanceReport;
384
- childReportParseError?: string;
385
- runtimeChecks: AcceptanceRuntimeCheck[];
386
- verifyRuns: AcceptanceVerifyResult[];
387
- reviewResult?: AcceptanceReviewResult;
388
- parentDecision?: {
389
- status: "accepted" | "rejected";
390
- at: string;
391
- reason?: string;
392
- };
393
- }
394
-
395
249
  export interface SingleResult {
396
250
  agent: string;
397
251
  task: string;
@@ -423,7 +277,6 @@ export interface SingleResult {
423
277
  structuredOutput?: unknown;
424
278
  structuredOutputPath?: string;
425
279
  structuredOutputSchemaPath?: string;
426
- acceptance?: AcceptanceLedger;
427
280
  }
428
281
 
429
282
  export interface Details {
@@ -627,7 +480,6 @@ export interface AsyncStatus {
627
480
  structuredOutput?: unknown;
628
481
  structuredOutputPath?: string;
629
482
  structuredOutputSchemaPath?: string;
630
- acceptance?: AcceptanceLedger;
631
483
  }>;
632
484
  sessionDir?: string;
633
485
  outputFile?: string;
@@ -804,13 +656,6 @@ export interface RunSyncOptions {
804
656
  schemaPath: string;
805
657
  outputPath: string;
806
658
  };
807
- acceptance?: AcceptanceInput;
808
- acceptanceContext?: {
809
- mode?: SubagentRunMode;
810
- async?: boolean;
811
- dynamic?: boolean;
812
- dynamicGroup?: boolean;
813
- };
814
659
  }
815
660
 
816
661
  export type IntercomBridgeMode = "off" | "fork-only" | "always";
@@ -306,7 +306,6 @@ function resultStatusLine(result: Details["results"][number], output: string): s
306
306
  if (result.detached) return result.detachedReason ? `Detached: ${result.detachedReason}` : "Detached";
307
307
  if (result.interrupted) return "Paused";
308
308
  if (result.exitCode !== 0) return `Error: ${result.error ?? (firstOutputLine(output) || `exit ${result.exitCode}`)}`;
309
- if (result.acceptance?.status && result.acceptance.status !== "not-required") return `Done · acceptance: ${result.acceptance.status}`;
310
309
  if (hasEmptyTextOutputWithoutOutputTarget(result.task, output)) return "Done (no text output)";
311
310
  return "Done";
312
311
  }
@@ -6,7 +6,13 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  ### Changed
8
8
 
9
- - Published a synchronized Atomic 0.8.29-alpha.4 prerelease with the upstream pi TUI dependency aligned to `^0.79.3`; no functional changes were made in the web-access extension.
9
+ - Aligned the web-access extension peer dependency with upstream pi TUI `^0.79.4`; no web-access extension code changes were made.
10
+
11
+ ## [0.8.29] - 2026-06-15
12
+
13
+ ### Changed
14
+
15
+ - Published a synchronized Atomic 0.8.29 stable release with the upstream pi TUI dependency aligned to `^0.79.3`; no functional changes were made in the web-access extension.
10
16
 
11
17
  ## [0.8.28] - 2026-06-11
12
18
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/web-access",
3
- "version": "0.8.29-alpha.4",
3
+ "version": "0.8.30-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
6
6
  "contributors": [
@@ -30,7 +30,7 @@
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@bastani/atomic": "*",
33
- "@earendil-works/pi-tui": "^0.79.3"
33
+ "@earendil-works/pi-tui": "^0.79.4"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "@bastani/atomic": {
@@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### Changed
10
+
11
+ - Aligned the workflows extension peer dependency with upstream pi TUI `^0.79.4` so workflow graph, custom UI, and prompt-broker integrations consume the latest shared TUI fixes; no workflows extension code changes were made for this metadata sync.
12
+
13
+ ### Fixed
14
+
15
+ - Fixed workflow stage sessions for workflows loaded through `atomic -e` to build fresh child resource loaders from the parent Atomic resource snapshot, preserving custom extensions/tools, subagents and agent definitions, skills, prompt templates, themes, packages, workflows, trusted borrowed project-local resources, explicit `resourceLoader` overrides, and recursive workflow-extension filtering.
16
+ - Fixed schema-backed workflow stages to send up to three corrective follow-up prompts when a turn finishes without the required `structured_output` call or with an invalid `structured_output` call, echoing the concrete contract/validation error before failing the stage.
17
+ - Fixed failed workflow stages to retain and persist SDK `sessionId`/`sessionFile` metadata, so post-error transcript inspection and follow-up messaging resume from the failed conversation instead of silently creating a fresh empty session.
18
+ - Fixed schema-backed workflow stages with `noTools: "all"` to keep the restrictive allowlist while still exposing the required `structured_output` final-answer tool.
19
+
20
+ ## [0.8.29] - 2026-06-15
21
+
9
22
  ### Added
10
23
 
11
24
  - Added opt-in schema-backed workflow item results: `ctx.stage(..., { schema })`, `ctx.task(..., { schema })`, `ctx.chain` items, and `ctx.parallel` items now receive a schema-specific `structured_output` tool only for that item, return the captured value from `ctx.stage().prompt(...)`, and expose parsed task values as `result.structured` while preserving formatted JSON handoff text ([#1350](https://github.com/bastani-inc/atomic/issues/1350)).
@@ -280,7 +280,7 @@ const decision = await ctx.stage("review-gate", { schema: Decision }).prompt(
280
280
  // decision.approved is typed from the schema.
281
281
  ```
282
282
 
283
- Atomic registers the canonical `structured_output` tool only for schema-enabled items and automatically adds it to explicit `tools` allowlists. The schema is used directly as the tool argument contract. A schema-backed `StageContext` supports one `prompt()` call because the final-answer tool is a single result contract; create another `ctx.stage(..., { schema })` for another structured prompt. `ctx.task`/`ctx.chain`/`ctx.parallel` results expose the captured value as `result.structured` and keep `result.text` as formatted JSON for handoffs.
283
+ Atomic registers the canonical `structured_output` tool only for schema-enabled items and automatically adds it to explicit `tools` allowlists. The schema is used directly as the tool argument contract. A schema-backed `StageContext` supports one `prompt()` call because the final-answer tool is a single result contract; create another `ctx.stage(..., { schema })` for another structured prompt. If a turn completes without calling `structured_output`, or the tool call fails schema validation, Atomic sends up to three corrective follow-up prompts that include the exact contract/validation error before failing the item. `ctx.task`/`ctx.chain`/`ctx.parallel` results expose the captured value as `result.structured` and keep `result.text` as formatted JSON for handoffs.
284
284
 
285
285
  `subagent` is available as a default workflow-stage tool with the same default two-hop nesting budget as main chat: a stage can launch a subagent, and that child can launch one nested subagent before the guard blocks further delegation. `tools` allowlists apply to bundled extension tools as well as built-ins; if a stage sets `tools`, list every tool it should see. Workflow stages can explicitly list `subagent`, `web_search`, `fetch_content`, `intercom`, and other loaded extension tools, while `excludedTools` and `noTools: "all"` still win. Bundled `@bastani/subagents` agent definitions are available to the `subagent` tool in workflow stages, including workflows launched from a subagent child process.
286
286
 
@@ -529,7 +529,7 @@ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` repo
529
529
  - **`renderCall`** — renders a compact workflow call summary in the chat scroll.
530
530
  - **`renderResult`** — renders the result or dispatch banner; live progress continues through the widget and graph viewer. Named workflow runs are background-oriented.
531
531
  - **`transcript`** — path-only by default when a transcript file exists: use `status`, `stages`, or `stage` to identify the stage and its `sessionFile`/`transcriptPath`, quote the exact path without changing platform separators (for example, preserve Windows backslashes), then search that file with `rg`/`grep` for targeted terms and read only small surrounding ranges. Default text results include JSON-escaped `sessionFileJson`/`transcriptPathJson` lines for copy-safe path literals plus a `lazyReadPrompt`, with `entries: not inlined` so transcript bodies and tool outputs stay out of model context. Passing explicit `tail` or `limit` opts into a bounded inline preview for quick context checks. If no transcript path is available, the action falls back to a bounded preview of up to 5 recent entries with a `fallbackNote`. A registered live stage handle is used when one exists, even before live messages arrive; otherwise the action falls back to stored stage snapshots. Snapshot entries are ordered chronologically before `tail`/`limit` is applied, with terminal result/error entries kept after tool entries when timestamps are missing or tied. `includeToolOutput` applies only to inlined snapshot previews or no-path fallback previews; live session transcripts may not expose tool output.
532
- - **`send`** — answers pending primitive/structured stage prompts only when `text`, `response`, or `message` is present; an explicit empty string is a valid answer, while an omitted payload is a no-op. Arbitrary `ctx.ui.custom<T>` widget prompts require the interactive workflow graph and return a clear unsupported message when targeted through `send`. `delivery: "auto"` answers pending prompts first, then resumes paused stages, steers streaming stages, or queues a follow-up.
532
+ - **`send`** — answers pending primitive/structured stage prompts only when `text`, `response`, or `message` is present; an explicit empty string is a valid answer, while an omitted payload is a no-op. Follow-ups to completed or failed stages reuse retained `sessionFile` metadata when available so the conversation resumes from the archived stage transcript instead of starting empty; if no session metadata was retained, the follow-up is refused instead of silently resetting. Arbitrary `ctx.ui.custom<T>` widget prompts require the interactive workflow graph and return a clear unsupported message when targeted through `send`. `delivery: "auto"` answers pending prompts first, then resumes paused stages, steers streaming stages, or queues a follow-up.
533
533
  - **`reload`** — refreshes workflow resources directly in-process instead of queuing a literal `/workflow reload` chat follow-up.
534
534
 
535
535
  ### F2 keyboard shortcut
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/workflows",
3
- "version": "0.8.29-alpha.4",
3
+ "version": "0.8.30-alpha.1",
4
4
  "private": true,
5
5
  "description": "Atomic extension for multi-stage workflow authoring and execution.",
6
6
  "contributors": [
@@ -83,7 +83,7 @@
83
83
  },
84
84
  "peerDependencies": {
85
85
  "@bastani/atomic": "*",
86
- "@earendil-works/pi-tui": "^0.79.3"
86
+ "@earendil-works/pi-tui": "^0.79.4"
87
87
  },
88
88
  "peerDependenciesMeta": {
89
89
  "@bastani/atomic": {
@@ -120,7 +120,12 @@ import {
120
120
  stageMatchesExpandedIdentifier,
121
121
  } from "../shared/expanded-workflow-graph.js";
122
122
  import { topLevelWorkflowRuns } from "../shared/run-visibility.js";
123
- import { WORKFLOW_STAGE_SUBAGENT_GUARD_ENV, getEnvValue, type CreateAgentSessionOptions } from "@bastani/atomic";
123
+ import {
124
+ WORKFLOW_STAGE_SUBAGENT_GUARD_ENV,
125
+ getEnvValue,
126
+ type CreateAgentSessionOptions,
127
+ type DefaultResourceLoaderInheritanceSnapshot,
128
+ } from "@bastani/atomic";
124
129
 
125
130
  export const WORKFLOW_TOOL_DESCRIPTION =
126
131
  "Run named workflows or direct one-off task/tasks/chain workflows; " +
@@ -377,6 +382,8 @@ export interface ExtensionAPI {
377
382
  getWorkflowResources?: () => readonly WorkflowResourceInfo[];
378
383
  /** Refresh package-provided workflow files before rediscovery, when supported by host. */
379
384
  refreshWorkflowResources?: () => Promise<readonly WorkflowResourceInfo[]>;
385
+ /** Return resource-loader options child Atomic workflow stages should inherit. */
386
+ getResourceLoaderInheritanceSnapshot?: () => DefaultResourceLoaderInheritanceSnapshot | undefined;
380
387
  /**
381
388
  * Register a keyboard shortcut.
382
389
  * Present on pi >= 1.x; absent on older runtimes.
@@ -22,7 +22,12 @@
22
22
  */
23
23
 
24
24
  import { basename } from "node:path";
25
- import type { ChatMessageRenderOptions, CreateAgentSessionOptions, PackageSource } from "@bastani/atomic";
25
+ import type {
26
+ ChatMessageRenderOptions,
27
+ CreateAgentSessionOptions,
28
+ DefaultResourceLoaderInheritanceSnapshot,
29
+ PackageSource,
30
+ } from "@bastani/atomic";
26
31
  import type { StageAdapters, StageSessionCreateResult, StageSessionRuntime } from "../runs/foreground/stage-runner.js";
27
32
  import type { StageExecutionMeta, StageOptions } from "../shared/types.js";
28
33
  import { stageUiBroker, type StageUiBroker } from "../shared/stage-ui-broker.js";
@@ -55,6 +60,8 @@ export interface PiExecOpts {
55
60
  export interface RuntimeWiringSurface {
56
61
  exec?: (command: string, args: string[], opts?: PiExecOpts) => Promise<PiExecResult>;
57
62
  ui?: PiUISurface;
63
+ /** Resource-loader inheritance snapshot supplied by Atomic's ExtensionAPI. */
64
+ getResourceLoaderInheritanceSnapshot?: () => DefaultResourceLoaderInheritanceSnapshot | undefined;
58
65
  /** Test seam: inject a stub session factory instead of importing the SDK. */
59
66
  createAgentSession?: (options?: CreateAgentSessionOptions) => Promise<StageSessionCreateResult>;
60
67
  }
@@ -103,13 +110,14 @@ export interface PiCodingAgentSdk {
103
110
  getAgentDir(): string;
104
111
  getBuiltinPackagePaths?: () => string[];
105
112
  SettingsManager: {
106
- create(cwd?: string, agentDir?: string): PiSdkSettingsManager;
113
+ create(cwd?: string, agentDir?: string, options?: { projectTrusted?: boolean }): PiSdkSettingsManager;
107
114
  };
108
115
  DefaultResourceLoader: new (options: {
109
116
  cwd: string;
110
117
  agentDir: string;
111
118
  settingsManager?: PiSdkSettingsManager;
112
119
  builtinPackagePaths?: PackageSource[];
120
+ resourceLoaderInheritanceSnapshot?: DefaultResourceLoaderInheritanceSnapshot;
113
121
  }) => PiSdkResourceLoader;
114
122
  createAgentSession(options?: AtomicCreateAgentSessionOptions): Promise<{ session: StageSessionRuntime }>;
115
123
  }
@@ -119,6 +127,10 @@ type AtomicCreateAgentSessionOptions = Omit<CreateAgentSessionOptions, "settings
119
127
  sessionManager?: PiSdkSessionManager;
120
128
  };
121
129
 
130
+ export interface PrepareAtomicStageSessionOptions {
131
+ resourceLoaderInheritanceSnapshot?: DefaultResourceLoaderInheritanceSnapshot;
132
+ }
133
+
122
134
  function resolveSessionCwd(options: AtomicCreateAgentSessionOptions | undefined): string {
123
135
  return options?.cwd ?? options?.sessionManager?.getCwd() ?? process.cwd();
124
136
  }
@@ -141,20 +153,33 @@ function resolveSessionCwd(options: AtomicCreateAgentSessionOptions | undefined)
141
153
  export async function prepareAtomicStageSessionOptions(
142
154
  options: CreateAgentSessionOptions | undefined,
143
155
  sdk: PiCodingAgentSdk,
156
+ prepareOptions: PrepareAtomicStageSessionOptions = {},
144
157
  ): Promise<AtomicCreateAgentSessionOptions | undefined> {
145
158
  const atomicOptions = options as AtomicCreateAgentSessionOptions | undefined;
146
159
  if (atomicOptions?.resourceLoader !== undefined) return atomicOptions;
147
160
 
161
+ const inheritanceSnapshot = prepareOptions.resourceLoaderInheritanceSnapshot;
148
162
  const cwd = resolveSessionCwd(atomicOptions);
149
163
  const hasAgentDirOverride = atomicOptions?.agentDir !== undefined;
150
164
  const agentDir = atomicOptions?.agentDir ?? sdk.getAgentDir();
151
165
  const settingsManager =
152
- atomicOptions?.settingsManager ?? sdk.SettingsManager.create(cwd, agentDir);
166
+ atomicOptions?.settingsManager ?? sdk.SettingsManager.create(
167
+ cwd,
168
+ agentDir,
169
+ inheritanceSnapshot?.projectTrusted === undefined
170
+ ? undefined
171
+ : { projectTrusted: inheritanceSnapshot.projectTrusted },
172
+ );
173
+ const inheritedBuiltinPackagePaths = inheritanceSnapshot?.builtinPackagePaths;
174
+ const builtinPackagePaths = inheritedBuiltinPackagePaths === undefined
175
+ ? sdk.getBuiltinPackagePaths?.() ?? []
176
+ : [...inheritedBuiltinPackagePaths];
153
177
  const resourceLoader = new sdk.DefaultResourceLoader({
154
178
  cwd,
155
179
  agentDir,
156
180
  settingsManager,
157
- builtinPackagePaths: stageBuiltinPackagePaths(sdk.getBuiltinPackagePaths?.() ?? []),
181
+ resourceLoaderInheritanceSnapshot: inheritanceSnapshot,
182
+ builtinPackagePaths: stageBuiltinPackagePaths(builtinPackagePaths),
158
183
  });
159
184
  await reloadWorkflowStageResources(resourceLoader);
160
185
 
@@ -167,15 +192,39 @@ export async function prepareAtomicStageSessionOptions(
167
192
  };
168
193
  }
169
194
 
170
- function stageBuiltinPackagePaths(paths: readonly string[]): PackageSource[] {
195
+ function clonePackageSource(source: PackageSource): PackageSource {
196
+ if (typeof source === "string") return source;
197
+ return {
198
+ source: source.source,
199
+ ...(source.extensions === undefined ? {} : { extensions: [...source.extensions] }),
200
+ ...(source.skills === undefined ? {} : { skills: [...source.skills] }),
201
+ ...(source.prompts === undefined ? {} : { prompts: [...source.prompts] }),
202
+ ...(source.themes === undefined ? {} : { themes: [...source.themes] }),
203
+ ...(source.workflows === undefined ? {} : { workflows: [...source.workflows] }),
204
+ };
205
+ }
206
+
207
+ function packageSourcePath(source: PackageSource): string {
208
+ return typeof source === "string" ? source : source.source;
209
+ }
210
+
211
+ function disablePackageExtensions(source: PackageSource): PackageSource {
212
+ if (typeof source === "string") return { source, extensions: [] };
213
+ return { ...source, extensions: [] };
214
+ }
215
+
216
+ function stageBuiltinPackagePaths(paths: readonly PackageSource[]): PackageSource[] {
171
217
  // Workflow stages are child AgentSessions owned by the workflow extension.
172
218
  // Loading the workflows extension again inside that child session replays its
173
219
  // `session_start` lifecycle and clears/kills the parent workflow store. Keep
174
220
  // the workflows package itself so its bundled skills/prompts/resources remain
175
221
  // available, but disable only its extension entry for stage sessions.
176
- return paths.map((path) =>
177
- basename(path) === "workflows" ? { source: path, extensions: [] } : path,
178
- );
222
+ return paths.map((path) => {
223
+ const cloned = clonePackageSource(path);
224
+ return basename(packageSourcePath(cloned)) === "workflows"
225
+ ? disablePackageExtensions(cloned)
226
+ : cloned;
227
+ });
179
228
  }
180
229
 
181
230
  const SUBAGENT_CHILD_EXTENSION_ENV_KEYS = [
@@ -225,9 +274,10 @@ async function reloadWorkflowStageResourcesWithEnvIsolation(resourceLoader: PiSd
225
274
 
226
275
  async function createPiSdkAgentSession(
227
276
  options?: CreateAgentSessionOptions,
277
+ prepareOptions?: PrepareAtomicStageSessionOptions,
228
278
  ): Promise<StageSessionCreateResult> {
229
279
  const sdk = await import("@bastani/atomic") as PiCodingAgentSdk;
230
- const sessionOptions = await prepareAtomicStageSessionOptions(options, sdk);
280
+ const sessionOptions = await prepareAtomicStageSessionOptions(options, sdk, prepareOptions);
231
281
  const result = await sdk.createAgentSession(sessionOptions);
232
282
  // `CreateAgentSessionResult` is `{ session, extensionsResult, modelFallbackMessage? }`;
233
283
  // workflow stages only consume `.session` (structurally an `AgentSession`,
@@ -275,6 +325,7 @@ async function createTestAgentSession(_options?: CreateAgentSessionOptions): Pro
275
325
  async compact(): ReturnType<StageSessionRuntime["compact"]> {
276
326
  return {
277
327
  promptVersion: 1,
328
+ parameters: { compression_ratio: 0.5, preserve_recent: 2, query: "auto-detected" },
278
329
  deletedTargets: [],
279
330
  protectedEntryIds: [],
280
331
  stats: {
@@ -419,7 +470,12 @@ export function buildRuntimeAdapters(
419
470
  const createSession =
420
471
  options.createAgentSession ??
421
472
  pi.createAgentSession ??
422
- (isTestContext() ? createTestAgentSession : createPiSdkAgentSession);
473
+ (isTestContext()
474
+ ? createTestAgentSession
475
+ : (sessionOptions?: CreateAgentSessionOptions) =>
476
+ createPiSdkAgentSession(sessionOptions, {
477
+ resourceLoaderInheritanceSnapshot: pi.getResourceLoaderInheritanceSnapshot?.(),
478
+ }));
423
479
  const broker = options.stageUiBroker ?? stageUiBroker;
424
480
  const adapters: StageAdapters = {
425
481
  agentSession: {