Add artifact provenance and stage skip outcomes
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user