salmon-loop 0.2.13 → 0.3.0

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 (224) hide show
  1. package/dist/cli/argv/headless-detection.js +27 -0
  2. package/dist/cli/chat-flow.js +11 -0
  3. package/dist/cli/chat.js +160 -24
  4. package/dist/cli/commands/chat.js +14 -7
  5. package/dist/cli/commands/flow-mode.js +63 -0
  6. package/dist/cli/commands/registry.js +2 -0
  7. package/dist/cli/commands/run/benchmark-artifacts.js +41 -0
  8. package/dist/cli/commands/run/early-errors.js +23 -0
  9. package/dist/cli/commands/run/handler.js +115 -27
  10. package/dist/cli/commands/run/headless-error-writer.js +8 -0
  11. package/dist/cli/commands/run/loop-params.js +2 -0
  12. package/dist/cli/commands/run/mode.js +2 -5
  13. package/dist/cli/commands/run/parse-options.js +16 -0
  14. package/dist/cli/commands/run/persist-session.js +10 -1
  15. package/dist/cli/commands/run/preflight.js +10 -0
  16. package/dist/cli/commands/run/reporter-factory.js +4 -0
  17. package/dist/cli/commands/run/runtime-llm.js +38 -11
  18. package/dist/cli/commands/run/runtime-options.js +2 -2
  19. package/dist/cli/commands/serve.js +97 -77
  20. package/dist/cli/commands/tool-names.js +78 -78
  21. package/dist/cli/headless/anthropic-stream-normalized-encoder.js +6 -1
  22. package/dist/cli/headless/json-protocol.js +37 -0
  23. package/dist/cli/headless/native-stream-normalized-encoder.js +6 -1
  24. package/dist/cli/headless/protocol-metadata.js +22 -0
  25. package/dist/cli/headless/stream-json-protocol.js +34 -1
  26. package/dist/cli/index.js +6 -4
  27. package/dist/cli/locales/en.js +30 -6
  28. package/dist/cli/program-bootstrap.js +10 -5
  29. package/dist/cli/program-commands.js +5 -1
  30. package/dist/cli/reporters/anthropic-stream.js +7 -1
  31. package/dist/cli/reporters/json.js +4 -0
  32. package/dist/cli/reporters/stream-json.js +17 -2
  33. package/dist/cli/run-cli.js +5 -3
  34. package/dist/cli/slash/runtime.js +27 -12
  35. package/dist/cli/ui/components/CommandInput.js +7 -3
  36. package/dist/cli/ui/components/CommandSuggestionList.js +1 -1
  37. package/dist/cli/utils/command-option-source.js +13 -0
  38. package/dist/cli/utils/verify-resolver.js +8 -4
  39. package/dist/cli/utils/worktree-prepare-resolver.js +7 -3
  40. package/dist/core/adapters/fs/file-adapter.js +6 -0
  41. package/dist/core/adapters/fs/filesystem.js +2 -1
  42. package/dist/core/adapters/git/git-adapter.js +78 -1
  43. package/dist/core/backends/salmon-loop/task-executor.js +1 -0
  44. package/dist/core/benchmark/patch-artifact.js +124 -0
  45. package/dist/core/benchmark/swe-bench.js +25 -0
  46. package/dist/core/config/load.js +18 -11
  47. package/dist/core/config/resolve-llm.js +12 -0
  48. package/dist/core/config/resolvers/server.js +0 -6
  49. package/dist/core/config/validate.js +73 -21
  50. package/dist/core/context/gatherers/metadata-gatherer.js +1 -0
  51. package/dist/core/context/gatherers/ripgrep-gatherer.js +84 -2
  52. package/dist/core/context/keywords.js +18 -4
  53. package/dist/core/context/service-deps.js +2 -2
  54. package/dist/core/context/service.js +8 -0
  55. package/dist/core/context/steps/context-gather.js +38 -0
  56. package/dist/core/context/summarization/summarizer.js +55 -12
  57. package/dist/core/context/targeting/target-resolver.js +4 -4
  58. package/dist/core/extensions/index.js +23 -5
  59. package/dist/core/extensions/merge.js +14 -0
  60. package/dist/core/extensions/paths.js +31 -0
  61. package/dist/core/extensions/schemas.js +8 -5
  62. package/dist/core/facades/cli-chat.js +6 -2
  63. package/dist/core/facades/cli-command-chat.js +1 -0
  64. package/dist/core/facades/cli-command-tool-names.js +2 -0
  65. package/dist/core/facades/cli-observability.js +1 -1
  66. package/dist/core/facades/cli-program-bootstrap.js +1 -0
  67. package/dist/core/facades/cli-run-handler.js +4 -2
  68. package/dist/core/facades/cli-run-persist-session.js +1 -0
  69. package/dist/core/facades/cli-serve.js +4 -4
  70. package/dist/core/facades/cli-utils-worktree.js +1 -1
  71. package/dist/core/failure/diagnostics.js +53 -1
  72. package/dist/core/grizzco/dsl/llm-strategy.js +4 -1
  73. package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +67 -9
  74. package/dist/core/grizzco/engine/pipeline/pipeline.js +6 -2
  75. package/dist/core/grizzco/engine/transaction/attempt-failure.js +90 -15
  76. package/dist/core/grizzco/engine/transaction/report-mapper.js +17 -3
  77. package/dist/core/grizzco/engine/transaction/transaction-runner.js +165 -7
  78. package/dist/core/grizzco/flows/AutopilotFlow.js +18 -0
  79. package/dist/core/grizzco/flows/flow-dispatch.js +11 -0
  80. package/dist/core/grizzco/steps/answer.js +13 -14
  81. package/dist/core/grizzco/steps/autopilot.js +396 -0
  82. package/dist/core/grizzco/steps/cache-sharing.js +29 -0
  83. package/dist/core/grizzco/steps/explore.js +37 -21
  84. package/dist/core/grizzco/steps/generateReview.js +2 -5
  85. package/dist/core/grizzco/steps/patch/apply-check.js +10 -0
  86. package/dist/core/grizzco/steps/patch/diff-normalization.js +70 -0
  87. package/dist/core/grizzco/steps/patch/diff-salvage.js +46 -0
  88. package/dist/core/grizzco/steps/patch/prompt-input.js +42 -0
  89. package/dist/core/grizzco/steps/patch.js +105 -146
  90. package/dist/core/grizzco/steps/plan.js +101 -25
  91. package/dist/core/grizzco/steps/preflight.js +5 -6
  92. package/dist/core/grizzco/steps/request-assembly.js +78 -0
  93. package/dist/core/grizzco/steps/research.js +39 -36
  94. package/dist/core/grizzco/steps/tool-runtime.js +47 -0
  95. package/dist/core/grizzco/steps/verify-shared.js +23 -0
  96. package/dist/core/grizzco/steps/verify.js +13 -21
  97. package/dist/core/interaction/orchestration/facade.js +1 -1
  98. package/dist/core/llm/ai-sdk/chat-executor.js +2 -0
  99. package/dist/core/llm/ai-sdk/high-level-phase-specs.js +63 -0
  100. package/dist/core/llm/ai-sdk/message-mapper.js +40 -10
  101. package/dist/core/llm/ai-sdk/provider-factory.js +14 -0
  102. package/dist/core/llm/ai-sdk/request-params.js +113 -1
  103. package/dist/core/llm/ai-sdk/result-mapper.js +16 -0
  104. package/dist/core/llm/ai-sdk.js +112 -27
  105. package/dist/core/llm/capabilities.js +12 -0
  106. package/dist/core/llm/contracts/repair.js +36 -30
  107. package/dist/core/llm/errors.js +83 -2
  108. package/dist/core/llm/message-composition.js +7 -22
  109. package/dist/core/llm/phase-router.js +29 -10
  110. package/dist/core/llm/redact.js +28 -3
  111. package/dist/core/llm/registry.js +2 -0
  112. package/dist/core/llm/request-augmentation.js +55 -0
  113. package/dist/core/llm/request-envelope.js +334 -0
  114. package/dist/core/llm/shared-request-assembly.js +35 -0
  115. package/dist/core/llm/stream-utils.js +13 -4
  116. package/dist/core/llm/utils.js +18 -29
  117. package/dist/core/memory/relevant-retrieval.js +144 -0
  118. package/dist/core/observability/logger.js +11 -2
  119. package/dist/core/patch/diff.js +1 -0
  120. package/dist/core/prompts/registry.js +39 -2
  121. package/dist/core/prompts/runtime.js +50 -12
  122. package/dist/core/prompts/templates/phases/patch_user.hbs +2 -5
  123. package/dist/core/prompts/templates/phases/research_user.hbs +11 -0
  124. package/dist/core/prompts/templates/phases/review_user.hbs +3 -0
  125. package/dist/core/prompts/templates/system/answer_system.hbs +5 -0
  126. package/dist/core/prompts/templates/system/autopilot_system.hbs +11 -0
  127. package/dist/core/prompts/templates/system/explore_system.hbs +14 -23
  128. package/dist/core/prompts/templates/system/main_system.hbs +4 -16
  129. package/dist/core/prompts/templates/system/patch_system.hbs +39 -8
  130. package/dist/core/prompts/templates/system/plan_system.hbs +86 -1
  131. package/dist/core/prompts/templates/system/research_system.hbs +2 -0
  132. package/dist/core/protocols/a2a/agent-card.js +5 -3
  133. package/dist/core/protocols/a2a/sdk/executor.js +2 -1
  134. package/dist/core/protocols/a2a/sdk/server.js +0 -1
  135. package/dist/core/protocols/acp/formal-agent.js +300 -58
  136. package/dist/core/protocols/acp/handlers.js +5 -1
  137. package/dist/core/protocols/acp/permission-provider.js +1 -1
  138. package/dist/core/protocols/shared/flow-mode-mapping.js +23 -0
  139. package/dist/core/public-capabilities/flow-mode-metadata.js +39 -0
  140. package/dist/core/public-capabilities/projections.js +29 -0
  141. package/dist/core/public-capabilities/registry.js +26 -0
  142. package/dist/core/public-capabilities/types.js +2 -0
  143. package/dist/core/runtime/agent-server-runtime.js +47 -43
  144. package/dist/core/runtime/execution-profile.js +67 -0
  145. package/dist/core/session/artifact-state.js +160 -0
  146. package/dist/core/session/compaction/index.js +183 -0
  147. package/dist/core/session/compaction/microcompact.js +78 -0
  148. package/dist/core/session/compaction/tracking.js +48 -0
  149. package/dist/core/session/compaction/types.js +11 -0
  150. package/dist/core/session/compression.js +8 -0
  151. package/dist/core/session/manager.js +244 -8
  152. package/dist/core/session/pruning-strategy.js +55 -9
  153. package/dist/core/session/replacement-preview-provider.js +24 -0
  154. package/dist/core/session/replacement-state.js +131 -0
  155. package/dist/core/session/resume-repair/pipeline.js +79 -0
  156. package/dist/core/session/resume-repair/stages/load-raw-archive-state.js +40 -0
  157. package/dist/core/session/resume-repair/stages/reattach-runtime-state.js +8 -0
  158. package/dist/core/session/resume-repair/stages/recover-orphaned-branches.js +10 -0
  159. package/dist/core/session/resume-repair/stages/relink-boundary-and-tail.js +36 -0
  160. package/dist/core/session/resume-repair/stages/replay-startup-hooks.js +23 -0
  161. package/dist/core/session/resume-repair/stages/rescue-stale-metadata.js +17 -0
  162. package/dist/core/session/resume-repair/types.js +2 -0
  163. package/dist/core/session/summary-sync.js +164 -13
  164. package/dist/core/session/token-tracker.js +6 -0
  165. package/dist/core/skills/audit.js +34 -0
  166. package/dist/core/skills/bridge.js +84 -7
  167. package/dist/core/skills/discovery.js +94 -0
  168. package/dist/core/skills/feature-flags.js +52 -0
  169. package/dist/core/skills/index.js +1 -1
  170. package/dist/core/skills/loader.js +195 -20
  171. package/dist/core/skills/parser.js +296 -24
  172. package/dist/core/skills/permissions.js +117 -0
  173. package/dist/core/skills/runtime/MicroTaskRunner.js +10 -4
  174. package/dist/core/skills/runtime/SkillRunner.js +240 -61
  175. package/dist/core/strata/layers/shadow-driver/shadow-driver.js +37 -7
  176. package/dist/core/strata/layers/worktree.js +67 -10
  177. package/dist/core/strata/runtime/synchronizer.js +29 -2
  178. package/dist/core/streaming/stream-assembler.js +75 -31
  179. package/dist/core/sub-agent/context-snapshot.js +156 -0
  180. package/dist/core/sub-agent/core/loop.js +1 -1
  181. package/dist/core/sub-agent/core/manager.js +119 -20
  182. package/dist/core/sub-agent/dispatch-policy.js +29 -0
  183. package/dist/core/sub-agent/prefix-consistency.js +48 -0
  184. package/dist/core/sub-agent/registry-defaults.js +4 -0
  185. package/dist/core/sub-agent/tools/task-spawn.js +79 -2
  186. package/dist/core/sub-agent/types.js +134 -5
  187. package/dist/core/tools/audit.js +13 -4
  188. package/dist/core/tools/builtin/ast-grep.js +1 -1
  189. package/dist/core/tools/builtin/ast.js +1 -1
  190. package/dist/core/tools/builtin/benchmark.js +360 -0
  191. package/dist/core/tools/builtin/code-search/backends/rg.js +2 -1
  192. package/dist/core/tools/builtin/code-search/executor.js +6 -1
  193. package/dist/core/tools/builtin/code-search/spec.js +26 -2
  194. package/dist/core/tools/builtin/fs.js +256 -23
  195. package/dist/core/tools/builtin/git.js +2 -2
  196. package/dist/core/tools/builtin/index.js +51 -2
  197. package/dist/core/tools/builtin/interaction.js +8 -1
  198. package/dist/core/tools/builtin/plan.js +37 -15
  199. package/dist/core/tools/builtin/shell.js +1 -1
  200. package/dist/core/tools/loader.js +39 -16
  201. package/dist/core/tools/mapper.js +17 -3
  202. package/dist/core/tools/mcp/client.js +2 -1
  203. package/dist/core/tools/parallel/scheduler.js +35 -4
  204. package/dist/core/tools/permissions/permission-rules.js +5 -10
  205. package/dist/core/tools/policy.js +6 -1
  206. package/dist/core/tools/recoverable-tool-errors.js +10 -0
  207. package/dist/core/tools/router.js +24 -6
  208. package/dist/core/tools/session.js +458 -48
  209. package/dist/core/tools/tool-visibility.js +62 -0
  210. package/dist/core/tools/types.js +9 -1
  211. package/dist/core/types/execution.js +4 -0
  212. package/dist/core/types/flow-mode.js +8 -0
  213. package/dist/core/utils/path.js +52 -0
  214. package/dist/core/verification/runner.js +4 -1
  215. package/dist/core/version.js +17 -0
  216. package/dist/languages/typescript/index.js +4 -1
  217. package/dist/locales/en.js +35 -2
  218. package/dist/utils/eol.js +1 -1
  219. package/package.json +14 -7
  220. package/scripts/fix-es-abstract-compat.js +77 -0
  221. package/dist/core/runtime/fastify-server-bundle.js +0 -26
  222. package/dist/core/runtime/sidecar-fastify-plugin.js +0 -35
  223. package/dist/core/runtime/sidecar-paths.js +0 -47
  224. package/dist/core/runtime/sidecar-route-catalog.js +0 -103
@@ -1,9 +1,12 @@
1
+ import { resolveLlmCapabilities } from '../../llm/capabilities.js';
1
2
  import { Phase } from '../../types/runtime.js';
2
3
  import { DecisionEngine, PlanBuilder } from './DecisionEngine.js';
3
4
  function defaultMaxRoundsForPhase(phase) {
4
5
  // Explore needs more rounds to navigate the codebase
5
6
  if (phase === Phase.EXPLORE)
6
7
  return 8;
8
+ if (phase === Phase.AUTOPILOT)
9
+ return 8;
7
10
  if (phase === Phase.RESEARCH)
8
11
  return 8;
9
12
  if (phase === Phase.PLAN)
@@ -13,7 +16,7 @@ function defaultMaxRoundsForPhase(phase) {
13
16
  return 4;
14
17
  }
15
18
  export function resolveLlmToolCallingPolicy(phase, llm) {
16
- const caps = llm.getCapabilities?.();
19
+ const caps = resolveLlmCapabilities(llm, phase);
17
20
  const maxRounds = defaultMaxRoundsForPhase(phase);
18
21
  // Grizzco DSL engine is transaction-shaped; for LLM policies we inject a minimal context and keep all
19
22
  // decisions inside ctx.data to avoid coupling to file/operation semantics.
@@ -3,8 +3,35 @@ import { getBudgetRunSummary } from '../../../context/budget/integration.js';
3
3
  import { getAuthorizationDecisionsFromAuditTrail } from '../../../observability/authorization-decisions.js';
4
4
  import { buildFailureEnvelope } from '../../../observability/error-envelope.js';
5
5
  import { getTokenUsageFromAuditTrail } from '../../../observability/token-usage.js';
6
+ import { resolveExecutionProfile } from '../../../runtime/execution-profile.js';
6
7
  import { ErrorType, Phase } from '../../../types/runtime.js';
8
+ const ROOT_CAUSE_CODES = [
9
+ 'LLM_RATE_LIMITED',
10
+ 'LLM_UPSTREAM_5XX',
11
+ 'LLM_NETWORK_UNREACHABLE',
12
+ 'LLM_REQUEST_TIMEOUT',
13
+ 'PLAN_OUTPUT_NOT_JSON',
14
+ 'PLAN_SCHEMA_INVALID',
15
+ 'STDOUT_CONTRACT_VIOLATION',
16
+ 'RESOURCE_LIMIT_CONFIRMED',
17
+ ];
18
+ function toRootCauseCode(code) {
19
+ if (typeof code !== 'string')
20
+ return undefined;
21
+ return ROOT_CAUSE_CODES.includes(code)
22
+ ? code
23
+ : undefined;
24
+ }
7
25
  export function buildLoopResultFromTransaction({ executionReport, flowMode, options, telemetry, auditPath, }) {
26
+ const profile = resolveExecutionProfile(flowMode);
27
+ const rootCause = toRootCauseCode(executionReport.lastErrorCode);
28
+ const terminalReason = executionReport.retryExhausted
29
+ ? 'RETRY_BUDGET_EXHAUSTED'
30
+ : executionReport.terminalReasonCode === 'AWAITING_INPUT'
31
+ ? undefined
32
+ : executionReport.success
33
+ ? undefined
34
+ : 'NON_RETRYABLE_FAILURE';
8
35
  const ctx = executionReport.lastContext ??
9
36
  executionReport.flowReport.data;
10
37
  const contextHash = (() => {
@@ -19,11 +46,35 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
19
46
  const verifyArtifact = ctx && typeof ctx === 'object' && 'verifyArtifact' in ctx
20
47
  ? ctx.verifyArtifact
21
48
  : executionReport.lastVerifyArtifact;
22
- const assistantMessage = flowMode === 'answer'
23
- ? ctx?.report?.summary?.trim?.()
24
- ? String(ctx.report.summary).trim()
25
- : ''
26
- : undefined;
49
+ const artifactHints = (() => {
50
+ const hints = {
51
+ verifyArtifact,
52
+ subAgentPatchArtifacts: executionReport.lastSubAgentPatchArtifacts?.length
53
+ ? executionReport.lastSubAgentPatchArtifacts
54
+ : undefined,
55
+ subAgentAuditArtifacts: executionReport.lastSubAgentAuditArtifacts?.length
56
+ ? executionReport.lastSubAgentAuditArtifacts
57
+ : undefined,
58
+ recentReadArtifacts: executionReport.lastRecentReadArtifacts?.length
59
+ ? executionReport.lastRecentReadArtifacts
60
+ : undefined,
61
+ toolResultPreviewArtifacts: executionReport.lastToolResultPreviewArtifacts?.length
62
+ ? executionReport.lastToolResultPreviewArtifacts
63
+ : undefined,
64
+ };
65
+ if (!hints.verifyArtifact &&
66
+ !hints.subAgentPatchArtifacts &&
67
+ !hints.subAgentAuditArtifacts &&
68
+ !hints.recentReadArtifacts &&
69
+ !hints.toolResultPreviewArtifacts) {
70
+ return undefined;
71
+ }
72
+ return hints;
73
+ })();
74
+ const assistantMessage = ((flowMode === 'answer' || profile.driver === 'agent') &&
75
+ ctx?.report?.summary?.trim?.()
76
+ ? String(ctx.report.summary).trim()
77
+ : undefined) ?? undefined;
27
78
  const finalPatch = ctx && typeof ctx === 'object' && 'diff' in ctx ? ctx.diff : undefined;
28
79
  const changedFiles = ctx && typeof ctx === 'object' && 'changedFiles' in ctx ? ctx.changedFiles : undefined;
29
80
  const authorizationDecisions = (() => {
@@ -36,14 +87,12 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
36
87
  const attempts = executionReport.attempts;
37
88
  const usage = getTokenUsageFromAuditTrail() ?? undefined;
38
89
  const budgetSummary = getBudgetRunSummary() ?? undefined;
39
- if (options.dryRun ||
40
- flowMode === 'review' ||
41
- flowMode === 'research' ||
42
- flowMode === 'answer') {
90
+ if (options.dryRun || profile.readOnly) {
43
91
  return {
44
92
  success: true,
45
93
  reason: text.loop.operationCompleted,
46
94
  reasonCode: options.dryRun ? 'DRY_RUN' : 'SUCCESS',
95
+ terminalReason,
47
96
  attempts,
48
97
  contextHash,
49
98
  logs: telemetry.getLogs(),
@@ -55,6 +104,7 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
55
104
  assistantMessage,
56
105
  auditPath,
57
106
  verifyArtifact,
107
+ artifactHints,
58
108
  authorizationSummary: executionReport.authorizationSummary || undefined,
59
109
  strategyName: executionReport.flowReport.strategyName ?? flowMode,
60
110
  fsMode: executionReport.flowReport.fsMode ?? flowMode,
@@ -65,6 +115,7 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
65
115
  success: true,
66
116
  reason: text.loop.operationCompleted,
67
117
  reasonCode: 'SUCCESS',
118
+ terminalReason,
68
119
  attempts,
69
120
  contextHash,
70
121
  logs: telemetry.getLogs(),
@@ -76,6 +127,7 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
76
127
  assistantMessage,
77
128
  auditPath,
78
129
  verifyArtifact,
130
+ artifactHints,
79
131
  authorizationSummary: executionReport.authorizationSummary || undefined,
80
132
  strategyName: executionReport.flowReport.strategyName ?? flowMode,
81
133
  fsMode: executionReport.flowReport.fsMode ?? flowMode,
@@ -107,6 +159,8 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
107
159
  success: false,
108
160
  reason: safeHint,
109
161
  reasonCode,
162
+ terminalReason,
163
+ rootCause,
110
164
  diagnosticCode: executionReport.terminalDiagnosticCode ?? reasonCode,
111
165
  safeHint,
112
166
  remediationSteps,
@@ -122,6 +176,7 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
122
176
  errorCode: executionReport.lastErrorCode,
123
177
  auditPath,
124
178
  verifyArtifact,
179
+ artifactHints,
125
180
  authorizationSummary: executionReport.authorizationSummary || undefined,
126
181
  strategyName: executionReport.flowReport.strategyName ?? flowMode,
127
182
  fsMode: executionReport.flowReport.fsMode ?? flowMode,
@@ -138,6 +193,7 @@ export function buildLoopFailureResult({ message, flowMode, telemetry, auditPath
138
193
  const decisions = getAuthorizationDecisionsFromAuditTrail();
139
194
  return decisions.length > 0 ? decisions : undefined;
140
195
  })();
196
+ const rootCause = toRootCauseCode(errorCode);
141
197
  const errorEnvelope = buildFailureEnvelope({
142
198
  phase: failurePhase,
143
199
  fallbackMessage: message,
@@ -146,6 +202,8 @@ export function buildLoopFailureResult({ message, flowMode, telemetry, auditPath
146
202
  success: false,
147
203
  reason: message,
148
204
  reasonCode,
205
+ terminalReason: 'NON_RETRYABLE_FAILURE',
206
+ rootCause,
149
207
  diagnosticCode: reasonCode,
150
208
  safeHint: message,
151
209
  remediationSteps: [],
@@ -300,19 +300,23 @@ export class Pipeline {
300
300
  async execute() {
301
301
  try {
302
302
  const data = await this.promise;
303
+ const lastExecutedStep = [...this.traces].reverse().find((trace) => !trace.name.endsWith(':recovery'))?.name ??
304
+ this.lastStepName;
303
305
  return {
304
306
  success: true,
305
307
  duration: Date.now() - this.startTime,
306
- lastStep: this.lastStepName,
308
+ lastStep: lastExecutedStep,
307
309
  data,
308
310
  traces: this.traces,
309
311
  };
310
312
  }
311
313
  catch (error) {
314
+ const lastExecutedStep = [...this.traces].reverse().find((trace) => !trace.name.endsWith(':recovery'))?.name ??
315
+ this.lastStepName;
312
316
  return {
313
317
  success: false,
314
318
  error: error instanceof Error ? error : new Error(String(error)),
315
- lastStep: this.lastStepName,
319
+ lastStep: lastExecutedStep,
316
320
  duration: Date.now() - this.startTime,
317
321
  data: this.ctxRef.current,
318
322
  traces: this.traces,
@@ -2,6 +2,8 @@ import { text } from '../../../../locales/index.js';
2
2
  import { buildFailureGuidance } from '../../../failure/diagnostics.js';
3
3
  import { sanitizeError } from '../../../llm/errors.js';
4
4
  import { mapErrorForDisplay } from '../../../observability/error-mapping.js';
5
+ import { resolveExecutionProfile } from '../../../runtime/execution-profile.js';
6
+ import { isRecoverableToolInputErrorCode } from '../../../tools/recoverable-tool-errors.js';
5
7
  import { EXECUTION_PHASES } from '../../../types/runtime.js';
6
8
  import { classifyError, isRetryable } from '../../../verification/runner.js';
7
9
  const RETRYABLE_PHASES = new Set([
@@ -19,6 +21,7 @@ const NON_RETRYABLE_PERMISSION_CODES = new Set([
19
21
  'PERMISSION_REQUIRED_CONTEXT_CACHE_OUTSIDE_ROOT',
20
22
  'PERMISSION_DENIED_CONTEXT_CACHE_OUTSIDE_ROOT',
21
23
  ]);
24
+ const NON_RETRYABLE_LLM_CODES = new Set(['LLM_AUTHENTICATION_FAILED']);
22
25
  function inferFailurePhase(flowReport) {
23
26
  const failedTrace = [...flowReport.traces].reverse().find((trace) => Boolean(trace.error));
24
27
  if (failedTrace && EXECUTION_PHASES.includes(failedTrace.name)) {
@@ -67,6 +70,7 @@ function extractInterrupt(error) {
67
70
  }
68
71
  export function resolveAttemptFailure(params) {
69
72
  const { flowReport, context, flowMode } = params;
73
+ const profile = resolveExecutionProfile(flowMode);
70
74
  const interrupt = extractInterrupt(flowReport.error);
71
75
  const interruptCode = extractErrorCode(flowReport.error);
72
76
  if (interruptCode === 'INTERRUPT_REQUIRED' && interrupt?.type === 'awaiting_input') {
@@ -87,23 +91,19 @@ export function resolveAttemptFailure(params) {
87
91
  inputRequired,
88
92
  };
89
93
  }
90
- const verifyOk = flowMode === 'review' || flowMode === 'research' || flowMode === 'answer'
91
- ? true
92
- : context?.verifyResult?.ok !== false;
93
- const applyBackFailed = flowMode !== 'review' &&
94
- flowMode !== 'research' &&
95
- flowMode !== 'answer' &&
96
- context?.applyBackResult?.success === false &&
97
- !context.applyBackResult.skipped;
94
+ const autopilotCompletion = flowMode === 'autopilot' && context && 'completion' in context ? context.completion : undefined;
95
+ const verifyOk = profile.verifyPolicy === 'never' ? true : context?.verifyResult?.ok !== false;
96
+ const applyBackResult = context && 'applyBackResult' in context ? context.applyBackResult : undefined;
97
+ const applyBackFailed = profile.failurePolicy === 'rollback' &&
98
+ applyBackResult?.success === false &&
99
+ !applyBackResult.skipped;
98
100
  const environmentMode = context?.options?.environmentMode;
99
101
  if (applyBackFailed) {
100
- const fallbackReason = context.applyBackResult?.safeMessage ||
101
- context.applyBackResult?.error ||
102
- text.loop.applyBackFailed;
102
+ const fallbackReason = applyBackResult?.safeMessage || applyBackResult?.error || text.loop.applyBackFailed;
103
103
  const guidance = buildFailureGuidance({
104
104
  reasonCode: 'APPLY_BACK_FAILED',
105
105
  failurePhase: 'APPLY_BACK',
106
- errorCode: context.applyBackResult?.errorCode || 'APPLY_BACK_FAILED',
106
+ errorCode: applyBackResult?.errorCode || 'APPLY_BACK_FAILED',
107
107
  environmentMode,
108
108
  fallbackReason,
109
109
  });
@@ -112,16 +112,51 @@ export function resolveAttemptFailure(params) {
112
112
  reasonCode: 'APPLY_BACK_FAILED',
113
113
  failurePhase: 'APPLY_BACK',
114
114
  retryable: false,
115
- errorCode: context.applyBackResult?.errorCode || 'APPLY_BACK_FAILED',
115
+ errorCode: applyBackResult?.errorCode || 'APPLY_BACK_FAILED',
116
116
  diagnosticCode: guidance.diagnosticCode,
117
117
  safeHint: guidance.safeHint,
118
118
  remediationSteps: guidance.remediationSteps,
119
119
  };
120
120
  }
121
- if (flowReport.success && verifyOk) {
121
+ if (flowReport.success && verifyOk && !autopilotCompletion) {
122
122
  return undefined;
123
123
  }
124
124
  const errorCode = extractErrorCode(flowReport.error) ?? extractErrorCodeFromTraces(flowReport);
125
+ if (flowMode === 'autopilot' && autopilotCompletion) {
126
+ if (autopilotCompletion.status === 'changed' ||
127
+ autopilotCompletion.status === 'read_only_answer') {
128
+ if (flowReport.success && verifyOk)
129
+ return undefined;
130
+ }
131
+ const reasonCode = autopilotCompletion.status === 'verification_missing'
132
+ ? 'VERIFY_COMMAND_MISSING'
133
+ : autopilotCompletion.status === 'tool_failure' &&
134
+ isRecoverableToolInputErrorCode(autopilotCompletion.errorCode)
135
+ ? 'TOOL_CORRECTION_REQUIRED'
136
+ : 'LOOP_FAILED';
137
+ const failurePhase = autopilotCompletion.status === 'verification_missing' ? 'VERIFY' : 'AUTOPILOT';
138
+ const fallbackReason = autopilotCompletion.reason ||
139
+ (autopilotCompletion.status === 'no_effect'
140
+ ? 'Autopilot completed without changing files or producing an answer.'
141
+ : text.loop.loopExecutionFailed);
142
+ const guidance = buildFailureGuidance({
143
+ reasonCode,
144
+ failurePhase,
145
+ errorCode: autopilotCompletion.errorCode,
146
+ environmentMode,
147
+ fallbackReason,
148
+ });
149
+ return {
150
+ reason: guidance.safeHint,
151
+ reasonCode,
152
+ failurePhase,
153
+ retryable: reasonCode === 'TOOL_CORRECTION_REQUIRED' || autopilotCompletion.status === 'no_effect',
154
+ errorCode: autopilotCompletion.errorCode,
155
+ diagnosticCode: guidance.diagnosticCode,
156
+ safeHint: guidance.safeHint,
157
+ remediationSteps: guidance.remediationSteps,
158
+ };
159
+ }
125
160
  if (errorCode === 'PREFLIGHT_NOT_GIT') {
126
161
  const fallbackReason = sanitizeReason(flowReport.error);
127
162
  const guidance = buildFailureGuidance({
@@ -182,7 +217,28 @@ export function resolveAttemptFailure(params) {
182
217
  remediationSteps: guidance.remediationSteps,
183
218
  };
184
219
  }
185
- if (flowMode !== 'review' && context?.verifyResult?.ok === false) {
220
+ if (errorCode && NON_RETRYABLE_LLM_CODES.has(errorCode)) {
221
+ const failurePhase = inferFailurePhase(flowReport);
222
+ const fallbackReason = sanitizeReason(flowReport.error);
223
+ const guidance = buildFailureGuidance({
224
+ reasonCode: 'LOOP_FAILED',
225
+ failurePhase,
226
+ errorCode,
227
+ environmentMode,
228
+ fallbackReason,
229
+ });
230
+ return {
231
+ reason: guidance.safeHint,
232
+ reasonCode: 'LOOP_FAILED',
233
+ failurePhase,
234
+ retryable: false,
235
+ errorCode,
236
+ diagnosticCode: guidance.diagnosticCode,
237
+ safeHint: guidance.safeHint,
238
+ remediationSteps: guidance.remediationSteps,
239
+ };
240
+ }
241
+ if (profile.verifyPolicy !== 'never' && context?.verifyResult?.ok === false) {
186
242
  const verifyOutput = context.verifyResult.output || text.loop.loopExecutionFailed;
187
243
  const errorType = classifyError(verifyOutput);
188
244
  const fallbackReason = sanitizeReason(context.lastError || verifyOutput);
@@ -207,6 +263,25 @@ export function resolveAttemptFailure(params) {
207
263
  }
208
264
  const failurePhase = inferFailurePhase(flowReport);
209
265
  const fallbackReason = sanitizeReason(context?.lastError || flowReport.error);
266
+ if (isRecoverableToolInputErrorCode(errorCode)) {
267
+ const guidance = buildFailureGuidance({
268
+ reasonCode: 'TOOL_CORRECTION_REQUIRED',
269
+ failurePhase,
270
+ errorCode,
271
+ environmentMode,
272
+ fallbackReason,
273
+ });
274
+ return {
275
+ reason: guidance.safeHint,
276
+ reasonCode: 'TOOL_CORRECTION_REQUIRED',
277
+ failurePhase,
278
+ retryable: RETRYABLE_PHASES.has(failurePhase),
279
+ errorCode,
280
+ diagnosticCode: guidance.diagnosticCode,
281
+ safeHint: guidance.safeHint,
282
+ remediationSteps: guidance.remediationSteps,
283
+ };
284
+ }
210
285
  const guidance = buildFailureGuidance({
211
286
  reasonCode: failurePhase === 'ROLLBACK' ? 'ROLLBACK_FAILED' : 'LOOP_FAILED',
212
287
  failurePhase,
@@ -1,5 +1,5 @@
1
1
  export function mapSuccessReport(params) {
2
- const { attempt, flowReport, history, authorizationSummary, lastContext, lastVerifyArtifact, lastErrorCode, } = params;
2
+ const { attempt, flowReport, history, authorizationSummary, lastContext, lastVerifyArtifact, lastSubAgentPatchArtifacts, lastSubAgentAuditArtifacts, lastRecentReadArtifacts, lastToolResultPreviewArtifacts, lastErrorCode, } = params;
3
3
  return {
4
4
  success: true,
5
5
  attempts: attempt,
@@ -10,10 +10,14 @@ export function mapSuccessReport(params) {
10
10
  retryExhausted: false,
11
11
  lastContext,
12
12
  lastVerifyArtifact,
13
+ lastSubAgentPatchArtifacts,
14
+ lastSubAgentAuditArtifacts,
15
+ lastRecentReadArtifacts,
16
+ lastToolResultPreviewArtifacts,
13
17
  };
14
18
  }
15
19
  export function mapTerminalFailureReport(params) {
16
- const { attempt, flowReport, history, authorizationSummary, lastContext, lastVerifyArtifact, failure, lastErrorCode, } = params;
20
+ const { attempt, flowReport, history, authorizationSummary, lastContext, lastVerifyArtifact, lastSubAgentPatchArtifacts, lastSubAgentAuditArtifacts, lastRecentReadArtifacts, lastToolResultPreviewArtifacts, failure, lastErrorCode, } = params;
17
21
  return {
18
22
  success: false,
19
23
  attempts: attempt,
@@ -24,6 +28,10 @@ export function mapTerminalFailureReport(params) {
24
28
  retryExhausted: false,
25
29
  lastContext,
26
30
  lastVerifyArtifact,
31
+ lastSubAgentPatchArtifacts,
32
+ lastSubAgentAuditArtifacts,
33
+ lastRecentReadArtifacts,
34
+ lastToolResultPreviewArtifacts,
27
35
  terminalReason: failure.reason,
28
36
  terminalReasonCode: failure.reasonCode,
29
37
  terminalFailurePhase: failure.failurePhase,
@@ -34,7 +42,7 @@ export function mapTerminalFailureReport(params) {
34
42
  };
35
43
  }
36
44
  export function mapRetryExhaustedReport(params) {
37
- const { attempts, flowReport, history, authorizationSummary, lastErrorCode, lastContext, lastVerifyArtifact, } = params;
45
+ const { attempts, flowReport, history, authorizationSummary, failure, lastErrorCode, lastContext, lastVerifyArtifact, lastSubAgentPatchArtifacts, lastSubAgentAuditArtifacts, lastRecentReadArtifacts, lastToolResultPreviewArtifacts, } = params;
38
46
  return {
39
47
  success: false,
40
48
  attempts,
@@ -45,6 +53,12 @@ export function mapRetryExhaustedReport(params) {
45
53
  retryExhausted: true,
46
54
  lastContext,
47
55
  lastVerifyArtifact,
56
+ lastSubAgentPatchArtifacts,
57
+ lastSubAgentAuditArtifacts,
58
+ lastRecentReadArtifacts,
59
+ lastToolResultPreviewArtifacts,
60
+ terminalFailurePhase: failure?.failurePhase,
61
+ terminalDiagnosticCode: failure?.diagnosticCode,
48
62
  };
49
63
  }
50
64
  //# sourceMappingURL=report-mapper.js.map
@@ -1,7 +1,8 @@
1
1
  import { recordAuditEvent } from '../../../observability/audit-trail.js';
2
2
  import { mapErrorForAudit } from '../../../observability/error-mapping.js';
3
3
  import { ReflectionEngine } from '../../../reflection/engine.js';
4
- import { executeSalmonLoopFlow } from '../../flows/SalmonLoopFlow.js';
4
+ import { resolveExecutionProfile } from '../../../runtime/execution-profile.js';
5
+ import { executeFlowAttempt } from '../../flows/flow-dispatch.js';
5
6
  import { resolveAttemptFailure } from './attempt-failure.js';
6
7
  import { buildAuthorizationSummary } from './authorization-summary.js';
7
8
  import { mapRetryExhaustedReport, mapSuccessReport, mapTerminalFailureReport, } from './report-mapper.js';
@@ -12,6 +13,108 @@ export class FlowTransactionCancelledError extends Error {
12
13
  this.name = 'FlowTransactionCancelledError';
13
14
  }
14
15
  }
16
+ function isArtifactHandle(value) {
17
+ return (Boolean(value) &&
18
+ typeof value === 'object' &&
19
+ typeof value.handle === 'string');
20
+ }
21
+ function mergeArtifactHandles(existing, incoming, limit = 4) {
22
+ const merged = [...existing];
23
+ const seen = new Set(existing.map((artifact) => artifact.handle));
24
+ for (const artifact of incoming) {
25
+ if (seen.has(artifact.handle))
26
+ continue;
27
+ merged.push(artifact);
28
+ seen.add(artifact.handle);
29
+ }
30
+ if (merged.length <= limit)
31
+ return merged;
32
+ return merged.slice(merged.length - limit);
33
+ }
34
+ function extractSubAgentArtifacts(entries) {
35
+ if (!Array.isArray(entries) || entries.length === 0) {
36
+ return { patchArtifacts: [], auditArtifacts: [] };
37
+ }
38
+ const patchArtifacts = [];
39
+ const auditArtifacts = [];
40
+ for (const entry of entries) {
41
+ if (entry?.toolName !== 'agent_dispatch' || entry.toolResultStatus !== 'ok')
42
+ continue;
43
+ if (isArtifactHandle(entry.toolResultPatchArtifact)) {
44
+ patchArtifacts.push(entry.toolResultPatchArtifact);
45
+ }
46
+ if (isArtifactHandle(entry.toolResultAuditArtifact)) {
47
+ auditArtifacts.push(entry.toolResultAuditArtifact);
48
+ }
49
+ }
50
+ return { patchArtifacts, auditArtifacts };
51
+ }
52
+ function extractRecentReadArtifacts(entries) {
53
+ if (!Array.isArray(entries) || entries.length === 0) {
54
+ return [];
55
+ }
56
+ const recentReads = [];
57
+ for (const entry of entries) {
58
+ if (entry.toolIntent !== 'READ' || entry.toolResultStatus !== 'ok')
59
+ continue;
60
+ if (typeof entry.toolResultReadArtifactPath !== 'string')
61
+ continue;
62
+ if (!isArtifactHandle(entry.toolResultReadArtifact))
63
+ continue;
64
+ recentReads.push({
65
+ path: entry.toolResultReadArtifactPath,
66
+ artifact: entry.toolResultReadArtifact,
67
+ });
68
+ }
69
+ return recentReads;
70
+ }
71
+ function mergeReadArtifacts(existing, incoming, limit = 6) {
72
+ const merged = [];
73
+ const seen = new Set();
74
+ for (const item of [...existing, ...incoming]) {
75
+ const key = `${item.path}::${item.artifact.handle}`;
76
+ if (seen.has(key))
77
+ continue;
78
+ seen.add(key);
79
+ merged.push(item);
80
+ }
81
+ if (merged.length <= limit)
82
+ return merged;
83
+ return merged.slice(merged.length - limit);
84
+ }
85
+ function extractToolResultPreviewArtifacts(entries) {
86
+ if (!Array.isArray(entries) || entries.length === 0) {
87
+ return [];
88
+ }
89
+ const previews = [];
90
+ for (const entry of entries) {
91
+ if (entry.toolResultStatus !== 'ok')
92
+ continue;
93
+ if (typeof entry.toolResultPreviewLabel !== 'string')
94
+ continue;
95
+ if (!isArtifactHandle(entry.toolResultPreviewArtifact))
96
+ continue;
97
+ previews.push({
98
+ label: entry.toolResultPreviewLabel,
99
+ artifact: entry.toolResultPreviewArtifact,
100
+ });
101
+ }
102
+ return previews;
103
+ }
104
+ function mergePreviewArtifacts(existing, incoming, limit = 6) {
105
+ const merged = [];
106
+ const seen = new Set();
107
+ for (const item of [...existing, ...incoming]) {
108
+ const key = `${item.label}::${item.artifact.handle}`;
109
+ if (seen.has(key))
110
+ continue;
111
+ seen.add(key);
112
+ merged.push(item);
113
+ }
114
+ if (merged.length <= limit)
115
+ return merged;
116
+ return merged.slice(merged.length - limit);
117
+ }
15
118
  export class FlowTransactionRunner {
16
119
  params;
17
120
  historyEntries = [];
@@ -20,8 +123,25 @@ export class FlowTransactionRunner {
20
123
  authorizationSummary = null;
21
124
  lastContext;
22
125
  lastVerifyArtifact;
126
+ lastSubAgentPatchArtifacts;
127
+ lastSubAgentAuditArtifacts;
128
+ lastRecentReadArtifacts;
129
+ lastToolResultPreviewArtifacts;
130
+ lastReplacementState;
23
131
  constructor(params) {
24
132
  this.params = params;
133
+ this.lastVerifyArtifact = params.options.artifactHints?.verifyArtifact;
134
+ this.lastSubAgentPatchArtifacts = [
135
+ ...(params.options.artifactHints?.subAgentPatchArtifacts ?? []),
136
+ ];
137
+ this.lastSubAgentAuditArtifacts = [
138
+ ...(params.options.artifactHints?.subAgentAuditArtifacts ?? []),
139
+ ];
140
+ this.lastRecentReadArtifacts = [...(params.options.artifactHints?.recentReadArtifacts ?? [])];
141
+ this.lastToolResultPreviewArtifacts = [
142
+ ...(params.options.artifactHints?.toolResultPreviewArtifacts ?? []),
143
+ ];
144
+ this.lastReplacementState = params.options.replacementState;
25
145
  }
26
146
  isShrinkCtx(ctx) {
27
147
  return Boolean(ctx && 'verifyResult' in ctx);
@@ -29,13 +149,15 @@ export class FlowTransactionRunner {
29
149
  async execute() {
30
150
  let retries = 0;
31
151
  let lastReport;
152
+ let lastAttemptFailure;
153
+ const profile = resolveExecutionProfile(this.params.flowMode);
32
154
  while (true) {
33
155
  if (this.params.options.signal?.aborted) {
34
156
  throw new FlowTransactionCancelledError();
35
157
  }
36
158
  const attempt = retries + 1;
37
159
  recordAuditEvent('loop.attempt.start', { attempt, flowMode: this.params.flowMode }, { phase: 'PREFLIGHT', scope: 'session' });
38
- const result = await executeSalmonLoopFlow({
160
+ const result = await executeFlowAttempt({
39
161
  workspace: this.params.env.workspace,
40
162
  options: this.params.options,
41
163
  mode: this.params.flowMode,
@@ -46,6 +168,20 @@ export class FlowTransactionRunner {
46
168
  shadowInitialRef: this.params.env.shadowInitialRef,
47
169
  attempt,
48
170
  initialContext: this.currentContext,
171
+ artifactHints: {
172
+ verifyArtifact: this.lastVerifyArtifact,
173
+ subAgentPatchArtifacts: this.lastSubAgentPatchArtifacts.length > 0
174
+ ? this.lastSubAgentPatchArtifacts
175
+ : undefined,
176
+ subAgentAuditArtifacts: this.lastSubAgentAuditArtifacts.length > 0
177
+ ? this.lastSubAgentAuditArtifacts
178
+ : undefined,
179
+ recentReadArtifacts: this.lastRecentReadArtifacts.length > 0 ? this.lastRecentReadArtifacts : undefined,
180
+ toolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts.length > 0
181
+ ? this.lastToolResultPreviewArtifacts
182
+ : undefined,
183
+ },
184
+ replacementState: this.lastReplacementState,
49
185
  lastError: this.currentLastError,
50
186
  applyBackRuntime: {
51
187
  activeRepoPath: this.params.env.activeRepoPath,
@@ -64,11 +200,18 @@ export class FlowTransactionRunner {
64
200
  if (shrinkCtx?.verifyArtifact) {
65
201
  this.lastVerifyArtifact = shrinkCtx.verifyArtifact;
66
202
  }
203
+ const subAgentArtifacts = extractSubAgentArtifacts(terminalCtx?.toolCallingAudit);
204
+ this.lastSubAgentPatchArtifacts = mergeArtifactHandles(this.lastSubAgentPatchArtifacts, subAgentArtifacts.patchArtifacts);
205
+ this.lastSubAgentAuditArtifacts = mergeArtifactHandles(this.lastSubAgentAuditArtifacts, subAgentArtifacts.auditArtifacts);
206
+ this.lastRecentReadArtifacts = mergeReadArtifacts(this.lastRecentReadArtifacts, extractRecentReadArtifacts(terminalCtx?.toolCallingAudit));
207
+ this.lastToolResultPreviewArtifacts = mergePreviewArtifacts(this.lastToolResultPreviewArtifacts, extractToolResultPreviewArtifacts(terminalCtx?.toolCallingAudit));
208
+ this.lastReplacementState = terminalCtx?.replacementState ?? this.lastReplacementState;
67
209
  const attemptFailure = resolveAttemptFailure({
68
210
  flowReport: result,
69
211
  context: shrinkCtx,
70
212
  flowMode: this.params.flowMode,
71
213
  });
214
+ lastAttemptFailure = attemptFailure;
72
215
  const entry = {
73
216
  attempt,
74
217
  plan: shrinkCtx?.plan ?? null,
@@ -82,9 +225,11 @@ export class FlowTransactionRunner {
82
225
  this.params.telemetry.addHistory(entry);
83
226
  this.authorizationSummary = buildAuthorizationSummary(shrinkCtx?.toolAuditLogger?.getLogs?.());
84
227
  if (!attemptFailure) {
85
- const successPhase = this.params.flowMode === 'review' || this.params.flowMode === 'research'
86
- ? 'SHRINK'
87
- : 'APPLY_BACK';
228
+ const successPhase = profile.failurePolicy === 'preserve'
229
+ ? profile.entryPhase
230
+ : profile.readOnly
231
+ ? 'SHRINK'
232
+ : 'APPLY_BACK';
88
233
  recordAuditEvent('loop.attempt.success', { attempt, flowMode: this.params.flowMode }, { phase: successPhase, severity: 'low', scope: 'session' });
89
234
  // Reflection Mechanism: trigger when multiple attempts were needed
90
235
  if (attempt > 1 && this.params.options.llm) {
@@ -107,8 +252,12 @@ export class FlowTransactionRunner {
107
252
  history: this.historyEntries,
108
253
  authorizationSummary: this.authorizationSummary,
109
254
  lastErrorCode: this.extractErrorCode(result.error),
110
- lastContext: shrinkCtx,
255
+ lastContext: terminalCtx,
111
256
  lastVerifyArtifact: this.lastVerifyArtifact,
257
+ lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
258
+ lastSubAgentAuditArtifacts: this.lastSubAgentAuditArtifacts,
259
+ lastRecentReadArtifacts: this.lastRecentReadArtifacts,
260
+ lastToolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts,
112
261
  });
113
262
  }
114
263
  if (attemptFailure.reasonCode === 'AWAITING_INPUT') {
@@ -160,8 +309,12 @@ export class FlowTransactionRunner {
160
309
  history: this.historyEntries,
161
310
  authorizationSummary: this.authorizationSummary,
162
311
  lastErrorCode: attemptFailure.errorCode ?? this.extractErrorCode(result.error),
163
- lastContext: shrinkCtx,
312
+ lastContext: terminalCtx,
164
313
  lastVerifyArtifact: this.lastVerifyArtifact,
314
+ lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
315
+ lastSubAgentAuditArtifacts: this.lastSubAgentAuditArtifacts,
316
+ lastRecentReadArtifacts: this.lastRecentReadArtifacts,
317
+ lastToolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts,
165
318
  failure: attemptFailure,
166
319
  });
167
320
  }
@@ -184,9 +337,14 @@ export class FlowTransactionRunner {
184
337
  flowReport: lastReport,
185
338
  history: this.historyEntries,
186
339
  authorizationSummary: this.authorizationSummary,
340
+ failure: lastAttemptFailure,
187
341
  lastErrorCode: this.extractErrorCode(lastReport.error),
188
342
  lastContext: this.lastContext,
189
343
  lastVerifyArtifact: this.lastVerifyArtifact,
344
+ lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
345
+ lastSubAgentAuditArtifacts: this.lastSubAgentAuditArtifacts,
346
+ lastRecentReadArtifacts: this.lastRecentReadArtifacts,
347
+ lastToolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts,
190
348
  });
191
349
  }
192
350
  extractErrorCode(error) {