Context
session_start is emitted only after validation, bootstrap, subscription, and session creation. Invalid files/directories, empty input, bootstrap failures, and stalled stdin can therefore leave JSON consumers with no stdout event.
A truthful session_start cannot be emitted before a real session ID exists.
Problem / Goal
Give JSON consumers a structured lifecycle from invocation start through pre-session failure without inventing a session ID or changing the meaning of session_start.
Proposed Approach
Add an invocation-level envelope:
invocation_start with schemaVersion and a generated invocationID;
invocation_error for validation, stdin, bootstrap, and session-creation failures;
invocation_complete exactly once;
- include
invocationID in later session events once a session exists.
For argument-parse failures, the headless entry point may detect an explicit --format json directly from argv before yargs completes.
Acceptance Criteria
Out of Scope
- Model/provider errors after session creation.
- Signal and timeout policy.
- Fabricating sessions solely to report validation failures.
Roadmap Alignment
- Pillar: EXEC
- Quarter: Q3 2026
- Priority: P1
- Theme fit: Execution telemetry and pilot-quality executor reliability.
- Decision gate impact: Indirect, by making failed automation diagnosable.
References
Upstream OpenCode References
- anomalyco/opencode#27559 — auto-closed after inactivity, not resolved; a missing session exits 0 with empty JSON stdout and the report explicitly requests a structured JSON failure event.
- anomalyco/opencode#30100 — open; a JSON command spawned from Node.js/Electron on Windows exits successfully with empty stdout.
These reports demonstrate pre-session and command-start failures that are invisible to JSON-only consumers. Neither defines a general invocation lifecycle independent of a real session ID.
Context
session_startis emitted only after validation, bootstrap, subscription, and session creation. Invalid files/directories, empty input, bootstrap failures, and stalled stdin can therefore leave JSON consumers with no stdout event.A truthful
session_startcannot be emitted before a real session ID exists.Problem / Goal
Give JSON consumers a structured lifecycle from invocation start through pre-session failure without inventing a session ID or changing the meaning of
session_start.Proposed Approach
Add an invocation-level envelope:
invocation_startwithschemaVersionand a generatedinvocationID;invocation_errorfor validation, stdin, bootstrap, and session-creation failures;invocation_completeexactly once;invocationIDin later session events once a session exists.For argument-parse failures, the headless entry point may detect an explicit
--format jsondirectly from argv before yargs completes.Acceptance Criteria
invocation_startis emitted before reading piped stdin and before run validation/bootstrap.invocationID, not a fabricatedsessionID.--dir, missing--file, empty input, bootstrap failure, and session-create failure produce structured invocation errors.invocation_complete.session_startretains its current meaning and real session ID.invocation_startbefore stdin closes.Out of Scope
Roadmap Alignment
References
packages/cli/src/cli/cmd/run.tspackages/cli/src/headless.tsUpstream OpenCode References
These reports demonstrate pre-session and command-start failures that are invisible to JSON-only consumers. Neither defines a general invocation lifecycle independent of a real session ID.