From 2ef7c76d9911c9cf3b5610844084a67445f9adbd Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Sat, 29 Aug 2026 17:47:15 +0000 Subject: [PATCH] Add post-transcript implementation plan --- docs/roadmap/implementation.md | 1175 ++++++++++------- .../post-transcript-artifact-workflow.md | 66 +- 2 files changed, 711 insertions(+), 530 deletions(-) diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index e0b964c..6a0ad64 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,546 +1,779 @@ -# Notarius v0.6 CLI References Implementation Plan +# Post-Transcript Artifact Workflow Implementation Plan ## Purpose And Status -This is the executable implementation plan for the accepted target state in -[Notarius v0.6 CLI Reference Integration](notarius-v0.6-cli-references.md). It -is written for a `gpt-5.6-terra` coding agent that will implement exactly one -pending stage per prompt, in order. +This document is the executable implementation plan for +[`post-transcript-artifact-workflow.md`](post-transcript-artifact-workflow.md). +That roadmap owns the accepted user intent, compatibility policy, and target +state. This plan translates it into bounded stages suitable for one +`gpt-5.6-terra` implementation prompt apiece. -The feature roadmap owns user intent, architectural boundaries, settled policy, -and the target end state. This document owns delivery order, concrete changes, -test allocation, and implementation status. Do not restate or change a roadmap -decision here during implementation; if current Notarius v0.6.0 evidence -contradicts the roadmap, stop and record the conflict instead of inventing a -different contract. +All stages below are pending and must be implemented in numeric order. A later +stage may rely on every earlier stage having been completed, tested, documented +where directed, and committed. Do not use this plan to redesign the accepted +feature. If existing code makes a specified name awkward, preserve the stated +behavior and ownership boundaries rather than introducing a second workflow +model. -| Stage | Outcome | Status | -| ---: | --- | --- | -| 1 | Add the reference-selector and configuration vocabulary, including optional spell-catalog inputs. | Completed | -| 2 | Materialize and inventory the optional spell catalog through the prepare and operator lifecycle. | Completed | -| 3 | Centralize manifest-authoritative prepared-input resolution and migrate analyze to it. | Completed | -| 4 | Add deterministic Notarius v0.6 reference arguments at the subprocess adapter boundary. | Completed | -| 5 | Resolve references in extract and bind fingerprints, resume, and metadata to their identities. | Completed | -| 6 | Prove assembled extraction lifecycle and downstream invalidation behavior. | Completed | -| 7 | Update canonical documentation and maintained examples for the completed feature. | Completed | -| 8 | Perform compatibility, quality, and repository-wide closure validation. | Completed | +## Settled Implementation Decisions -## Governing Decisions +The following choices make the plan decision-complete: -The following requirements are settled and are not questions for the -implementing agent: - -1. `pipeline.notarius.references` is a map whose key is a Notarius v0.6 CLI - reference selector and whose value is a prepared Narratio source ID. It is - not a map of paths. -2. Every configured binding is required. There is no per-entry `required` - field. An optional Notarius reference is omitted by omitting the map entry. - An empty or omitted map remains valid for custom pipelines and backward - compatibility. - The map is limited by the centrally declared configuration constant - `MaxNotariusReferenceBindings = 256`, which is far above the four-entry - maintained D&D case while bounding argv and manifest growth. -3. The supported prepared reference sources are - `narratio.input.party`, `narratio.input.players`, - `narratio.input.glossary`, and `narratio.input.spell_catalog`. - Arbitrary Notarius slot names and qualified selectors may bind those sources; - direct paths and later-stage artifacts may not. -4. Campaign and session `spell_catalog_file` are optional. A session value - overrides the campaign value; an empty session value inherits the campaign - value. A `narratio.input.spell_catalog` reference binding requires an - effective configured file. -5. Prepared sources are authoritative only when the current session manifest - records the matching canonical input and checksum. Consumers do not fall - back to campaign/session source paths or accept an incidental workspace file. -6. Narratio passes absolute prepared-file paths to Notarius. Fingerprints and - metadata use the canonical workspace-relative path identity together with - selector, source ID, SHA-256 checksum, and size so workspace relocation does - not become the only identity signal. -7. External CLI references are sorted by normalized selector. They override - matching external references in the Notarius configuration. Narratio never - emits `--without-reference`, the deprecated `roster` alias, or CLI bindings - for generated D&D artifact handoffs. -8. Notarius remains authoritative for whether a selected target declares a - slot, accepted reference media types and sizes, generated-handoff collisions, - pipeline topology, and D&D payload schemas. Narratio validates selector - structure and its own source contract only. -9. Notarius v0.6.0 is the minimum supported CLI contract when references are - configured. Do not add version-string parsing or an automatic per-session - `notarius config validate` subprocess. -10. The existing receipt-v2, bundle-confinement, diagnostic, ten-lane selection, - immutable promotion, and analysis-source behavior must remain intact. -11. The default test suite remains offline, deterministic, and independent of - a sibling checkout or installed Notarius binary. A real v0.6.0 smoke run is - useful supplementary evidence when locally available, not a default-suite - dependency. -12. Add no external Go dependency for this feature. Use narrow owner-specific - types and existing file, path, artifact, manifest, adapter, and stage - facilities. +- The canonical order is `prepare`, `transcribe`, `merge`, `polish`, + `normalize`, `trim`, `render`, `extract`, `analyze`, `publish`, `notify`. +- Execution order remains a flat, fixed registry. Invalidation uses a separate + fixed direct-dependency table whose transitive closure is returned in + canonical order. It is not configurable and is not an execution DAG. +- `run` and `session plan` share one inclusive contiguous-range selector. + Omitted endpoints select the beginning or end of the canonical registry. +- A bounded `run` requires every excluded prefix stage to have a terminal + manifest status of `succeeded` or `skipped`. The first absent, pending, + running, failed, stale, or interrupted prerequisite is an actionable error. + Excluded prefix stages are not resume-validated or repaired; selected stages + still validate the concrete inputs they consume. Stages after `--through` + are not prerequisites and receive no analogous check. +- `--force` affects only selected pipeline stages. Invalidation may mark a + dependent outside the range stale, but cannot execute it. +- `--artifacts` is valid only when the selected range contains `analyze` or + `publish`. Its existing repeatable, comma-separated normalization and + deduplication semantics remain unchanged. +- `regenerate-artifacts` performs argument expansion and calls the canonical + `run` handler. It owns no planner, runner, prerequisite, or force behavior. + Duplicate `--force`, `--from`, or `--through` options are rejected by the + shared bounded-run parser, including `--name=value` spellings. +- Incremental state is specific to configured Scriptorium artifacts inside the + fixed `analyze` stage. Do not create dynamic stages, generic jobs, or a + general subtask framework. +- The session manifest owns current artifact availability. A configured output + file found on disk without current manifest evidence is unavailable. +- Analysis fingerprints contain only Narratio-observable semantic inputs. They + exclude run IDs, absolute workspace paths, timeouts, and executable contents. + They also cannot observe arbitrary files or transitive configuration loaded + privately by Scriptorium; those changes require explicit force. +- Partial analysis preserves unrelated current records. On an error, the + runner accepts a restricted analyze-state result alongside the error so it + can record completed, failed, and newly stale artifact state before marking + the aggregate stage failed. It must never promote unvalidated files. +- Legacy aggregate-only analysis output remains readable but is not current + evidence. Only regenerated artifacts enter the new per-artifact state. ## Instructions For Every Stage -For each implementation prompt, the coding agent must: +Before changing code in each stage: -1. Read `docs/development.md`, all three files under `docs/policy/`, the feature - roadmap, this plan, and the stage-specific documents and source named below. - Inspect the current tree because earlier stages may have changed names or - ownership boundaries. -2. Use the repository knowledge graph first for code discovery and call tracing; - use text search for documentation, configuration, examples, string literals, - and evidence the graph cannot supply. -3. Confirm the worktree state and preserve unrelated changes. Implement only the - current stage. Do not begin a later stage merely because an adjacent file is - open. -4. Keep production code, focused tests, fakes, and fixtures consistent within - the stage. Remove superseded helpers when their final caller migrates. Do not - retain two competing source maps, path resolvers, fingerprint paths, or - subprocess argument builders. -5. Follow the testing policy's ownership rule. Parser/config tests own selector - and configuration cases; artifact tests own prepared-file identity and - integrity; adapter tests own exact arguments; stage tests own orchestration and - resume; application tests own lifecycle invalidation. Do not repeat every - lower-level case at higher levels. -6. Keep errors actionable and content-free. They may identify a selector, - Narratio source ID, canonical path, or checksum mismatch, but must not include - reference contents. Preserve ordinary group-workspace permissions and - restrictive API-key handling. -7. Run `gofmt` on changed Go files and focused tests while iterating. Before - marking any stage complete, run at minimum: +1. Read `docs/development.md`, its task-specific references, all documents in + `docs/policy/`, this plan, and the relevant portions of the feature roadmap. +2. Inspect the current implementation before editing. Prefer the codebase + knowledge graph for code discovery, then read the exact owning files. +3. Confirm the worktree state and preserve unrelated user changes. - ```sh - go test ./... - go test -race ./... - go vet ./... - go build ./... - go test ./internal/doccheck - go test ./internal/config -run '^TestExamplesLoadAndValidate$' +During each stage: + +- Keep changes within that stage's scope and the accepted roadmap. +- Follow the architecture policy's dependency direction, filesystem safety, + manifest authority, and application-owned lifecycle rules. +- Follow the testing policy: place behavior at its narrowest public owner, use + fakes at owned boundaries, keep the default suite offline and deterministic, + and avoid duplicating the same assertion across layers. +- Update a canonical current-behavior document in the same stage when that + stage changes already usable behavior. Do not describe unimplemented later + stages as current. +- Preserve backward-compatible manifest reads and emit only the new canonical + representation after its writer is introduced. +- Run focused tests during development, then `go test ./...` before completing + the stage. Run the repository's required formatting, static checks, and + documentation checks identified by `docs/development.md`. + +At the end of each stage, leave a cohesive change that can be reviewed and +committed independently. Do not begin a later stage while an earlier stage has +failing tests or incomplete acceptance criteria. + +## Stage 1 — Canonical Order And Dependency-Aware Invalidation + +### Goal + +Move `render` before `extract` and replace suffix-based invalidation with the +fixed dependency relation required by the feature roadmap. + +### Required Work + +1. Change the single canonical stage registry so `render` immediately follows + `trim` and `extract` immediately follows `render`. Do not add a second stage + list in a command or test helper. +2. In the application orchestration owner, define a fixed table of direct + invalidation edges: + - `prepare -> transcribe` + - `transcribe -> merge` + - `merge -> polish` + - `polish -> normalize` + - `normalize -> trim` + - `trim -> render, extract` + - `render -> analyze` + - `extract -> analyze` + - `analyze -> publish` + - `publish -> notify` + - `notify ->` none +3. Compute transitive dependents from that table and return them in canonical + order. Unknown stages must return an error; callers must not silently treat + them as having no dependents. +4. Validate the relation against the canonical registry when it is constructed + or first used. Reject duplicate registry names, unknown edge endpoints, + cycles, missing stage classifications, and registry/table drift. +5. Route every existing invalidation trigger through this owner: force, + non-resumable success, failure, and changed effective outcome. Retain the + existing rule that only succeeded dependent records become stale and retain + the existing no-op treatment for an identical repeated self-skip. +6. Remove assumptions that invalidation is the canonical suffix. In + particular, `render` and `extract` must never invalidate one another, while + either invalidates `analyze`, `publish`, and `notify`. +7. Update the architecture policy, internal overview, and focused render, + extract, and manifest documentation for the implemented order and separate + invalidation owner. + +### Tests And Exit Criteria + +- Registry/planner tests assert the complete new order. +- Table-driven invalidation tests assert every transitive set in the feature + roadmap, canonical output ordering, render/extract independence, unknown + stages, cycle rejection, and inventory drift rejection. +- Representative runner tests prove each invalidation trigger uses the new + relation and does not execute newly stale stages implicitly. +- Existing manifests with stable stage names remain readable and resumable; + no version-based invalidation or manifest migration is introduced. + +## Stage 2 — Shared Bounded Plan Selection + +### Goal + +Give the application one validated representation of a contiguous canonical +stage range, shared by execution and plan preview. + +### Required Work + +1. Extend the application planner with a bounded-plan constructor accepting + optional `from` and `through` names. The returned plan contains an inclusive + contiguous slice of the canonical registry. +2. Default an omitted `from` to the first stage and an omitted `through` to the + last stage. Preserve the current full plan when both are omitted. +3. Reject unknown endpoints and a `from` endpoint occurring after `through`. + Errors must name the bad value or reversed pair and list or point to valid + canonical stage names. +4. Put range membership and endpoint information on one application-level + value so `run`, `session plan`, prerequisite validation, and adapter + composition do not independently recalculate bounds. +5. Keep `run-stage` and the dedicated `analyze` and `publish` conveniences on + their existing single-stage paths. Do not reinterpret them through new + range flags. + +### Tests And Exit Criteria + +- Planner tests cover every endpoint, one-stage ranges, omitted starts, omitted + ends, a full omitted range, unknown names, reversed ranges, and stable order. +- Tests assert that selecting a range cannot create a non-contiguous plan or + mutate the canonical registry. +- No CLI behavior changes in this stage; the new planner API is ready for both + `run` and `session plan` to consume next. + +## Stage 3 — Bounded `run` And `session plan` Command Contracts + +### Goal + +Expose the shared range through both commands with one parsing and structural +validation contract. + +### Required Work + +1. Add repeat-safe singleton option parsing for `--from`, `--through`, and + `--force` to the shared bounded-run command layer. Reject duplicates whether + written as separate arguments or `--name=value`; never use argument order to + choose a winner. +2. Preserve the existing session-oriented argument conventions and common + configuration flags. Preserve repeatable/comma-separated `--artifacts` + normalization and deduplication. +3. Add `--from` and `--through` to `run`, and pass the resulting bounded plan to + the existing runner rather than filtering stages after planning. +4. Add the same bounds, force flag, and artifact selection to `session plan`. + Both commands must call the Stage 2 selector and surface identical range + validation errors. +5. Reject `--artifacts` when the range contains neither `analyze` nor `publish`. + Accept it when either consumer is present, including a single-stage range. +6. Update command help, usage errors, `docs/cli.md`, and `docs/operations.md` for + the inclusive/defaulting behavior. Do not document the alias until Stage 5. + +### Tests And Exit Criteria + +- Command tests cover valid ranges, defaults, invalid/reversed ranges, + singleton duplicates in both syntaxes, and artifact/range compatibility. +- Unbounded `run` and unbounded `session plan` retain their prior behavior + except for the canonical order implemented in Stage 1. +- Parsing tests assert structural equivalence between the run and plan range + values, without duplicating all planner cases at the command layer. + +## Stage 4 — Bounded Runner Prerequisites And Composition + +### Goal + +Make bounded execution honor its mutation boundary while still failing safely +when excluded upstream work cannot support the selected stages. + +### Required Work + +1. Before starting a bounded run, inspect the session manifest for every + canonical stage before `--from`. Accept only `succeeded` or `skipped` as a + terminal prerequisite status. Treat an absent record and every other status + as unusable. +2. Report the first unusable prefix stage in canonical order, its status (or + absence), the selected start, and an actionable suggestion to widen the + range or recover that stage explicitly. Do not mutate the manifest, create a + run record, or invoke an adapter before this check succeeds. +3. Do not call resume validators for excluded prefix stages. Concrete selected + stages continue to resolve and validate their own manifest-authoritative + inputs, so an unsafe or missing artifact still fails at its owning boundary. +4. Do not inspect stages after `--through` as prerequisites. They may become + stale through Stage 1 invalidation, but must not be scheduled. +5. Ensure force decisions are calculated only for stages in the bounded plan. + A forced selected stage may stale dependencies outside the range but cannot + execute them. +6. Make production composition plan-aware. Initialize and validate only the + external adapters, object storage, remote locks, and other collaborators + needed by selected stages or by shared session lifecycle requirements. + Preserve each selected stage's current fail-fast configuration validation. +7. Keep post-publish cleanup conditional on publish actually executing. +8. Update operational and troubleshooting documentation for prerequisite + failures, recovery, excluded-stage behavior, and plan-aware composition. + +### Tests And Exit Criteria + +- Runner tests cover every unacceptable prefix status, accepted skipped + prerequisites, no prefix for a first-stage run, and no check after the end. +- Tests prove excluded stages are neither executed nor resume-validated and + that a failed prerequisite check performs no persistent run mutation. +- Adapter-composition tests prove a bounded render-only run does not require + Notarius or Scriptorium, an extract-only run requires Notarius but not + Scriptorium, and analyze requires only its actual collaborators. +- Tests prove force/invalidation can stale an out-of-range dependent without + executing it and that stop-on-selected-stage-failure remains unchanged. + +## Stage 5 — Exact `regenerate-artifacts` Alias + +### Goal + +Add the transparent convenience command without creating another orchestration +path. + +### Required Work + +1. Register the top-level `regenerate-artifacts` command. +2. Implement it only by constructing the equivalent canonical arguments and + invoking the shared `run` parser/handler: + + ```text + run --force --from extract --through analyze [caller options] ``` - Default tests must not contact live services or require credentials. -8. Compare the final diff against the stage goal and exit criteria. Update only - the current stage's status row from `Pending` to `Completed`. Do not mark a - stage complete while a required check fails or required behavior is absent. - Intermediate commits are implementation-branch state and must not be released - before Stage 7 has reconciled current-behavior documentation. + Preserve common session/configuration arguments and all repeatable + `--artifacts` values. +3. Do not add an alias-specific loader, plan, runner, prerequisite check, + summary, artifact rule, or force rule. Canonical run diagnostics may call + the operation `run`. +4. Let the shared duplicate-singleton validation from Stage 3 reject a caller's + `--force`, `--from`, or `--through`, since the alias already supplies them. +5. Give the alias concise help that states the exact expansion, that extraction + always runs, that selected analysis artifacts and required prerequisites are + rebuilt, and that publish/notify never run. +6. Add the alias to `docs/cli.md` and the development workflow in + `docs/operations.md`. -## Stage 1 — Reference And Configuration Vocabulary +### Tests And Exit Criteria -**Read first:** `docs/config.md`, `docs/integrations/notarius.md`, -`internal/config/config.go`, `internal/config/defaults.go`, -`internal/config/load.go`, `internal/config/validate.go`, -`internal/config/notarius_test.go`, `internal/config/campaign_config_test.go`, -and `internal/artifactpolicy/policy.go` and its tests. Read the tagged Notarius -v0.6.0 `docs/cli.md` reference-selector section from `../notarius` when that -checkout is available; otherwise use the canonical link from the feature -roadmap. +- A narrow command test captures the forwarded arguments or resulting shared + command request and proves exact equivalence, including option pass-through. +- Tests prove alias help does not execute, duplicate owned options fail through + the shared parser, and unknown/private alias options are not accepted. +- Do not duplicate runner integration cases under the alias name; its only + behavior is expansion. -**Depends on:** None. +## Stage 6 — Versioned Analyze-Artifact Manifest State -**Goal:** Establish one normalized reference-selector grammar and the strict -configuration model needed by later stages, without adding path-valued Notarius -configuration or making spell catalogs mandatory for every campaign. +### Goal -**Work:** +Introduce a backward-compatible, analyze-specific session-manifest model that +can represent independently current artifacts without treating them as stages. -- Add a small dependency-free `internal/notariusref` package as the contract - owner for Notarius reference selector normalization. Its exported normalizer - must trim the selector and each component, reject empty components and `=`, - and accept only the v0.6 forms `slot`, - `chunk.slot`, `lane.slot`, `lane.extract.slot`, `lane.merge.slot`, and - `lane.normalize.slot`. A three-component selector accepts only `extract`, - `merge`, or `normalize` in its middle component. Do not check the selector - against a Notarius module or lane registry. -- Add `References map[string]string` with YAML key `references` to - `config.NotariusConfig`. During enabled Notarius validation, sort raw keys, - normalize each selector through the shared contract, trim each source value, - reject empty values and normalized-selector collisions, require each value to - be one of the four prepared reference sources, and replace the config map with - its normalized form. Enforce the named, centrally discoverable - `config.MaxNotariusReferenceBindings` limit of 256 entries with an error that - identifies the field and limit. Keep a nil/empty map valid. Rely on strict YAML - decoding to reject duplicate identical keys, but explicitly reject distinct - raw keys that normalize to one selector. -- Add `SpellCatalogFile string` with YAML key `spell_catalog_file` to campaign - inputs and session inputs, plus `SpellCatalogFile ResolvedInputFile` to - resolved stable inputs. Merge it with the existing session-over-campaign - helper. It is not part of the campaign-required input set. Reject a non-empty - configured scalar that becomes empty after trimming. -- Add `artifactpolicy.SourceInputSpellCatalog` and make the artifact-policy - owner describe all four prepared reference sources, including their canonical - manifest kind and filename. Use that owner for stable-source recognition - instead of adding a second switch in configuration validation. Preserve the - existing three source IDs and their behavior. -- Extend cross-configuration validation so a normalized reference to - `narratio.input.spell_catalog` requires a non-empty effective resolved - `spell_catalog_file`. Existing campaign requirements already guarantee party, - players, and glossary declarations. Do not check filesystem existence during - configuration validation. -- If analyze's current private filename switch must change to keep the tree - behaviorally coherent, make it delegate to the artifact-policy descriptor and - recognize spell catalog; Stage 3 will replace the filesystem-only resolver. +### Required Work -**Tests and exit criteria:** At the contract/config owners, cover every accepted -selector shape; zero, empty, excess, invalid-stage, and `=` forms; whitespace -normalization; normalized collisions; unsupported and empty source IDs; nil and -empty maps; exactly the configured binding limit and limit plus one; strict -unknown fields; campaign inheritance and session override; optional omission; -and the cross-config missing-spell-catalog failure. Prefer table-driven parser -and validator tests over assertions against private helper structure. Existing -configuration and example tests must still pass without adding spell catalogs -to every campaign. The codebase has one selector grammar owner and one -prepared-source descriptor owner. +1. Add an explicit analysis-state contract version to the `analyze` stage + record. Absence means legacy aggregate-only state; a present supported + version distinguishes a valid empty set from legacy data. +2. Add a map keyed by normalized configured artifact key. Each record must + contain: + - key and disposition/status (`current`, `stale`, `missing`, `failed`, or + `unselected`); + - fingerprint contract version and fingerprint when evaluated; + - normalized configured dependency keys; + - the existing output artifact record when current, including source ID, + contract, canonical confined path, and checksum, plus a separate + analyze-record output-size field (do not broaden every artifact schema + solely to carry this analyze-specific evidence); + - producer run ID and update time; + - a bounded non-secret error for failed work; and + - useful non-secret Scriptorium provenance, logs, and generated config paths + already allowed by manifest policy. +3. Add the corresponding analyze-artifact collection to invocation-stage + records. A session record describes the reconciled current set; an + invocation record describes only work evaluated or attempted by that run. +4. Keep the schema explicitly owned by analyze. Do not add dynamic stage names + or generic pipeline-subtask abstractions. +5. Extend validation and canonical serialization for the new fields. Validate + normalized unique keys, supported versions, status-specific required and + forbidden fields, output identity, checksum/size, and non-secret bounded + metadata. Maintain deterministic JSON output. +6. Readers must accept old manifests with no new fields. Writers must not + fabricate fingerprints from legacy aggregate outputs or emit parallel + legacy state as current evidence. +7. Preserve per-artifact analysis state when ordinary stage lifecycle helpers + clear aggregate result details during running, failure, or skip. Other stage + records keep their existing behavior. +8. Update `docs/internal/manifest.md` with the new authority, legacy meaning, + status model, and session-versus-invocation distinction. -## Stage 2 — Spell Catalog Prepare And Operator Lifecycle +### Tests And Exit Criteria -**Read first:** `docs/internal/stage-prepare.md`, `docs/internal/workspace.md`, -`docs/operations.md`, `internal/stage/prepare.go` and its tests, -`internal/app/operator_inspection.go`, `internal/app/operator_findings.go` and -their focused tests, `internal/manifest/manifest.go`, and the relevant confined -file-operation helpers. +- Manifest round-trip tests cover every status and deterministic map output. +- Validation tests cover malformed keys, unsupported versions, impossible + status/field combinations, incomplete current output, and bad checksum/size. +- Legacy fixtures remain readable and are explicitly identified as lacking + current artifact evidence. +- Lifecycle tests prove unrelated current records survive transitions while + aggregate output/log/config/metadata fields retain their prior clearing + semantics. -**Depends on:** Stage 1. +## Stage 7 — Runner Projection And Partial-Error State Boundary -**Goal:** Make the effective optional spell catalog a normal prepared session -input with canonical storage, checksum/provenance, safe stale-file handling, and -operator visibility. +### Goal -**Work:** +Give analyze one safe way to promote reconciled session state and invocation +history through the existing application-owned runner transaction. -- Resolve `StableInputs.SpellCatalogFile` with the same origin-preserving - campaign/session behavior as the five existing stable inputs. When configured, - require a regular readable source, copy it atomically to - `inputs/spell_catalog.json`, preserve ordinary workspace permissions, and add - one manifest input record with kind `spell_catalog`, canonical destination, - checksum, and `campaign_config` or `session_config` source provenance. -- Treat the input as optional when no effective path is configured. Do not call - the required-input path resolver with an empty value and do not create a - manifest record. Remove an obsolete canonical `inputs/spell_catalog.json` - without following it when a forced prepare transitions from configured to - absent; refuse to recursively remove a directory or other ambiguous object at - that exact file path. -- Include a configured spell catalog in operator inspection and validation - findings. Omission is not an error unless Stage 1 cross-configuration policy - says the enabled Notarius reference requires it. Reuse the common resolved - stable-input enumeration where practical instead of extending parallel - hand-written lists in several functions. -- Adjust input-slice capacity, deterministic ordering, test fixtures, and any - manifest assumptions affected by the optional sixth stable file. Do not parse - or schema-validate the JSON payload in Narratio; Notarius owns that contract. +### Required Work -**Tests and exit criteria:** Through prepare and operator package behavior, cover -campaign and session source provenance, canonical destination bytes and -checksum, optional omission, missing configured source, replacement after source -change, safe removal when configuration is removed, rejection of an ambiguous -destination object, deterministic manifest ordering, and operator reporting. -Do not duplicate selector-validation cases from Stage 1. Existing sessions with -no spell catalog remain valid and produce no stale manifest entry. +1. Extend the stage result contract with an optional analyze-specific state + projection containing: + - the complete reconciled session analysis state; and + - the invocation subset attempted or evaluated in the current run. + Keep ordinary stage results unchanged. +2. On successful analyze completion, have the runner validate and apply the + session projection to the session manifest and the invocation projection to + the run manifest. Rebuild aggregate session `Outputs` deterministically from + current per-artifact records only. Keep invocation `Outputs` limited to + artifacts actually produced by that invocation. +3. Add a restricted result-plus-error path for analyze. If a stage returns an + error with an analyze-state projection, validate and persist only that state + before marking the aggregate stage failed. Ignore/reject ordinary success + outputs, success disposition, or unrelated stage projections alongside an + error. +4. Apply state only after the stage has validated run-local outputs and safely + materialized the records it marks current. The runner must never derive + records by scanning output directories. +5. On projection validation or persistence failure, fail conservatively and do + not advertise newly attempted artifacts as current. Preserve the last + durable unrelated current records. +6. Add `Force` to the stage environment as application-owned invocation + context, set it from the selected stage decision, and leave unselected + stages unaffected. This will distinguish explicit targets from ordinary + stale prerequisite rebuilding in later stages. -## Stage 3 — Manifest-Authoritative Prepared Input Resolution +### Tests And Exit Criteria -**Read first:** `docs/internal/artifacts.md`, `docs/internal/manifest.md`, -`docs/internal/stage-analyze.md`, `internal/artifacts/artifact_resolver.go`, -`internal/artifacts/resolve.go`, `internal/artifacts/checksum.go`, their tests, -and the prepared stable-input resolution path in `internal/stage/analyze.go` and -`internal/stage/analyze_test.go`. +- Runner tests prove separate session and invocation projections on success. +- Error-path tests prove completed artifacts can be durably represented, the + failed target is not current, unrelated prior current records survive, and + aggregate analyze/publish state remains conservative. +- Tests reject state projection from non-analyze stages and malformed or + contradictory result-plus-error payloads. +- Existing stages and ordinary error behavior remain unchanged. -**Depends on:** Stage 2. +## Stage 8 — Manifest-Authoritative Configured Artifact Evidence -**Goal:** Give analyze and extract one integrity-checked resolver for prepared -stable sources so neither stage trusts incidental files or reconstructs its own -source-to-filename table. +### Goal -**Work:** +Make configured analysis outputs available to analyze and publish only through +validated current manifest evidence. -- Add an artifacts-owned `PreparedInputIdentity` contract containing source ID, - manifest kind, absolute canonical path, slash-separated path relative to the - session root, SHA-256 checksum, and byte size. Add one resolver that accepts - session paths, the current session manifest, and a stable source ID. Provide a - typed or sentinel absence classification so callers can distinguish no current - manifest record from corrupt or unsafe recorded evidence. -- Derive kind and filename exclusively from the artifact-policy descriptor. The - resolver must require exactly one current manifest input record with the - expected kind and canonical path; resolve/rebase recorded local paths through - existing session-local path safety helpers; require the result to equal the - canonical file below `inputs/`; reject escapes, symlinks, non-regular files, - empty files, missing checksums, duplicate records, and checksum mismatches; and - calculate size without loading the complete file into memory. Do not fall back - to the configured campaign/session path or accept canonical file presence - without manifest evidence. Zero matching manifest records is the typed absent - case; once a record exists, a missing or invalid file is an integrity error, - not optional absence. -- Return owner-neutral errors from `internal/artifacts`. At stage boundaries, - wrap unavailable or stale prepared inputs with the source ID and actionable - `narratio run-stage prepare --force` guidance. Do not include file - contents. -- Replace analyze's private prepared-source filename switch and filesystem-only - resolver with the shared artifact resolver. Preserve required-versus-optional - Scriptorium input behavior: a typed absent optional source is omitted, an - absent required source fails with prepare guidance, and invalid recorded - evidence fails regardless of optionality. Make `narratio.input.spell_catalog` - usable wherever another prepared Scriptorium source is accepted. +### Required Work -**Tests and exit criteria:** Artifact-package tests own valid resolution and the -missing-record, duplicate-record, wrong-kind/path, traversal/rebase, symlink, -non-regular, empty, missing-checksum, and checksum-mismatch boundaries. Analyze -tests need only prove required/optional stage behavior and successful use of the -shared source, including spell catalog; do not repeat the artifact resolver's -full matrix. Remove the old filename/path resolver after its final caller moves. +1. Add an analysis-evidence inspector and catalog hydrator analogous to the + extraction-evidence owner, but specific to configured Scriptorium artifacts. +2. For a `current` record, verify the supported state/fingerprint version, + configured key and source ID, contract, configured canonical path, confined + no-follow regular file, stored size, and stored checksum. Return a typed + current/non-current result with an actionable reason. +3. Treat stale, missing, failed, unselected, legacy, removed, malformed, + unsafe, missing, or checksum-mismatched evidence as unavailable. Do not + silently rewrite status during read-only catalog hydration. +4. Remove current-session configured-artifact fallbacks that call `stat` and + mark canonical files available merely because they exist. Hydrate analyze, + publish, operator display, and artifact resolution from the evidence owner. +5. Retain existing behavior for prior-session inputs or other source kinds only + where their canonical owner already has an explicit compatibility policy; + do not broaden filesystem fallback. +6. When current configuration removes or renames a key, omit its old record + from the current catalog even if the manifest retains history until the next + analyze reconciliation. +7. Update `docs/internal/artifacts.md` and `docs/internal/stage-publish.md` for + manifest-authoritative configured results. -## Stage 4 — Notarius Adapter Reference Arguments +### Tests And Exit Criteria -**Read first:** `docs/internal/adapters.md`, `docs/integrations/notarius.md`, -`internal/adapters/notarius/runner.go`, `fake.go`, `subprocess.go`, and focused -adapter tests. Re-read the Notarius v0.6.0 subprocess and CLI reference-selector -contracts from the tagged sibling checkout when available. +- Evidence tests cover valid current output, each non-current status, legacy + absence, config/path/source mismatch, symlink/non-regular files, missing + files, size mismatch, and checksum mismatch. +- Analyze and publish catalog tests prove an incidental file is unavailable and + a validated current record is available. +- Publish tests prove stale configured artifacts cannot be selected or uploaded + while unrelated current artifacts remain publishable. -**Depends on:** Stage 1. +## Stage 9 — Deterministic Analyze Input Identity -**Goal:** Extend the transport-neutral Notarius request and production adapter -to emit safe, exact, repeatable v0.6 `--reference` arguments without changing -receipt or bundle ingestion. +### Goal -**Work:** +Resolve every Narratio-visible analyze input into a stable semantic identity +that the fingerprint engine can consume without depending on workspace paths or +producer runs. -- Add a transport-neutral reference binding containing normalized selector and - absolute path, and add an ordered slice of those bindings to `RunRequest`. - Keep source IDs and manifest identities out of the adapter contract; those are - stage policy. -- Validate each adapter binding before process launch: normalize/validate the - selector through the shared Stage 1 contract, require a non-empty absolute - path, reject duplicate normalized selectors, and avoid mutating the caller's - slice. Do not open or parse the reference file in the adapter. -- Build arguments as repeated pairs `--reference`, - `=` after `--output-dir` and before - `--json`. Preserve one argument for the combined selector/path value so spaces, - additional `=` characters within the path portion, and platform separators do - not involve shell interpretation. The request order is authoritative; Stage 5 - will supply sorted bindings. -- Preserve current executable, environment, timeout, cancellation, diagnostic, - receipt-v2, bounded-read, confinement, and bundle-discovery behavior. Do not - add `--without-reference`, generated reference arguments, version probing, or - configuration preflight. -- Update the fake only as required to retain and expose the extended request. +### Required Work -**Tests and exit criteria:** Adapter tests own exact argv with zero and multiple -references, position before `--json`, spaces and `=` in paths, selector -normalization, duplicate/invalid selector rejection, relative/empty path -rejection, and no subprocess start after request-validation failure. Existing -receipt-v2 and bundle fixture tests must remain unchanged in meaning and pass. -Do not assert stage-level source sorting here beyond preserving the request -order. +1. Define an ordered input-identity record containing the configured input + name, source ID, required/optional policy, presence/absence, contract, + content checksum, and size. Include a stable session-relative or source-based + logical identity where needed; never include an absolute path. +2. Resolve transcript, prepared-input, extraction-lane, previous-session, and + configured-artifact sources through their existing artifact resolvers and + catalogs. Configured-artifact dependencies must pass Stage 8 evidence. +3. Hash validated regular files using the repository's streaming file-safety + primitives and central size limits. Reuse an already validated manifest + checksum when its owning evidence contract proves it represents the same + bytes; do not read whole artifacts into memory. +4. Represent an absent optional input explicitly so appearance/disappearance + changes identity. A missing required input remains an error. +5. Normalize input ordering independently of Go map iteration while preserving + any configured order whose semantics are observable to Scriptorium. +6. Keep identity resolution read-only. It may inspect files and manifests but + cannot materialize output, update status, invoke adapters, or create run + records. -## Stage 5 — Extract Reference Identity, Invocation, And Resume +### Tests And Exit Criteria -**Read first:** `docs/internal/stage-extract.md`, -`docs/integrations/notarius.md`, `docs/internal/manifest.md`, -`internal/stage/extract.go`, `internal/stage/extract_resume.go`, their focused -tests, the Stage 3 prepared-input identity contract, and the Stage 4 Notarius -request contract. +- Table-driven tests cover every supported source kind, optional absence, + missing required input, unsafe path/type, checksum reuse, and changed bytes. +- Identical bytes at relocated workspace roots produce identical semantic + identities; changed bytes or contracts produce different identities. +- Configured dependencies cannot resolve from incidental or stale files. +- Ordering remains deterministic across randomized map insertion. -**Depends on:** Stages 3 and 4. +## Stage 10 — Versioned Analysis Fingerprints And Reconciliation -**Goal:** Make configured references part of the actual extraction invocation -and durable reuse contract, using one resolution path for initial execution and -resume validation. +### Goal -**Work:** +Classify configured artifacts as current or requiring work from one deterministic +fingerprint contract shared by resume validation, planning, and execution. -- Add one extract-owned reference-resolution helper used by both `Run` and - `ValidateResume`. Iterate normalized config bindings in lexical selector - order, resolve each source through the Stage 3 manifest-authoritative resolver, - and produce both adapter bindings and immutable reference identities. Resolve - every reference before creating run-local receipt, log, output, or promotion - directories and before invoking the adapter. -- Define the fingerprint/metadata identity as normalized selector, source ID, - canonical session-relative slash path, SHA-256 checksum, and byte size. Do not - include contents or original campaign/session absolute paths. Pass only - selector and absolute prepared path to the adapter. -- Extend the extraction fingerprint document with the sorted reference - identities. Keep all existing binary, config path, pipeline, timeout, working - directory, trimmed-transcript identity, and required-output identities. The - result must be independent of YAML map iteration order and must change for a - selector, source, relative path, checksum, or size change. -- Persist `reference_count` and a bounded deterministic `references` metadata - list on successful extraction. Each entry contains exactly `selector`, - `source_id`, `path`, `checksum`, and `size_bytes`. Empty bindings produce count - zero and an empty list. Do not duplicate Notarius reference payloads or - downstream error messages. -- Make resume recompute current reference identities through the same helper - before comparing the configuration fingerprint. A valid changed prepared - input yields a fingerprint mismatch and a non-resumable result so extraction - reruns. Missing, unsafe, or checksum-inconsistent current input is an error - with prepare-force guidance because immediately rerunning extract cannot - succeed. Do not silently reuse the old bundle. -- Preserve explicit disabled-stage skip without resolving references. Preserve - required lane selection, immutable promotion, receipt identity, and bundle - evidence behavior. +### Required Work -**Tests and exit criteria:** Stage tests own sorted request construction for all -four D&D bindings, zero bindings, failure before adapter invocation for an -unavailable source, content-free metadata, and fingerprint changes for each -identity field while remaining stable across map order. Resume tests must prove -reuse with unchanged references, non-reuse after a valid prepared-reference -change, hard failure for missing or checksum-invalid current evidence, and no -reference resolution when disabled. Use the fake adapter; do not duplicate exact -subprocess argv cases from Stage 4. +1. Define a centrally named fingerprint contract version and a canonical + serialization used only as hash input. Do not use ad hoc string concatenation + or Go map serialization. +2. Include all Narratio-observable result-affecting fields: + - normalized artifact key and normalized Scriptorium artifact configuration; + - deterministic dependency keys; + - effective prompt/profile identifiers, render-debug behavior, normalized + output identity, ordered input declarations, and sorted effective vars; + - Stage 9 resolved input identities and current configured-dependency output + identities; and + - result-affecting global Scriptorium configuration that Narratio directly + passes or interprets. +3. Exclude timeout/retry settings, absolute binary/config/output/workspace + paths, run IDs, timestamps, log/config output locations, and executable or + arbitrary transitive file contents. Document that explicit force is required + when an unobserved Scriptorium-private input changes. +4. Compute dependency artifact fingerprints in deterministic topological order + and reject unknown dependencies and cycles through the existing configuration + validation owner. +5. Build a read-only reconciliation function that compares current config, + stored record/version/fingerprint, Stage 8 output evidence, and newly resolved + identities. Return a typed reason for `current`, `stale`, `missing`, `failed`, + `legacy`, `removed`, or otherwise non-resumable state. +6. Fingerprint byte-identical input content identically even when it came from + a forced upstream run with a different producer run ID. -## Stage 6 — Assembled Lifecycle And Invalidation Coverage +### Tests And Exit Criteria -**Read first:** `docs/internal/overview.md`, `docs/internal/manifest.md`, -`docs/internal/stage-extract.md`, `docs/internal/stage-prepare.md`, -`internal/app/runner.go`, -`internal/app/extract_lifecycle_test.go`, and representative full pipeline and -stage fixtures. Inspect existing downstream invalidation tests before adding -new cases. +- Golden or table-driven tests prove deterministic fingerprints across map + order, workspace relocation, and producer run IDs. +- Sensitivity tests change each included semantic field independently and + assert a new fingerprint. Exclusion tests cover timeout, timestamp, run ID, + and absolute-root-only changes. +- Reconciliation tests cover current, tampered output, changed dependency, + optional input transition, legacy record, removed config, version mismatch, + and byte-identical upstream replacement. +- `docs/internal/stage-analyze.md` records the implemented fingerprint boundary + and its explicit limitations. -**Depends on:** Stage 5. +## Stage 11 — Incremental Analysis Work Planning -**Goal:** Prove at the application boundary that prepared campaign context -reaches Notarius and that reference changes cannot leave extraction or later -analysis falsely current. +### Goal -**Work:** +Turn reconciliation results, explicit selection, dependencies, and force into +a deterministic artifact execution plan without invoking Scriptorium. -- Extend the smallest existing assembled runner fixture to execute prepare and - extract with party, players, glossary, and spell catalog bindings. Assert that - the fake Notarius request receives the four canonical prepared absolute paths, - not the original campaign/session source paths, and that the successful - manifest records bounded reference identity. -- Add one lifecycle regression covering a valid reference-content change: - rerun/force prepare so the manifest and prepared checksum change, then verify - extract resume is rejected, Notarius runs again, and succeeded canonical - downstream stages are invalidated according to the existing stage-order - policy. Assert outcomes, not private runner call choreography. -- Add one representative session override case to prove the overridden prepared - bytes/checksum reach extraction. Do not repeat all four configuration merge - cases or artifact-integrity failures already owned by earlier stages. -- Confirm an empty reference map preserves the pre-v0.6 invocation behavior and - that all ten configured D&D lanes remain registered as the same - `narratio.extraction.` sources available to analyze. -- Fix production integration defects exposed by these assembled tests without - broadening the feature or adding a DAG, generic reference workflow, or direct - Notarius payload parsing. +### Required Work -**Tests and exit criteria:** The application-level tests must be deterministic, -offline, and fake only the external Notarius boundary. They must credibly fail -if Narratio passes original paths, omits one configured reference, reuses stale -extraction, or loses a configured lane, while remaining insensitive to private -helper structure and exact non-contractual diagnostics. Earlier focused suites -and the repository baseline remain green. +1. Define explicit targets as the normalized `--artifacts` selection when + present, otherwise all enabled configured artifacts. Preserve existing + unknown/ambiguous-selection validation. +2. Compute the transitive configured prerequisite closure of explicit targets + and order the closure deterministically and topologically. +3. Reuse a prerequisite when Stage 10 classifies it current. Schedule a stale, + missing, failed, legacy, or invalid prerequisite before its dependent. +4. Force only explicit targets. A prerequisite is forced only when it is also + an explicit target; otherwise a current prerequisite is reused. +5. Preserve the existing selection rule: default selection includes enabled + artifacts, while an explicitly named disabled artifact is a valid target. + A disabled configured prerequisite may be reused when current or executed + when it is in a selected target's required closure. Never execute an + unrelated disabled artifact. +6. Retain valid unselected records. Classify artifacts removed or renamed from + current configuration as unavailable in the reconciled session projection. +7. Produce a typed plan containing explicit targets, prerequisite-only work, + reused current artifacts, invalidated/removed records, reasons, and the + deterministic execution order. Keep the function read-only and free of + adapter calls. -## Stage 7 — Canonical Documentation And Maintained Examples +### Tests And Exit Criteria -**Read first:** `docs/policy/documentation.md`, `docs/config.md`, -`docs/operations.md`, `docs/troubleshooting.md`, -`docs/integrations/notarius.md`, `docs/internal/overview.md`, -`docs/internal/adapters.md`, `docs/internal/artifacts.md`, -`docs/internal/stage-prepare.md`, `docs/internal/stage-extract.md`, -`docs/internal/stage-analyze.md`, `examples/README.md`, and all maintained -pipeline, campaign, and session examples affected by the new fields. +- Planning tests cover full/default selection, partial selection, dependency + closure, nested dependencies, current prerequisite reuse, stale prerequisite + rebuilding, target-only force, disabled prerequisites, unknown keys, cycles, + removed configuration, and deterministic order. +- Tests prove valid unrelated records survive the projected result and legacy + unselected outputs do not become current. +- The planner exposes enough typed information for `session plan` and analyze + execution to share decisions rather than recomputing them differently. -**Depends on:** Stage 6. +## Stage 12 — Incremental Analyze Execution And Promotion -**Goal:** Move the completed behavior from roadmap-only future state into its -canonical current-behavior owners and provide valid copyable D&D examples -without duplicating volatile Notarius contracts. +### Goal -**Work:** +Execute the Stage 11 work plan on the successful path, safely promote validated +results, and preserve or invalidate records according to actual output identity. -- Update `docs/config.md` with `pipeline.notarius.references`, its selector-to- - source shape, normalization/validation rules, required-by-presence behavior, - supported stable source IDs, and campaign/session `spell_catalog_file` - precedence and optionality. Keep complete copyable YAML in `examples/`. -- Update `docs/integrations/notarius.md` to the v0.6.0 baseline and exact - repeatable-reference invocation boundary. Explain absolute CLI paths, - precedence over configured external paths, the four maintained external D&D - slots, the generated-handoff exclusion, and unchanged receipt-v2/ten-lane - output compatibility. Link to Notarius's canonical v0.6 CLI and D&D consumer - docs instead of copying its target/module matrix. -- Update operations and troubleshooting with prepared input location, - fingerprint/rerun consequences, operator inspection, missing-reference - diagnosis, and Notarius undeclared-slot/generated-collision failures. Update - internal component documents only with implemented ownership and flow; do not - duplicate configuration field definitions there. -- Add a valid, secret-free sample spell catalog following Notarius v0.6's - published overlay schema, add `spell_catalog_file` to the sample campaign, and - configure all four external reference bindings in the complete annotated D&D - pipeline. Add the same bindings to other Notarius-enabled maintained examples - only when their selected pipeline declares them; do not add a Notarius section - to examples that intentionally omit extraction. -- Ensure the maintained command snippets place repeated `--reference` arguments - before `--json`, use `party` rather than `roster`, and never show generated - handoffs on the CLI. Remove stale v0.5 compatibility wording where it refers to - the supported invocation baseline. +### Required Work -**Tests and exit criteria:** Run documentation-link checks and the example -loader explicitly. Verify every changed example is accepted by strict config -validation, contains no credentials or private infrastructure values, and has -one canonical owner for each volatile fact. Search current-behavior docs and -examples for stale v0.5 invocation wording, deprecated `roster` emission, and -generated D&D CLI handoff examples. Do not mark the roadmap itself implemented; -its status remains target-state context until the implementation sprint is -reviewed and closed. +1. Refactor analyze to execute only scheduled artifacts in deterministic order. + Reused current artifacts must be exposed to later scheduled dependents + through the runtime catalog without invoking Scriptorium. +2. For each scheduled artifact, keep output run-local until the adapter result + and output pass existing safety, contract, size, and checksum validation. + Materialize canonically only through the established file-operation owner. +3. Record the new fingerprint, full output evidence, producer run ID, bounded + non-secret provenance, logs, and generated configs in the Stage 7 projection. +4. After replacement, compare semantic output identity. If bytes/contract are + unchanged, allow an unselected dependent whose recomputed fingerprint is + equal to remain current. If identity changes, mark every unselected + configured dependent stale without executing it. +5. Preserve valid unrelated current records and outputs during partial runs. + Reconstruct aggregate session outputs from all current records; report only + newly produced outputs in the invocation manifest. +6. A partial invocation succeeds when every explicit target and required + prerequisite succeeds, even if unrelated configured records remain stale. +7. Never synthesize a current record from an existing canonical output. -## Stage 8 — Compatibility And Quality Closure +### Tests And Exit Criteria -**Read first:** The feature roadmap, every completed stage diff, the final -current-behavior docs, `.woodpecker/verify.yml`, `.woodpecker/release.yml`, and -`.woodpecker/shuffle.yml`. Re-read the tagged Notarius v0.6.0 -`docs/consumers/dnd-pipeline.md`, `docs/cli.md`, and linked spell-catalog overlay -contract when the sibling checkout is available. +- Analyze tests cover current reuse, partial rerun preservation, nested stale + prerequisite rebuilding, selected force, dependency ordering, changed-output + dependent invalidation, and identical-output dependent preservation. +- Legacy tests prove full selection rebuilds the effective set, while partial + selection promotes only targets/prerequisites and leaves legacy unselected + outputs unavailable. +- Adapter fakes remain offline and assertions focus on requests, resulting + files, manifest records, and catalogs rather than private implementation maps. -**Depends on:** Stage 7. +## Stage 13 — Incremental Analyze Failure Safety -**Goal:** Verify the delivered code matches the accepted boundary, remains -compatible with all ten default D&D artifacts, and is ready for review without -dead compatibility paths or duplicated policy. +### Goal -**Work:** +Complete the incremental executor with conservative, durable behavior for +partial adapter, validation, materialization, and persistence failures. -- Audit the final diff against every target-state and out-of-scope statement in - the feature roadmap. Confirm only four external prepared sources are exposed, - custom selectors remain possible, every configured binding is required, and - no Notarius pipeline topology or generated-handoff logic moved into Narratio. -- Trace initial extract and resume paths to confirm both use the same prepared - identity and reference resolution, the adapter is the sole argv builder, and - artifact policy is the sole source-to-kind/filename vocabulary. Remove dead - helpers, redundant switches, stale fixtures, and low-value duplicate tests - found during this review. -- Confirm the complete D&D example still declares and validates the exact ten - output lanes and that analyze can consume those sources after reference- - enabled extraction. Confirm empty-reference custom pipelines remain supported. -- If a local Notarius v0.6.0 binary and its required offline/test configuration - are already available, perform a non-credentialed smoke invocation with all - four reference flags and record the result in the implementation handoff. Do - not download tools, contact paid providers, add a default test dependency, or - block completion solely because this supplementary environment is absent. -- Run the repository baseline plus the scheduled shuffled suite and release - cross-build commands: +### Required Work - ```sh - go test ./... - go test -race ./... - go test -race -shuffle=on -count=3 ./... - go vet ./... - go build ./... - go test ./internal/doccheck - go test ./internal/config -run '^TestExamplesLoadAndValidate$' - narratio_cross_dir="$(mktemp -d)" - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o "$narratio_cross_dir/narratio-linux-amd64" ./cmd/narratio - CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o "$narratio_cross_dir/narratio-darwin-amd64" ./cmd/narratio - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o "$narratio_cross_dir/narratio-windows-amd64.exe" ./cmd/narratio - ``` +1. At each artifact boundary, retain enough reconciled state to return the + restricted Stage 7 projection if later work fails. Do not report a completion + until its run-local output has been validated and canonically materialized. +2. On failure, mark the active target `failed` with a bounded non-secret error. + Mark any artifact whose current identity depends on the unavailable result + stale, including unselected dependents, without executing them. +3. Preserve unrelated previous current records. Preserve earlier completions + from this invocation only when they crossed the defined materialization and + validation boundary; include them in invocation history. +4. Return the restricted state projection alongside the original error so the + runner can persist artifact state before marking aggregate analyze failed. + Dependency-aware invalidation must keep publish and notify conservative. +5. If persistence of the partial projection itself fails, surface that failure + with the original context, retain the last durable manifest, and treat any + newly materialized file as incidental rather than current evidence. +6. Never mark a failed or unverified artifact current merely because old bytes + remain at its canonical path. Never reconstruct partial success by scanning + output directories after an error. - Cross-builds are compilation evidence only; do not claim native macOS or - Windows runtime validation. +### Tests And Exit Criteria -**Tests and exit criteria:** Every required command passes, `git diff --check` -is clean, the worktree contains no unintended generated test artifacts, and the -implementation is traceably complete against the roadmap. Summarize any -unavailable supplementary smoke evidence without treating it as a product -question or silently weakening the default suite. +- Tests cover first, middle, and last artifact adapter failures; unsafe or + invalid adapter output; canonical materialization failure; and session/run + manifest persistence failure. +- Each case proves the failed target is unavailable, dependent state is stale, + unrelated current work survives, and only durably completed work appears in + invocation history. +- Tests prove old canonical bytes and incidental newly materialized bytes do + not override the durable manifest authority. +- Error wrapping remains actionable and non-secret, and the original adapter or + filesystem cause remains discoverable. + +## Stage 14 — Analyze Resume Validation And Plan/Run Parity + +### Goal + +Make aggregate analyze skipping and `session plan` reflect artifact-level +freshness using the same read-only decision engine as execution. + +### Required Work + +1. Implement an analyze-specific resume validator that runs Stages 8–11 + reconciliation for the requested artifact set. It is resumable only when all + explicit targets and required prerequisites are current and no selected work + is scheduled. +2. A succeeded aggregate analyze record with stale unrelated artifacts may + still skip for a partial selection that does not require them. A later full + selection must not skip them. +3. If coarse stage invalidation marked analyze stale but recomputation proves + selected fingerprints and outputs unchanged, allow analyze execution to + perform zero Scriptorium calls and restore the correct successful aggregate + state through the ordinary runner boundary. +4. Extend `session plan` to invoke the same stage resume validators and analyze + work planner as `run`, using a cloned/in-memory manifest transition model to + account for earlier selected stages and their invalidation. It must not + persist a session manifest, create an invocation directory, materialize a + file, or call an external adapter. +5. Plan output must distinguish pipeline-stage run/skip decisions and, for + analyze, explicit targets, prerequisite-only rebuilds, and current reuse with + concise reasons. Do not promise output identities that require execution. +6. Preserve the rule that excluded stages are never resume-validated. The + Stage 4 prefix status check remains structural and read-only. + +### Tests And Exit Criteria + +- Resume tests cover full and partial selections, force, current/stale/legacy + mixtures, current prerequisites, changed inputs, output tampering, and a + stale aggregate record with semantically current selected artifacts. +- Paired plan/run tests feed the same fixture and assert identical selected + stage and analyze-artifact decisions before execution. +- Side-effect tests prove planning performs no manifest write, run-directory + creation, canonical materialization, or adapter invocation. +- Existing extract resume validation remains functional in bounded and + unbounded plans. + +## Stage 15 — Assembled Workflow And Compatibility Coverage + +### Goal + +Verify the complete feature through production composition and representative +historical state without adding another behavior path. + +### Required Work + +1. Add assembled application tests for: + - an ordinary full run in the new canonical order; + - `run --from extract --through analyze --force` with and without artifact + selection; + - the exact alias reaching the same bounded-run request; + - render-only and extract-only forced runs demonstrating sibling + invalidation independence; + - a later publish consuming only current configured artifacts; and + - stop-on-failure with dependent stages outside the range left stale but + unexecuted. +2. Add compatibility fixtures or focused tests for manifests created under the + old render/extract order and aggregate-only analyze state. Confirm no + transcript stage is invalidated solely by version or old relative order. +3. Exercise a complete legacy transition: partial regeneration, unavailable + unselected legacy output, later full regeneration, then successful publish + from current per-artifact records. +4. Verify production composition does not eagerly require excluded adapters + and that generated run manifests list only the bounded requested stages and + actual invocation artifacts. +5. Remove obsolete suffix-invalidation, aggregate-analysis-replacement, and + filesystem-discovery compatibility code that no current path requires. Keep + any unavoidable compatibility shim narrow, clearly commented with its + removal condition, and covered by a legacy test. + +### Tests And Exit Criteria + +- Assembled tests use controlled fakes and real application wiring; they remain + offline and deterministic. +- The full suite passes under the standard test command and repository race or + platform checks required by policy. +- Coverage is allocated to behavior owners; this stage adds only integration + assertions that smaller tests cannot prove. + +## Stage 16 — Canonical Documentation And Quality Closure + +### Goal + +Bring every current-behavior owner into agreement and perform the final +repository-wide policy and regression check. + +### Required Work + +1. Audit current documentation for the old extract/render order, suffix-only + invalidation, unbounded-only run behavior, aggregate analysis replacement, + and filesystem-discovered configured artifacts. +2. Finalize: + - `docs/cli.md` for range syntax, duplicate singleton rejection, artifact + selection, exact alias expansion, and examples; + - `docs/operations.md` for the post-transcript development loop, force scope, + plan preview, explicit publish, and recovery; + - `docs/troubleshooting.md` for bounded prerequisite failures, stale or + tampered analysis evidence, legacy regeneration, fingerprint limitations, + and explicit force for unobserved Scriptorium inputs; + - `docs/internal/overview.md`, `stage-render.md`, `stage-extract.md`, + `stage-analyze.md`, `stage-publish.md`, `artifacts.md`, `manifest.md`, and + `adapters.md` for their implemented contracts; and + - `docs/policy/architecture.md` for flat canonical execution plus separate + dependency-aware invalidation and contiguous bounded runs. +3. Keep volatile syntax and schema details in their canonical owners. Other + documents should link rather than duplicate large flag or field inventories. +4. Confirm all examples use the new order and that none describe the fixed + dependency relation as a configurable DAG or claim perfect observation of + Scriptorium-private inputs. +5. Run formatting, documentation checks, static analysis, `go test ./...`, and + any race/platform checks required by repository policy. Review the final diff + for accidental generated files, secrets, broad refactors, stale compatibility + branches, and policy violations. +6. Update this plan's status only after all prior acceptance criteria pass. Do + not delete the accepted feature roadmap until the project's normal roadmap + closeout process authorizes it. + +### Tests And Exit Criteria + +- All maintained documentation agrees with implemented behavior and passes the + documentation policy's discoverability and ownership requirements. +- All repository-required checks pass from a clean checkout without installed + external adapter binaries. +- The worktree contains only intentional feature changes, no unresolved TODOs + standing in for this plan, and no known divergence from the feature roadmap. ## Open Questions -None. The feature roadmap and governing decisions above are sufficient to -implement the plan without additional product or architecture choices. +None. The accepted feature roadmap and the settled decisions above are +sufficient to implement every stage without a further product or architecture +choice. diff --git a/docs/roadmap/post-transcript-artifact-workflow.md b/docs/roadmap/post-transcript-artifact-workflow.md index 461f480..8a16fe8 100644 --- a/docs/roadmap/post-transcript-artifact-workflow.md +++ b/docs/roadmap/post-transcript-artifact-workflow.md @@ -193,12 +193,14 @@ override them. The shared command parsing layer should reject duplicate singleton options rather than use ordering to choose a winner. That rule should apply consistently to bounded `run` itself, not only to the alias. -Without `--artifacts`, the alias force-runs extraction and all configured -analysis artifacts. With `--artifacts`, extraction still produces its complete +Without `--artifacts`, the alias force-runs extraction and all enabled +configured analysis artifacts, matching the existing default analysis +selection. With `--artifacts`, extraction still produces its complete configured Notarius bundle, while forced analysis targets only the selected -Scriptorium artifacts and any prerequisites required to build them. It never -runs publish or notify. Changed results may correctly leave those later stages -stale. +Scriptorium artifacts and any prerequisites required to build them. An +explicitly selected disabled artifact remains a valid target under the existing +selection rules. The alias never runs publish or notify. Changed results may +correctly leave those later stages stale. The existing `analyze` command remains the convenience path for forcing analysis without rerunning Notarius. @@ -344,60 +346,6 @@ versioned metadata. Readers must accept older manifests, while new writers must emit one canonical representation and must not maintain parallel legacy and new analysis state indefinitely. -## Required Test Coverage - -Allocate tests to the behavior owner and avoid duplicating every case at every -layer: - -- planner and command tests prove the new canonical order, inclusive range - selection, omitted-bound defaults, invalid/reversed bounds, duplicate-option - rejection, artifact-range validation, and unchanged unbounded behavior; -- alias tests prove exact argument equivalence and pass-through without - re-testing the runner through an independent path; -- invalidation tests prove the complete fixed relation, inventory validation, - deterministic ordering, unknown-stage handling, and render/extract - independence; -- runner tests prove force is confined to the selected range, excluded stages - are not resume-validated or composed unnecessarily, outside dependents may be - staled but not executed, and unusable prerequisites do not widen the range; -- continuation tests cover representative manifests produced under the old - render/extract order; -- analyze tests prove fingerprint stability and sensitivity, dependency - ordering, selected force, stale-prerequisite rebuilding, valid unselected - preservation, changed-dependent invalidation, identical-content reuse, - removed configuration, output tampering, partial failure, and legacy-result - handling; and -- catalog and publish tests prove that only current per-artifact results are - exposed downstream. - -Tests must assert observable plans, manifest transitions, adapter requests, and -artifact availability rather than private map layout. The default suite remains -offline, deterministic, and independent of installed Seriatim, Notarius, or -Scriptorium binaries. - -## Documentation And Policy Changes - -When implementation lands, update all current-behavior owners in the same -change: - -- revise the architecture policy so canonical order owns execution, - dependency-aware invalidation owns affected work, and bounded runs remain - contiguous selections rather than arbitrary workflows; -- document the new order, range flags, exact alias expansion, force scope, - plan behavior, incremental reuse, and legacy-analysis transition in the CLI - and operations references; -- update the internal overview and the focused render, extract, analyze, - manifest, artifact, adapter, and publish documents where their implemented - contracts change; -- update troubleshooting guidance for incomplete bounded prerequisites, stale - analysis artifacts, fingerprint limitations, and forced recovery; and -- remove every current claim that extract runs between trim and render or that - all invalidation is a canonical-order suffix. - -Documentation should continue to describe one explicit pipeline, not a DAG -scheduler. Volatile command syntax and manifest details remain in their -canonical owners rather than being copied across orientation documents. - ## Compatibility And Operational Effects - Existing unbounded `run`, `run-stage`, `analyze`, and `publish` commands keep