# 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` - `outputs/.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": "outputs/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 in normalized output order. 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" } ], "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. ## Output Payload Files Each normalized raw output is written to `outputs/.json`. For `application/json` payloads, the file contains the raw JSON payload pretty-printed. Other media types are written as raw bytes with the media type reported in `index.json`. For the current D&D spell extractor, `outputs/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.