Design Spec: Composition¶
Document Control¶
| Field | Value |
|---|---|
| Status | Implemented |
| Command surface | canarchy decode, filter, j1939 decode |
| Primary area | CLI, event stream composition |
Goal¶
Allow commands that consume frame events to read the canonical JSONL event stream from stdin so CANarchy commands compose cleanly in pipelines.
User-Facing Motivation¶
Operators and coding agents should be able to connect commands with pipes instead of writing intermediate capture files for every transform.
Requirements¶
| ID | Type | Requirement |
|---|---|---|
REQ-COMP-01 |
Optional feature | Where --stdin is specified, decode, filter, and j1939 decode shall read JSONL frame events from stdin instead of a --file capture source. |
REQ-COMP-02 |
Unwanted behaviour | If --stdin is specified alongside a --file capture source, the system shall return a structured error with code STDIN_AND_FILE_SPECIFIED and exit code 1. |
REQ-COMP-03 |
Unwanted behaviour | If neither --stdin nor a capture file is provided for a command that requires one, the system shall return a structured error with code MISSING_INPUT and exit code 1. |
REQ-COMP-04 |
Event-driven | When --stdin is in use, the system shall validate each non-empty line as a canonical frame event before command-specific processing begins. |
REQ-COMP-05 |
Unwanted behaviour | If a stdin line is malformed JSON, is not a frame event, or does not decode into a valid frame, the system shall return a structured error with code INVALID_STREAM_EVENT and exit code 1. |
REQ-COMP-06 |
Unwanted behaviour | If stdin contains no valid non-empty frame events, the system shall return a structured error with code NO_STREAM_EVENTS and exit code 1. |
REQ-COMP-07 |
Ubiquitous | When --stdin is used, JSONL output shall preserve the existing event-stream contract of the consuming command. |
Command Surface¶
canarchy decode --dbc <file> --stdin [--json|--jsonl|--text]
canarchy filter <expression> --stdin [--json|--jsonl|--text]
canarchy j1939 decode --stdin [--json|--jsonl|--text]
Representative usage:
canarchy capture can0 --jsonl | canarchy filter 'id==0x18FEEE31' --stdin --jsonl
canarchy capture can0 --jsonl | canarchy decode --stdin --dbc truck.dbc --jsonl
canarchy capture can0 --jsonl | canarchy j1939 decode --stdin --jsonl
Pipe Contract¶
Each non-empty stdin line must be a JSON object whose top-level event_type is "frame" and whose payload contains payload.frame matching the canonical frame envelope.
Representative input line:
{
"event_type": "frame",
"payload": {
"frame": {
"arbitration_id": 419360305,
"data": "11223344",
"frame_format": "can",
"interface": "can0",
"is_extended_id": true,
"is_remote_frame": false,
"is_error_frame": false,
"bitrate_switch": false,
"error_state_indicator": false,
"timestamp": 0.0
}
},
"source": "transport.capture",
"timestamp": 0.0
}
Ignored input:
- blank lines
Rejected input:
- malformed JSON
- non-frame events such as
alertorsignal - frame payloads missing required fields or containing invalid CAN frame data
Error Contracts¶
| Code | Trigger | Exit code |
|---|---|---|
STDIN_AND_FILE_SPECIFIED |
--stdin is used with a --file capture source |
1 |
MISSING_INPUT |
neither --stdin nor a capture file is provided |
1 |
INVALID_STREAM_EVENT |
stdin line is malformed JSON, not a frame event, or does not decode into a valid frame | 1 |
NO_STREAM_EVENTS |
stdin contains no valid non-empty frame events | 1 |
Notes¶
This is additive. File-backed workflows remain unchanged, and stdin support is limited to commands that naturally consume frame-event streams.