Add artifact provenance and stage skip outcomes

This commit is contained in:
2026-08-09 23:20:32 +00:00
parent df58595d1e
commit 951383226c
12 changed files with 1565 additions and 305 deletions

View File

@@ -2,266 +2,497 @@
## Status
Proposed.
Proposed. Implementation has not started.
The ordered implementation plan is maintained in
[implementation.md](implementation.md). Until that plan is complete, this
document is the only Narratio documentation that describes the proposed
`extract` stage, Notarius configuration, or `narratio.extraction.*` sources.
## Purpose
Add a first-class Narratio `extract` stage that runs Notarius against the
session's final trimmed transcript, validates and collects the resulting
structured D&D artifacts, and registers those artifacts for later use by the
`analyze` and `publish` stages.
session's final trimmed transcript and makes validated structured artifacts
available to later analysis and publish work.
This feature should integrate Notarius through Narratio's existing stage,
adapter, manifest, workspace, and artifact-catalog boundaries. It must not turn
Narratio into a generic workflow engine or a second configuration language for
Notarius pipelines.
Notarius remains responsible for its D&D extraction pipeline, prompts,
references, LLM profiles, retries, validation, normalization, and published
schemas. Narratio owns invocation, required-output policy, safe bundle
ingestion, artifact identity, manifest state, resume, and downstream
availability.
The integration must preserve Narratio's explicit stage model. It must not
turn Narratio into a generic workflow engine or reproduce Notarius's
configuration language.
## User Outcome
An operator can enable one configured Notarius pipeline for a Narratio
campaign. During a normal run, Narratio will:
An operator can enable one Notarius pipeline for a Narratio campaign. During a
normal run, Narratio will:
1. finish producing the session transcript tiers;
2. invoke Notarius once with the final trimmed Seriatim JSON transcript;
3. collect and validate the configured structured artifact lanes;
4. record their exact files and provenance in the Narratio manifest; and
5. make those artifacts selectable as inputs to Scriptorium artifacts in the
later `analyze` stage.
1. produce the final trimmed Seriatim JSON transcript;
2. invoke Notarius once with that transcript;
3. discover the exact run bundle through Notarius's machine-readable receipt;
4. validate every output contract Narratio is configured to require;
5. promote the complete validated bundle into immutable session storage;
6. record exact artifact paths, checksums, contracts, and external provenance;
7. make configured lanes available as `narratio.extraction.<key>` sources; and
8. allow individual Scriptorium artifacts and publish rules to select those
sources explicitly.
The maintained D&D example should demonstrate all ten lanes emitted by
Notarius's complete `dnd-session` pipeline.
The maintained complete D&D example will require all ten lanes published by
Notarius's `dnd-session` pipeline. Ordinary deployments may configure a
narrower required set.
## Target Stage Architecture
## Chosen Architecture
### First-Class Stage
Extraction is an independently observable and resumable pipeline stage. It is
not part of `analyze`, a Scriptorium artifact producer, or an implicit external
preprocessing requirement.
This boundary is required because Notarius work is expensive, produces
multiple durable outputs, has its own compatibility and diagnostic contracts,
and may be consumed by both `analyze` and `publish`.
### Canonical Order
The canonical stage order becomes:
```text
prepare -> transcribe -> merge -> polish -> normalize -> trim -> render
-> extract -> analyze -> publish -> notify
prepare -> transcribe -> merge -> polish -> normalize -> trim
-> extract -> render -> analyze -> publish -> notify
```
`extract` is deliberately after all transcript-producing stages and before
analysis. Its source document is the manifest-resolved
`narratio.transcript.final_trimmed` artifact, normally
`transcripts/final.trimmed.json`. It does not consume rendered Markdown.
`extract` consumes `narratio.transcript.final_trimmed`, produced by `trim`. It
does not consume rendered Markdown.
Adding the stage must update full-plan construction, explicit stage selection,
downstream invalidation, prerequisite checks, resume behavior, run manifests,
CLI stage validation and help, and every canonical-stage inventory. Forcing an
upstream transcript stage must stale a previously successful `extract` stage
and its downstream stages. Forcing `extract` must stale `analyze`, `publish`,
and `notify` according to existing rules.
Narratio currently invalidates succeeded stages by canonical downstream order.
Placing `extract` before `render` means forcing extraction may rerun the less
expensive deterministic render stage, while forcing render does not rerun the
more expensive Notarius pipeline. This is preferable to placing extraction
after render and does not require dependency-aware scheduling or a DAG.
Adding the stage must update every canonical-stage inventory, full-plan and
single-stage selection, prerequisite validation, downstream invalidation,
resume behavior, run manifests, CLI validation and help, and focused tests.
### Stage Boundary
The stage owns Narratio policy and state transitions:
The stage owns Narratio policy:
- resolve the final trimmed transcript through the runtime artifact catalog;
- build a Narratio-level Notarius request from validated configuration and
run-local paths;
- call a narrow Notarius adapter;
- apply the configured required-output policy;
- materialize the validated bundle into its canonical session location;
- return manifest-ready artifact references and bounded metadata; and
- fail without marking the stage successful when any required contract or
materialization step fails.
- resolve the final trimmed transcript through the manifest-aware artifact
resolver;
- allocate run-local receipt, log, and output-root paths;
- build a transport-neutral Notarius request from resolved configuration;
- call the configured Notarius adapter once;
- enforce Narratio's configured required-output policy;
- validate selected payloads as regular, non-empty, syntactically valid JSON;
- promote the validated bundle to immutable session artifact storage;
- return explicit source IDs, checksums, contracts, and external provenance;
and
- report an explicit skipped outcome when Notarius is disabled.
The stage must not construct subprocess arguments, infer Notarius output
filenames, parse provider logs, or decode individual D&D payload bodies.
The stage must not construct subprocess arguments, guess Notarius filenames,
parse interactive output, decode D&D payload structures, or reproduce
Notarius pipeline configuration.
### Adapter Boundary
Add a dedicated Notarius adapter package with a small interface, production
subprocess implementation, and test fake. Its request should contain only the
resolved Notarius binary, configuration path, pipeline ID, transcript path,
output root, working directory, timeout, and process-log destinations needed
for one run.
Add `internal/adapters/notarius` with a narrow runner interface, production
subprocess implementation, and small fake.
The request contains only:
- resolved executable path or name;
- absolute Notarius configuration path;
- pipeline ID;
- absolute transcript path;
- absolute output root;
- working directory;
- timeout; and
- stdout receipt and stderr log destinations.
The adapter owns:
- optional `notarius config validate` preflight for the configured pipeline;
- exact `notarius run ... --json` argument construction;
- stdout and stderr separation;
- context cancellation and timeout propagation through Narratio's shared
subprocess boundary;
- context cancellation and timeout through Narratio's shared subprocess
boundary;
- environment inheritance;
- exit-status handling;
- decoding the `notarius.run-result.v1` success receipt;
- receipt and index path-confinement checks;
- decoding `index.json` and resolving descriptor paths safely beneath the
reported output directory; and
- returning a transport-neutral result containing the bundle location,
receipt summary, lane descriptors, pipeline-wide descriptors, warnings and
rejection locations, and diagnostic log paths.
- bounded receipt loading after exit status zero;
- tolerant decoding of supported `notarius.run-result.v1` documents;
- validation of required receipt fields;
- confinement of the receipt's absolute `output_directory` beneath the
absolute output root Narratio supplied for this invocation;
- confinement of `index_file` beneath the receipt's absolute
`output_directory`;
- tolerant decoding of the supported `index.json` contract;
- confinement of every index descriptor path beneath the bundle root; and
- bounded tolerant decoding of `rejected.json` and `warnings.json` into
transport-neutral summaries without reading lane payload bodies; summaries
persisted by Narratio contain structured scope, lane, and reason fields but
not unbounded free-form external messages; and
- returning transport-neutral receipt, descriptor, diagnostic, and bundle
information.
Only exit status zero permits receipt decoding. Receipt, index, or descriptor
paths that are absolute where a logical relative path is required, or that
escape their owning root, are integration failures. Unknown fields in a
supported receipt or index schema should be tolerated. Unsupported schema
versions and incompatible descriptor metadata should fail clearly.
Only exit status zero permits receipt decoding. Unsupported schema versions,
malformed documents, missing required fields, absolute logical paths, path
escapes, symlinks at consumed paths, and incompatible structural metadata are
integration failures.
The adapter must not write Narratio manifests, choose required lanes, decide
analysis inputs, or contain D&D domain logic.
The production runner will not execute `notarius config validate` before every
session. Notarius run-time validation remains authoritative, while operators
may use the separate validation command as deployment preflight. A second
automatic subprocess can be added later only if operational evidence warrants
it.
The adapter does not write Narratio manifests, decide required lanes, choose
analysis inputs, or interpret D&D payloads.
## External Contract Baseline
The integration consumes the contracts documented by Notarius in
`../notarius/docs/consumers/dnd-pipeline.md` and its linked canonical
integration documents.
The initial compatibility baseline is:
- `notarius run <pipeline-id> --config ... --input ... --output-dir ... --json`;
- successful receipt schema `notarius.run-result.v1`;
- an absolute receipt `output_directory`;
- logical `index_file` discovery beneath that directory;
- the production JSON `index.json` descriptor model; and
- the exact media type and schema identity configured for each required lane.
Compatibility is decided from these published contracts, not by parsing
`notarius --version`. Unknown fields in supported receipt and index versions
are tolerated. Unsupported versions or incompatible required descriptors fail
before any artifact becomes current in Narratio.
## Configuration Contract
Add a strict optional `pipeline.notarius` configuration section. Omission or
`enabled: false` keeps the current workflow usable and causes `extract` to
self-skip without outputs.
Add a strict optional `pipeline.notarius` section:
The section should provide:
- `enabled`: explicit opt-in;
- `binary`: Notarius executable, defaulting to `notarius`;
- `config_path`: required when enabled;
- `pipeline_id`: required when enabled;
- `timeout`: a positive stage timeout with a documented default;
- `working_directory`: optional explicit subprocess working directory,
defaulting to the directory containing `config_path`; and
- an `outputs` map defining the Notarius lane artifacts Narratio promises to
collect.
Each output-map key is a stable Narratio extraction key. Each value must define:
- the exact Notarius `lane_id`;
- the expected `media_type`;
- the expected `schema_id`;
- the expected `schema_version`; and
- optionally an expected `module_key` when the operator needs to constrain the
producing module as part of compatibility.
Narratio derives the downstream source ID
`narratio.extraction.<output-key>` from the map key. Keys and lane IDs must be
non-empty, unique after normalization, path-safe under the existing artifact
policy, and collision-free with built-in and configured artifact identities.
Every configured output is required: a successful Notarius process that omits
one, rejects it, or reports incompatible descriptor metadata fails the
`extract` stage.
This explicit map keeps Narratio's consumer contract stable when a Notarius
lane ID or schema changes and avoids hard-coding the current D&D family into a
generic adapter. It also replaces a separate `required_lanes` list, which would
duplicate configuration.
Narratio should not reproduce Notarius lane selection, references, LLM
profiles, model settings, retries, concurrency, or prompt configuration. Those
remain in the referenced Notarius configuration. Narratio should not expose a
runtime lane-selection flag for `extract`; one stage invocation runs the
configured Notarius pipeline as a unit.
All configured paths should become absolute during Narratio configuration
resolution. The deterministic default working directory allows a Notarius
profile path relative to that directory, but operator documentation should
still recommend absolute deployment paths where practical. Notarius reference
paths continue to follow Notarius's own configuration-relative rules.
## Output And Artifact Model
### Canonical Bundle
Run Notarius against a run-local output root. After all configured descriptors
are validated, materialize the contents of the exact run-specific Notarius
bundle into a fixed canonical session directory:
```text
artifacts/notarius/
```yaml
notarius:
enabled: true
binary: notarius
config_path: /absolute/path/to/notarius.yml
pipeline_id: dnd-session
timeout: 3h
working_directory: /absolute/path/to/deployment
outputs:
npc_registry:
lane_id: npc-registry
media_type: application/json
schema_id: <published-schema-id>
schema_version: <published-schema-version>
```
Preserve its relative layout, including `index.json`, `manifest.json`,
`rejected.json`, `warnings.json`, `lanes/`, and any indexed `chunk-map.json` or
`evidence-context.json`. Materialize the complete directory as one narrow,
transactional replacement so a failed or interrupted rerun cannot mix files
from different Notarius runs.
Fields:
The raw subprocess receipt and stderr log belong in the run-local `extract`
report and log directories. The raw receipt identifies the original run-local
Notarius bundle and must not be rewritten to pretend that the canonical copy
was its original `output_directory`. Narratio's manifest is the durable ledger
for the canonical materialized paths.
- `enabled` is an explicit opt-in and defaults to false;
- `binary` defaults to `notarius`;
- `config_path` is required when enabled;
- `pipeline_id` is required when enabled;
- `timeout` defaults to `3h` and must be positive;
- `working_directory` is optional and defaults to the directory containing
`config_path`; and
- `outputs` maps stable Narratio extraction keys to required Notarius lane
contracts.
### Registered Artifact Sources
All configured paths become absolute during configuration resolution. Notarius
reference paths continue to follow Notarius's configuration-relative rules,
while PromptKit profile paths remain relative to the chosen process working
directory where Notarius permits that behavior.
For each configured output, locate the lane through the canonical copy of
`index.json` and record a manifest artifact with:
Each output entry contains:
- source ID `narratio.extraction.<output-key>`;
- canonical lane-file path discovered from the index;
- exact `lane_id`;
- exact `media_type`;
- exact `schema_id`;
- exact `schema_version`; and
- optional `module_key`.
The map key produces `narratio.extraction.<key>`. Keys use Narratio's existing
path-safe configured-artifact key grammar. Keys, normalized source IDs, and
lane IDs must be non-empty and unique. Extraction source IDs must not collide
with built-ins or configured Scriptorium sources.
Every configured output is required for extraction-stage success. Operators
who need only a subset configure only that subset. Narratio does not add a
second `required_lanes` list or a runtime lane-selection flag.
Narratio does not configure Notarius lane topology, references, prompts, LLM
profiles, model settings, concurrency, retry behavior, or session IDs. One
stage execution runs the configured Notarius pipeline as a unit. Narratio does
not pass Notarius's `--session-id` override.
## Stage Outcomes And Resume
### Explicit Self-Skip
Extend the stage-result contract with an explicit disposition whose zero value
remains successful for backward compatibility. A stage may return:
- succeeded; or
- skipped with a stable reason.
When Notarius is absent or disabled, `extract` returns skipped with reason
`notarius_disabled`, no outputs, and bounded metadata. The runner records a
skipped session-stage and run-stage outcome rather than a successful empty
stage. Skipped stages are reconsidered on later invocations, so subsequently
enabling Notarius causes extraction to run without requiring force.
A genuine self-skip clears any older outputs for that stage before persisting
the new skipped state. Downstream consumers cannot resolve artifacts retained
from an earlier extraction after the stage is disabled.
### Resume Validation
Add a small optional resume-validation interface implemented by `extract`.
Before skipping an already-succeeded extract stage, the runner asks it whether
the recorded result remains resumable.
The resume validator confirms:
- Notarius is still enabled;
- recorded configuration identity matches the current config path, pipeline
ID, and output-contract map;
- the immutable bundle and canonical index still exist;
- every configured source is present in the succeeded extract record;
- lane files remain confined regular files;
- stored checksums still match; and
- stored descriptor contracts and external provenance remain compatible.
An ordinary contract mismatch returns a non-resumable decision with a bounded
reason. The runner marks the stage stale and executes it. An environmental
error that prevents making a safe decision returns an error and stops the run.
Narratio does not recursively interpret Notarius configuration, PromptKit
profiles, or reference files. Changes to those external inputs are therefore
not automatically detectable. Operator documentation must require
`--force extract` after changing them.
The configuration fingerprint covers the resolved binary, config path,
pipeline ID, timeout, working directory, and the deterministically sorted
output-contract map. It identifies Narratio's invocation contract, not the
transitive content of files owned by Notarius.
### Force And Invalidation
- Forcing `trim` or an earlier stage stales succeeded `extract` and all later
stages.
- Forcing `extract` stales succeeded `render`, `analyze`, `publish`, and
`notify` under the existing canonical-order rule.
- Forcing `render` does not stale `extract` because extraction precedes it.
- A failed, skipped, stale, or interrupted extract stage never supplies current
extraction sources.
## Bundle Storage And Commit
### Run-Local Execution
Notarius runs against a run-local output root beneath the Narratio run's
`extract` directory. Receipt bytes and stderr remain run-local diagnostics.
Failed and malformed bundles remain outside durable artifact storage for
inspection and never become current merely because files exist.
### Immutable Durable Bundles
After complete validation, promote the exact Notarius bundle into:
```text
artifacts/notarius/<narratio-run-id>/
```
The destination is unique and must not already exist. Promotion uses a sibling
temporary directory on the same filesystem, recursively copies only regular
files and directories, rejects symlinks and special files, preserves relative
layout, and renames the completed temporary tree into place.
The promoted tree preserves `index.json`, `manifest.json`, `rejected.json`,
`warnings.json`, `lanes/`, and any emitted pipeline-wide artifacts such as
`chunk-map.json` and `evidence-context.json`. Unknown regular files may be
preserved because the complete bundle is provenance, but no unknown file is
registered as a stable Narratio source.
There is no mutable filesystem `current` directory or symlink. The atomically
saved Narratio session manifest selects the current successful bundle. Older
successful bundles remain immutable until explicit cleanup policy removes
them.
The raw Notarius receipt is retained without rewriting its original
`output_directory`. Narratio's manifest records promoted durable paths.
## Artifact And Manifest Model
### Explicit Source Identity
Extend `artifacts.Ref` with an optional explicit `SourceID`. The application
runner prefers that value and retains existing stage-specific inference only
as a backward-compatible fallback. `extract` must not require another
stage-name special case in output mapping.
Add neutral optional artifact metadata models under `internal/artifactmodel`:
- contract metadata: media type, schema ID, schema version, and optional
module key; and
- external provenance: system, external run ID, pipeline ID, and external
artifact ID.
Both `artifacts.Ref` and `manifest.ArtifactRecord` carry these nested models.
Existing manifests remain readable because the fields are optional and use
`omitempty` encoding.
For a Notarius lane, external provenance uses:
- system `notarius`;
- receipt run ID;
- receipt pipeline ID; and
- lane ID as the external artifact ID.
### Registered Sources
For each configured output, `extract` records one artifact with:
- source ID `narratio.extraction.<key>`;
- durable lane path discovered through the promoted canonical index;
- producer stage and Narratio run ID;
- checksum;
- Notarius lane ID; and
- descriptor media type, schema identity/version, and module key when present.
- SHA-256 checksum;
- configured and observed contract metadata; and
- Notarius external provenance.
If the current manifest model cannot carry descriptor compatibility metadata,
extend its artifact metadata in a backward-tolerant way rather than encoding
that information in filenames or source IDs.
The canonical promoted `index.json` is also a stage output with kind
`notarius_index`, but it is not a selectable extraction source. Extract-stage
metadata records the durable bundle root, receipt path, Notarius validation
status, counts, warnings/rejections paths and summaries, the producing Narratio
run ID, and the normalized configured-contract fingerprint used by resume
validation.
Also record the canonical Notarius index as a stage output or stage metadata so
operators can discover the complete bundle, including non-lane artifacts. The
configured lane sources are the stable interface for analysis; the index and
bundle remain the provenance and inspection interface.
The producing Narratio run ID belongs to the successful extract result. It is
not compared with the session manifest's top-level `run_id`, which advances on
later invocations even when extraction is validly resumed. Resume and catalog
checks instead require the extract outputs, immutable bundle path, and stored
extract-stage producer identity to agree with one another.
## Analysis And Publish Integration
## Artifact Catalog And Resolution
Extend the runtime artifact catalog and configured Scriptorium input validation
so an enabled analysis artifact can declare, for example:
Add extraction as a first-class artifact-policy and runtime-catalog family:
- source kind `extraction`;
- canonical prefix `narratio.extraction.`;
- registration from `pipeline.notarius.outputs`; and
- manifest-backed availability from the current successful `extract` record.
Extraction availability is never inferred by scanning
`artifacts/notarius/`. A source is available only when:
- it is declared in current configuration;
- the session manifest records `extract` as succeeded and not stale;
- the exact matching source output is present;
- its durable path is confined and valid;
- its checksum matches; and
- its recorded contract and external provenance are compatible.
The catalog should expose one shared registration and hydration path used by
both `analyze` and `publish`. Avoid parallel extract-specific resolution logic
inside each stage.
## Analyze Integration
An enabled Scriptorium artifact may select an extraction source through the
existing input contract:
```yaml
inputs:
npc_registry:
npcs:
source: narratio.extraction.npc_registry
required: true
```
Resolution must remain manifest-first and verify that the recorded artifact
was produced by a successful current `extract` stage. A required extraction
source that is unavailable must fail analysis with guidance to configure or
rerun `extract`; an optional source may be omitted according to the existing
Scriptorium input contract.
Required missing extraction inputs fail with guidance to enable/configure or
rerun `extract`. Optional missing inputs follow the existing Scriptorium input
contract.
Publish source resolution should accept configured
`narratio.extraction.<output-key>` sources through the same artifact catalog so
operators may publish selected structured artifacts without manually copying
paths. The existing `--artifacts` flag remains scoped to Scriptorium artifact
selection and must not partially execute the Notarius pipeline.
Narratio never injects every extraction output into every analysis. Each
Scriptorium artifact chooses the smallest useful set. This limits context
size, cost, and the risk of treating derived claims as transcript authority.
Analysis prompts should continue to treat the transcript as authoritative and
Notarius artifacts as structured, cited, derived evidence.
No current-session analysis artifact should consume an incidental file from a
failed, stale, skipped, or superseded extraction run.
The existing `--artifacts` selection remains scoped to Scriptorium artifacts.
It does not select Notarius lanes or partially run the Notarius pipeline.
## Failure, Skip, Resume, And Diagnostics
## Publish Integration
- Missing or invalid enabled Notarius configuration fails configuration
validation before stage execution where statically discoverable.
- A disabled or absent Notarius configuration makes `extract` skip with clear
stage metadata and no new outputs.
- A missing or invalid final trimmed transcript fails `extract` before starting
Notarius.
- Preflight failure, nonzero Notarius exit, cancellation, timeout, malformed or
unsupported receipt/index data, unsafe paths, incompatible descriptors,
rejected required outputs, or missing configured lanes fails the entire
stage.
- Process success does not override Narratio's required-output policy.
- A failed run retains bounded run-local receipt bytes, stderr, and the
unpublished Notarius bundle for diagnosis, subject to Narratio's existing
sensitive-data and cleanup policies.
- The canonical bundle and manifest artifacts are updated only after complete
validation and materialization.
- Resume skips a succeeded, non-stale `extract` stage only when its
manifest-recorded canonical index and configured lane outputs still validate.
- Force and staleness behavior follows the ordinary stage contract; it must not
depend on merely finding `artifacts/notarius/` on disk.
Publish source validation and resolution accept configured
`narratio.extraction.<key>` sources through the shared runtime artifact
catalog. Operators may publish individual structured lanes without manually
copying files.
Transcripts, Notarius outputs, evidence context, manifests, receipts, and logs
are private campaign material. Subprocess arguments and manifest metadata must
not contain secrets. Credentials remain in the environment or in mechanisms
owned by Notarius and PromptKit.
The Notarius bundle is not automatically published wholesale. Bundle files or
lanes are published only through explicit configured publish rules. Existing
publish locking, destination safety, commit ordering, and required/unselected
artifact behavior remain unchanged.
## Maintained D&D Example
## Failure And Diagnostic Semantics
Add or update a Narratio example that enables Notarius's complete
`dnd-session` pipeline and maps these ten required lanes to stable extraction
keys:
The stage fails before invoking Notarius when enabled configuration or the
final trimmed transcript is invalid.
| Output key | Notarius lane ID |
The stage fails after invocation for:
- cancellation or timeout;
- nonzero process exit;
- malformed, oversized, or unsupported receipt data;
- malformed or unsupported index data;
- unsafe receipt, descriptor, or filesystem paths;
- symlinks or special files in the promoted bundle;
- mismatched receipt pipeline identity;
- missing configured lanes;
- duplicate lane descriptors;
- rejected required lanes;
- incompatible media type, schema identity/version, or module key;
- empty or syntactically invalid required JSON payloads;
- checksum or promotion failure; or
- manifest persistence failure.
Process success alone does not establish consumer success. Notarius may exit
zero while omitting or rejecting a lane, and Narratio's configured required
set remains authoritative.
Failure retains bounded receipt and stderr diagnostics plus the run-local
bundle where available. Durable artifact storage and extraction source records
are updated only after complete validation and promotion. A promoted unique
bundle whose later manifest save fails is unreferenced and may be reclaimed by
explicit cleanup; it is never inferred as current.
## Security And Privacy
Transcripts, Notarius lanes, evidence context, manifests, receipts, warnings,
rejections, debug data, and logs are private campaign material.
- Secrets do not appear in command arguments, generated configuration,
artifact metadata, logs, examples, or documentation.
- Credentials continue to enter through Notarius and PromptKit's documented
environment or secret mechanisms.
- Receipt and index paths are untrusted external input until confined.
- Recursive promotion never follows symlinks or copies special files.
- Diagnostics remain bounded and do not echo payload bodies.
- Automatic cleanup follows Narratio's existing post-publish gates and path
safety rules; it does not silently remove immutable extraction bundles
outside an explicit covered policy.
## Maintained Complete D&D Example
Add a maintained example that enables Notarius's complete `dnd-session`
pipeline and maps these required lanes:
| Extraction key | Notarius lane ID |
| --- | --- |
| `item_registry` | `item-registry` |
| `npc_registry` | `npc-registry` |
@@ -274,106 +505,100 @@ keys:
| `location_occurrences` | `location-occurrences` |
| `enemy_events` | `enemy-events` |
The example must include each lane's current media type and schema identity
from Notarius's published contracts. It should also demonstrate at least one
Scriptorium analysis artifact consuming one or more
`narratio.extraction.*` sources. The example must use placeholders and relative
paths suitable for the example tree, contain no credentials, and pass the
repository's configuration validation tests.
The example obtains exact media types and schema identities from Notarius's
published contracts at implementation time. It demonstrates at least one
Scriptorium artifact consuming a small, purpose-specific subset of extraction
sources. It uses only placeholders and repository-relative example paths,
contains no credentials, and passes maintained example validation.
## Compatibility Policy
## Documentation Deliverables
The initial integration baseline is the public subprocess contract available
in Notarius v0.3.0:
When implementation lands, update current-behavior documentation in the same
change:
- successful JSON receipt schema `notarius.run-result.v1`;
- production JSON bundle discovery through `index.json`; and
- the schema IDs and versions explicitly configured for required lanes.
Runtime compatibility should be decided from those published contracts, not
from textual parsing of `notarius --version`. New optional receipt or index
fields must not break Narratio. An unsupported receipt version or lane schema
must fail before the artifact is registered for analysis.
## Documentation Deliverables When Implemented
Update current-behavior documentation in the same change that implements the
feature:
- add `docs/integrations/notarius.md` for the external CLI, receipt, bundle,
and adapter contract, linking to Notarius's canonical documentation;
- add `docs/internal/stage-extract.md` for stage inputs, outputs, collaborators,
state transitions, failures, and focused tests;
- update `docs/internal/adapters.md`, `docs/internal/artifacts.md`,
`docs/internal/manifest.md`, and the internal stage inventory;
- update `docs/policy/architecture.md` to list Notarius among isolated external
systems and preserve the adapter/stage boundary;
- add `docs/integrations/notarius.md` for the consumed CLI, receipt, index, and
compatibility contract, linking to Notarius's canonical documentation;
- add `docs/internal/stage-extract.md` for stage flow, collaborators, state,
failures, resume validation, and focused tests;
- update `docs/internal/overview.md`, `docs/internal/adapters.md`,
`docs/internal/artifacts.md`, `docs/internal/manifest.md`, and
`docs/internal/workspace.md` within their canonical scopes;
- update `docs/policy/architecture.md` for the Notarius boundary and explicit
skipped/resume-validation contracts;
- update `docs/config.md`, `docs/cli.md`, `docs/operations.md`,
`docs/troubleshooting.md`, `README.md`, and maintained examples only to the
extent their canonical scopes require; and
- update `docs/development.md` only to the extent its canonical contributor
routing scope requires.
`docs/troubleshooting.md`, `README.md`, and maintained examples only within
their canonical scopes; and
- update `docs/development.md` only if its contributor routing changes.
Outside this roadmap, do not describe `extract`, Notarius configuration, or
`narratio.extraction.*` sources as implemented until the code exists.
Outside this roadmap, do not describe the feature as implemented until its
code and documentation are complete.
## Testing And Validation Expectations
## Testing Expectations
Implementation should provide focused tests for:
Tests should protect contracts and meaningful risks rather than private helper
structure. The implementation plan assigns detailed ownership, with coverage
for:
- strict configuration decoding, defaults, required fields, path resolution,
output-map validation, normalized-key collisions, and example loading;
- exact stage order, selection, downstream staleness, resume, force, and
prerequisite behavior;
- adapter command construction, deterministic working directory, environment
inheritance, stdout/stderr separation, cancellation, timeout, and nonzero
exits;
- supported and unsupported receipt versions, unknown optional fields,
malformed receipts, index decoding, and path escapes at every boundary;
- descriptor lookup by lane ID rather than filename, expected metadata checks,
missing/rejected configured lanes, and tolerated unconfigured lanes;
- run-local execution, transactional canonical-bundle replacement, checksums,
failed-run preservation, and manifest recording;
- artifact-catalog resolution from `narratio.extraction.*` into analysis and
publish, including required, optional, missing, stale, and skipped cases; and
- end-to-end stage execution with a fake Notarius adapter, without live LLM or
external subprocess requirements in the ordinary test suite.
- strict configuration, defaults, normalization, cross-source validation, and
maintained examples;
- stage result dispositions and clearing of self-skipped outputs;
- backward-compatible artifact metadata serialization;
- exact adapter arguments, streams, cancellation, timeout, exit behavior,
receipt/index compatibility, and every path-confinement boundary;
- recursive promotion safety, atomic visibility, cleanup on failure, symlink
rejection, and immutable destination behavior;
- required-lane policy, descriptor compatibility, JSON syntax, checksums, and
provenance;
- canonical order, single-stage selection, force, staleness, resume
validation, and enable-after-skip behavior;
- manifest-backed extraction catalog resolution for required, optional,
missing, stale, skipped, incompatible, and tampered artifacts;
- analyze and publish integration without automatic lane injection; and
- representative assembled execution with a fake Notarius runner and no live
LLM, credentials, or external subprocess in the ordinary test suite.
Run the repository-wide Go tests, vet, build, and maintained example validation
after focused tests pass.
Repository-wide tests, vet, build, and maintained-example validation are
required after focused tests pass.
## Acceptance Criteria
- `extract` is a first-class transactional stage between `render` and
`analyze` everywhere Narratio models stage order or state.
- Narratio invokes Notarius only through a narrow, tested adapter.
- The stage consumes the manifest-resolved final trimmed Seriatim transcript.
- The Notarius configuration remains owned by Notarius; Narratio configures
only invocation and its downstream consumer contract.
- Every configured output is discovered through the receipt and `index.json`,
contract-checked, materialized transactionally, and recorded with a stable
`narratio.extraction.*` source ID.
- The complete D&D example maps all ten current lanes and passes strict config
validation.
- Analysis can consume extraction sources through the existing artifact input
model, and publish can select them through the artifact catalog.
- Failed, partial, rejected, unsafe, stale, or incompatible output never becomes
a current analysis input.
- Resume and force behavior remains manifest-driven.
- Documentation accurately describes the implemented stage, adapter,
configuration, operations, and compatibility boundary without duplicating
Notarius's canonical schemas.
- `extract` is a first-class stage between `trim` and `render` everywhere
Narratio models stage order and lifecycle.
- Narratio invokes Notarius only through a narrow tested adapter.
- Extraction consumes the manifest-resolved final trimmed Seriatim JSON.
- Disabled extraction is recorded as skipped and runs normally if later
enabled.
- Successful resume requires valid manifest-recorded immutable outputs rather
than filesystem presence alone.
- The complete bundle is promoted to a unique immutable directory without
following symlinks or exposing a partial destination.
- Every configured lane is discovered by lane ID, contract-checked, checksummed,
and recorded with explicit source identity and external provenance.
- Analysis and publish resolve extraction sources only from a current
successful extract manifest record.
- Failed, skipped, stale, partial, rejected, unsafe, incompatible, or tampered
output never becomes a current input.
- The complete D&D example maps all ten current lanes and demonstrates curated
analysis inputs.
- Tests remain deterministic, offline, and independent of real Notarius,
PromptKit, LLM providers, and credentials.
- Current-behavior documentation is updated only as implementation becomes
complete.
## Non-Goals
- Reimplementing Notarius extraction, prompts, schemas, references, retries,
profiles, or lane orchestration in Narratio.
- Allowing one Narratio run to invoke arbitrary extractor programs or multiple
Notarius pipelines.
- Making `extract` a configurable DAG or folding it into the Scriptorium
`analyze` stage.
- Partially selecting Notarius lanes through Narratio's `--artifacts` flag.
- Decoding D&D payload bodies in the generic Notarius adapter.
- Supporting previous-session extraction artifacts in the initial feature.
- Reimplementing Notarius extraction, configuration, schemas, prompts,
references, retries, profiles, validation, or lane orchestration.
- Supporting arbitrary extractor programs or multiple Notarius pipelines in
one Narratio run.
- Turning canonical stage execution into a DAG or generic workflow engine.
- Folding extraction into `analyze` or Scriptorium.
- Automatically injecting all structured outputs into every prompt.
- Selecting Notarius lanes through Narratio's `--artifacts` flag.
- Decoding D&D payload bodies in the generic adapter or stage.
- Automatically detecting changes throughout Notarius's referenced config,
PromptKit profile, and campaign-reference closure.
- Supporting previous-session extraction sources in the initial feature.
- Automatically publishing the complete Notarius bundle.
- Requiring live Notarius, PromptKit, an LLM provider, or external services in
the ordinary unit test suite.
the ordinary test suite.