# JSON Output This document is the durable JSON output file-format contract produced by the implemented `json` output module and written by the CLI. ## Output Directory The CLI writes logical output files under: ```text // ``` The default output root is `./notarius-output`. Operational behavior is covered in [Operations](../operations.md). ## Files The `json` output module writes: - `index.json` - `manifest.json` - `lanes/.json`, one file per normalized raw lane output - `rejected.json` - `warnings.json` Files are pretty-printed JSON with a trailing newline when the payload is JSON. ## `index.json` Shape: ```json { "manifest_file": "manifest.json", "output_files": [ { "lane_id": "spells", "media_type": "application/json", "file": "lanes/spells.json", "module_key": "noop", "schema_id": "notarius.dnd.spells", "schema_name": "notarius_dnd_spells_v1", "schema_version": "v1" } ], "rejected_file": "rejected.json", "warnings_file": "warnings.json" } ``` `output_files` is sorted by lane ID. Output file names are produced by sanitizing the lane ID: - characters outside `A-Z`, `a-z`, `0-9`, `.`, `_`, and `-` become `_`; - repeated `..` sequences are replaced; - leading and trailing `.`, `_`, and `-` are trimmed; - empty sanitized names are rejected; - two lanes that sanitize to the same output file are rejected. ## `manifest.json` `manifest.json` contains a run manifest: ```json { "run_id": "run-123", "pipeline_id": "dnd-session", "pipeline_digest": "sha256:...", "input_module": "seriatim", "chunker": "dnd/scenes", "source_digests": ["sha256:..."], "extractors": ["dnd/spells"], "merger": "appendorder", "normalizer": "noop", "output_encoder": "json", "artifact_lanes": [ { "id": "spells", "extractor": "dnd/spells", "merger": "appendorder", "normalizer": "noop" } ], "validator_chains": [ { "stage": "extract", "lane_id": "spells", "module_key": "dnd/spells", "validators": [ { "key": "generic/valid_json", "execution_class": "deterministic" }, { "key": "generic/valid_json_schema", "execution_class": "deterministic" }, { "key": "extract/dnd/spells/shape", "execution_class": "deterministic" }, { "key": "extract/dnd/spells/source_refs", "execution_class": "deterministic" }, { "key": "extract/dnd/spells/source_relatedness", "execution_class": "deterministic" } ] } ], "validation_status": "approved", "started_at": "2026-01-01T00:00:00Z", "completed_at": "2026-01-01T00:00:01Z" } ``` Fields with empty values may be omitted by JSON encoding. `source_digests` contains source document digests only. Bound references are recorded separately under `references`, which contains provenance only: target stage, lane ID when present, slot name, origin type and URI, digest, media type, byte size, and binding source. Reference content is not written to durable output. Reference `stage` is `chunk`, `extract`, `merge`, or `normalize`. `lane_id` is omitted for chunk references and present for extract, merge, and normalize references. `validation_status` is `approved` when no raw outputs were rejected and `rejected` when one or more raw outputs were rejected. `validator_chains` records the resolved validator chain for each validation point. Entries include stage, lane ID when applicable, module key, and validators with key and execution class. Empty chains are recorded with an empty `validators` array, including chains resolved from explicit empty config overrides. `normalized_outputs` summarizes each normalized lane output without embedding payload bytes. Entries include lane ID, normalizer module key, source ID, media type, and response schema provenance where available. `rejected_outputs` summarizes rejected module outputs without embedding raw payload bytes. Entries include stage, lane, module, chunk, validator or reason, message, attempt count, and optional diagnostic artifact path. ## Output Payload Files Each normalized raw output is written to `lanes/.json`. The JSON output encoder accepts only `application/json` normalized outputs. The file contains the raw JSON payload pretty-printed. For the current D&D spell extractor, `lanes/spells.json` has this shape: ```json { "spell_casts": [ { "caster": "Aria", "spell": "Cure Wounds", "effect": "heals an injured ally", "narrative_description": "Aria raises her holy symbol and casts Cure Wounds.", "source_refs": [ { "source_id": "session-alpha", "start_unit_id": 1, "end_unit_id": 1 } ] } ] } ``` ## `rejected.json` Shape: ```json { "rejected": [] } ``` When raw output validation rejects an output, entries use the `contracts.RejectedOutput` shape, including stage, lane ID, module key, validator name, reason code, message, attempt count, and optional diagnostic artifact path. ## `warnings.json` Shape: ```json { "warnings": [ { "scope": "extract", "reason_code": "example", "message": "human-readable warning" } ] } ``` `warnings` is an empty array when no warnings are reported.