Context
An observed headless execution using CLI 0.4.3 and Gemini 2.5 Flash completed one file-read tool call, then emitted a terminal message with finish: "error". No final text was recorded; there was no session-error event, and the process exited 0. A downstream consumer classified the result as incomplete despite the successful process exit.
The pinned Google SDK 2.0.54 maps only MALFORMED_FUNCTION_CALL to normalized error. This is strong evidence for a malformed generated function call, but the raw response and exact invalid call were not retained. Do not describe the exact offending call or its cause as proven.
Problem / Goal
Normalized finish: "error" loses provider-specific meaning. The pinned Google adapter also omits the raw finish reason/diagnostic from the metadata passed onward. A downstream telemetry field alone cannot recover information discarded at that boundary.
Proposed Approach
Preserve a structured termination diagnostic from the provider adapter through message storage and headless NDJSON. Include provider/model, raw and normalized reason, available provider request ID, and a bounded redacted diagnostic, correlated with invocation/session/message identity. Use an adapter change or dependency update after verifying it retains the needed fields. Missing provider details must be explicit; do not infer a raw reason and report it as observed.
Acceptance Criteria
Out of Scope
Raw response archives, a general debug-bundle product, new audit sinks (#33/#34), dashboards, automatic recovery, and changes to Google model behavior.
Roadmap Alignment
- Pillar: EXEC; Q3 2026 pilot-ready executor reliability and code-review quality.
- Priority: P1 — prevents repeated investigations from ending at a generic error.
- Milestone: Enterprise Observability (CLI repository milestone; repository-specific milestone numbering).
- Uses existing repository labels; priority and pillar are recorded here because matching labels do not exist in this repository.
References
Sequencing
Can proceed alongside the failure-outcome fix; align terminal event fields with #108
Context
An observed headless execution using CLI 0.4.3 and Gemini 2.5 Flash completed one file-read tool call, then emitted a terminal message with
finish: "error". No final text was recorded; there was no session-error event, and the process exited 0. A downstream consumer classified the result as incomplete despite the successful process exit.The pinned Google SDK 2.0.54 maps only
MALFORMED_FUNCTION_CALLto normalizederror. This is strong evidence for a malformed generated function call, but the raw response and exact invalid call were not retained. Do not describe the exact offending call or its cause as proven.Problem / Goal
Normalized
finish: "error"loses provider-specific meaning. The pinned Google adapter also omits the raw finish reason/diagnostic from the metadata passed onward. A downstream telemetry field alone cannot recover information discarded at that boundary.Proposed Approach
Preserve a structured termination diagnostic from the provider adapter through message storage and headless NDJSON. Include provider/model, raw and normalized reason, available provider request ID, and a bounded redacted diagnostic, correlated with invocation/session/message identity. Use an adapter change or dependency update after verifying it retains the needed fields. Missing provider details must be explicit; do not infer a raw reason and report it as observed.
Acceptance Criteria
MALFORMED_FUNCTION_CALLand a diagnostic survives the actual adapter-to-NDJSON path with both raw and normalized reasons.Out of Scope
Raw response archives, a general debug-bundle product, new audit sinks (#33/#34), dashboards, automatic recovery, and changes to Google model behavior.
Roadmap Alignment
References
packages/cli/src/session/processor.ts,src/session/prompt.ts,src/cli/cmd/run.ts, andsrc/cli/cmd/run.invocation.ts(paths relative topackages/cliexcept the first).aictrl runexits 0 on auth failure, masking broken CI workflows #70 (exception-driven exit status), NDJSON event schema gaps for downstream observability consumers #63 (event contract), Add NDJSON invocation lifecycle events before session creation #90 (invocation lifecycle), Preserve unknown usage on failed headless turns #93 (unknown usage), Add model stream idle-timeout handling #80 (stream idle timeout).Sequencing
Can proceed alongside the failure-outcome fix; align terminal event fields with #108