Files
notarius/docs/roadmap/subprocess.md

209 lines
9.3 KiB
Markdown

# Subprocess Integration Contract
## Status
Accepted for implementation.
## Purpose
Make Notarius straightforward to invoke as a subprocess from an orchestrator
such as Narratio. A caller should be able to run a configured pipeline, discover
the published output bundle without parsing human prose or scanning a
directory, and hand selected structured artifacts to a later stage.
This work strengthens the public CLI boundary. It does not turn Notarius into a
Go library, embed Narratio-specific behavior, or change pipeline execution and
artifact semantics.
## Desired End State
A subprocess caller can:
1. validate a Notarius configuration and selected pipeline before execution;
2. invoke `notarius run` with explicit input, output-root, session, and
reference arguments;
3. request one versioned, machine-readable success result on standard output;
4. use that result to locate the published output bundle;
5. discover normalized lane payloads through the bundle's authoritative
`index.json`;
6. distinguish process failure from successful partial pipeline outcomes; and
7. record Notarius run provenance in its own manifest without depending on
internal packages, cache formats, debug formats, or human-readable messages.
The existing human-oriented command output remains the default for interactive
use.
## Machine-Readable Run Result
`notarius run` supports `--json`. On success, the flag makes standard output
contain exactly one JSON object followed by a newline. No human-oriented status
line is mixed into that stream.
The result uses the schema identity `notarius.run-result.v1` and contains:
| Field | Presence | Meaning |
| --- | --- | --- |
| `schema_version` | Required | Exactly `notarius.run-result.v1`. |
| `run_id` | Required | The Notarius run identifier. |
| `pipeline_id` | Required | The effective pipeline identifier. |
| `output_directory` | Required | Absolute path to the successfully published output bundle. |
| `index_file` | Required for the production JSON output | Logical bundle path `index.json`. |
| `normalized_output_count` | Required | Number of final normalized lane outputs returned by the pipeline. |
| `rejected_output_count` | Required | Number of recorded rejected outputs. |
| `warning_count` | Required | Number of final run warnings returned by the pipeline. |
| `validation_status` | Required | The run manifest's final validation status without reinterpretation. |
| `debug_directory` | Optional | Absolute debug-bundle path when debug capture was requested and completed. |
An illustrative successful result is:
```json
{
"schema_version": "notarius.run-result.v1",
"run_id": "run-1770000000000000000-0123456789abcdef0123456789abcdef",
"pipeline_id": "dnd-session",
"output_directory": "/srv/narratio/runs/session-7/notarius/run-1770000000000000000-0123456789abcdef0123456789abcdef",
"index_file": "index.json",
"normalized_output_count": 6,
"rejected_output_count": 2,
"warning_count": 1,
"validation_status": "approved"
}
```
The receipt is a discovery and summary document, not a duplicate output
envelope. It does not embed lane payloads, rejection entries, warnings, the run
manifest, or output-file contents. Consumers use `index_file` and the existing
published JSON output contract for those records.
The result contract must tolerate future additive optional fields. Any
incompatible field or semantic change requires a new run-result schema version.
## Stream, Publication, And Failure Semantics
Machine-readable output is emitted only after:
- the pipeline has completed without a framework error;
- all logical output files have been successfully published;
- requested debug terminal reporting has completed; and
- all result fields are known.
Writing or encoding the machine-readable result is part of successful command
completion. Failure to write it produces the existing runtime-failure exit
class.
With `--json`:
- successful stdout is exclusively the run-result JSON document;
- successful warnings remain on stderr under the existing CLI contract;
- syntax and runtime errors retain their existing exit statuses and stderr
diagnostics;
- consumers treat stdout as a valid result only when the process exits with
status 0; failures before result writing emit no result, while a failure
during the stdout write may leave incomplete bytes that must be ignored; and
- human-readable diagnostic wording is not promoted into a machine contract.
Without `--json`, current interactive stdout and stderr behavior remains
unchanged.
Successful runs may contain rejected outputs or omit some normalized lanes.
That remains a valid pipeline outcome. The run result reports counts, while
`index.json`, `rejected.json`, and `warnings.json` remain authoritative for
details. Notarius will not add a generic `--fail-on-rejection` policy as part
of this work.
## Output Discovery And Consumer Responsibilities
The production JSON encoder's `index.json` remains the authoritative mapping
from lane IDs to published payloads. A subprocess consumer should:
- resolve `index_file` beneath `output_directory` and reject path escape;
- locate expected outputs by `lane_id`, not by guessing filenames;
- check each selected descriptor's media type and schema identity;
- decode payloads according to their published integration contracts;
- decide which lanes are required or optional for its own later stages; and
- retain rejection, warning, and manifest files when they are needed for
provenance or review.
For Narratio, required report inputs and partial-success policy remain Narratio
stage configuration and orchestration concerns. Notarius does not acquire
knowledge of Narratio stages, manifests, workspace layout, publication policy,
or report formats.
## Invocation Guidance
The consumer documentation recommends that subprocess callers:
- use `notarius config validate --pipeline` as an optional preflight;
- pass explicit absolute paths for the input, configuration, output root, and
CLI-supplied references;
- use a stable, non-secret prompt session identifier when useful for provider
routing or caching;
- capture stdout and stderr separately;
- supply credentials through the configured environment mechanism rather than
command arguments or generated configuration containing secret values;
- place output, cache, debug, and subprocess logs under intentional
sensitivity and retention policies; and
- treat the Notarius manifest and run-result receipt as provenance while
leaving the caller's own manifest authoritative for its stage lifecycle.
Notarius configuration remains owned by Notarius. An orchestrator may select a
configuration and pass supported operational overrides, but should not
duplicate the complete Notarius configuration schema.
## Documentation End State
- `docs/cli.md` owns `run --json`, stream behavior, and exit semantics;
- a new `docs/integrations/run-result.md` owns the versioned run-result wire
contract and compatibility policy;
- `docs/integrations/json-output.md` remains the sole owner of output-bundle
discovery and lane publication;
- a new `docs/consumers/subprocess.md` provides the task-oriented invocation and
consumption workflow; and
- `docs/internal/cli.md` describes how the CLI constructs and emits the result
only after successful publication.
Other documents should link to these owners instead of repeating volatile
fields or command details.
## Acceptance Criteria
- An ordinary successful `run` retains its existing human-readable output.
- A successful `run --json` emits one valid `notarius.run-result.v1` document
and no human prose on stdout.
- Relative configured or overridden output and debug roots are reported as
absolute bundle paths.
- The receipt identifies the production JSON bundle entry point without
copying its lane descriptors or payloads.
- Warning-bearing and rejection-bearing runs remain successful and report
accurate counts.
- Syntax, configuration, provider, pipeline, publication, debug, and result
writing failures retain the correct nonzero exit class. Consumers are
explicitly required to ignore stdout from a nonzero invocation.
- The implementation does not expose internal Go types or couple generic CLI
code to D&D or Narratio concepts.
- Public and internal documentation assigns each new contract to one canonical
owner.
- Offline behavioral tests protect the structured-output contract, default
human behavior, absolute path reporting, stream separation, and failure to
serialize or write the success result without duplicating lower-level output
encoder tests.
## Out Of Scope
The following may be useful later but are not prerequisites for the Narratio
integration:
- a result-file flag in addition to machine-readable stdout;
- a JSON failure envelope or stable machine-readable error taxonomy;
- caller-supplied Notarius run IDs or exact output-bundle paths;
- a generic `--fail-on-rejection` or required-lane CLI policy;
- a public Go client package or importable Narratio adapter;
- Narratio stage, configuration, manifest, or report-generation changes;
- `notarius version --json`;
- installable or queryable artifact JSON Schemas;
- signal-aware CLI contexts and graceful SIGINT or SIGTERM handling;
- packaged release artifacts and a broader application-versioning policy.
These items should be promoted only in response to a demonstrated integration
need rather than bundled into the initial subprocess contract.