Plan session manifest simplification

This commit is contained in:
2026-09-03 00:48:46 +00:00
parent c98b4ef4ef
commit 49324d3f35

View File

@@ -1,80 +1,78 @@
# Workstream 3 Implementation Plan # Workstream 4 Implementation Plan
## Purpose And Status ## Purpose And Status
This is the executable plan for [`refactoring.md`](refactoring.md), Workstream This is the executable plan for [`refactoring.md`](refactoring.md), Workstream
3: **Canonical contracts and compatibility purge**. Finding 1 of 4: **One durable local manifest authority**. Finding 2 of
[`contract-audit.md`](contract-audit.md) and rows C01/H43 of [`contract-audit.md`](contract-audit.md) and rows H14, H15, H17, C02, and C03
[`audit-decisions.md`](audit-decisions.md) own the approved decisions. of [`audit-decisions.md`](audit-decisions.md) own the approved decisions.
All seven stages are complete. Workstreams 1 through 3 are complete. All five stages are pending and must be implemented in order. Each stage is
Workstreams 4 and later remain out of scope for this completed plan: it did not bounded for one `gpt-5.6-terra` prompt. Workstreams 1 through 3 are complete.
remove the run manifest, redesign runner lifecycle, change analyze checkpoint Workstreams 5 and later are out of scope: do not decompose the runner into a
timing, replace locks, decompose publish, or add cleanup. new lifecycle type, redesign pre-execution decisions, add per-artifact analyze
checkpoints, split publish into separate transactions, add cleanup as a stage,
or change remote lock policy while following this plan.
## Settled Implementation Decisions ## Settled Implementation Decisions
- Delete deprecated representations rather than renaming, wrapping, or - The session manifest is the only durable local progress ledger. It alone
preserving them behind an internal compatibility facade. Historical releases records stage status, current artifacts, semantic evidence, diagnostics,
and completed audits remain unchanged. failures, resume authority, restore authority, and publish authority.
- Give both currently persisted local JSON manifest types an explicit required - Delete the structured invocation run manifest completely: its schema and
`schema_version`: `narratio.session-manifest.v1` for `Manifest` and types, store interface and methods, path helper, lifecycle mutations,
`narratio.run-manifest.v1` for `RunManifest`, with discoverable constants terminal recovery, analyze projection, publish dependency, fixtures, tests,
in package `manifest`. Constructors set it; save and load validate it; and current documentation all leave the repository.
neither path fills in a missing or unsupported value. Workstream 4 may later - Do not replace it with another JSON summary, journal, database, or event log.
delete the versioned run-manifest model. Historical per-invocation state is not an operational requirement.
- Loaded current state may not acquire required schema, stage identity, stage - Preserve run IDs. Every invocation still receives one before session state is
records, or analyze authority through normalization. Representation- initialized; it remains the identity used by the session manifest,
preserving normalization may remain. run-local directory, adapter provenance, logs, generated configuration,
- Every newly created `analyze` stage record in either manifest uses receipts, immutable publish prefix, command summary, and diagnostics.
`AnalyzeStateContractVersion`. An empty collection is valid current state. - Explicitly create the canonical run directory once per invocation after the
Version zero, an unknown version, or aggregate-only authority is rejected. session lock and identity checks. Removing the initial run-manifest save must
- The only party input is a strict `narratio.party.v1` document selected by not make diagnostic writers responsible for accidentally creating the run
required, campaign-owned `campaign.inputs.party_file`. Remove unversioned root. Directory-creation failure remains an invocation initialization error.
parties, `campaign.inputs.players_file`, `session.inputs.players_file`, - `RunSummary` remains the immediate in-memory command result and retains
and `session.inputs.party_file`; strict YAML decoding rejects those keys. session ID, run ID, session manifest path, selected stage names, executed
- Players remain the deterministic `narratio.players.v1` projection generated stages, and skipped stages. Remove only `RunManifestPath`; do not add a
from the party. Keep that prepared input, semantic identity, Notarius replacement persistent summary.
reference role, and operator visibility; it is never separately configured. - A run-manifest write can no longer fail an otherwise valid pipeline action.
- Simplify party runtime data to a canonical party and source provenance. Session-manifest transition and terminal-save failures remain correctness
Remove `PartyMode`, both mode constants, the compatibility-only failures and continue to join with the originating error where applicable.
`PartyDocument` shell, and `party_legacy.go`. `ParseParty` returns the - Publish no longer opens or validates `runs/<run_id>/manifest.json`. When
canonical representation directly. `upload_run` is enabled, it derives the current run root canonically and uses
- The only remote current selector is versioned `current/commit.json` and its the session manifest's recorded output, log, and generated-configuration
verified immutable commit. Pointer absence returns a typed references as an allowlist. It includes only safe regular files confined to
current-commit-pointer-missing error with publish/republish guidance. Do not the current run root and ignores records from earlier runs.
inspect `current/run_id.txt` or `current/manifest.json`. - New remote commits do not upload or classify a run manifest. Keep
- Successful current-state loads always contain a validated non-nil pointer, `RemoteArtifactTypeRunManifest` as a read-only wire value so already committed
commit, and committed session manifest. Keep `CurrentPointerKey` and the and verified remote snapshots remain readable; it must have no local loader,
immutable manifest key; remove legacy key names and duplicated fields. path, special publish branch, or newly emitted declaration. This preserves a
- Restore uses only objects declared by the selected commit and never lists a durable remote protocol without retaining the local dual-authority model.
session prefix to reconstruct a snapshot. Preserve committed verification, - Preserve `RemoteArtifactTypeRunFile` for declared run-local diagnostics.
manifest-last installation, conflicts, and root-scoped safety. Publishing no current-run diagnostics is valid and must not require a
- Previous-session hydration resolves each requested source exactly once from placeholder file.
the commit's unique `published_output` declaration. Derive its relative - Remove the invocation subset from `AnalyzeStateProjection` and from analyze
destination from that declaration's immutable destination key. Do not consult execution. During this workstream, analyze still returns and persists one
current config or previous-manifest outputs for alternate paths and do not validated reconciled session collection at the existing end-of-stage
issue candidate `Exists` calls. boundary. Do not implement artifact-by-artifact persistence yet.
- A built-in artifact is authoritative only when its succeeded producer stage - Preserve the current safe behavior when the end-of-stage analyze manifest
has exactly one output matching registered source and kind, with safe path, save fails: incidental output bytes do not establish authority, prior
producer run ID, and checksum. Verify checksum and content. Remove canonical- in-memory analyze authority is restored, and the aggregate stage fails.
path and filename fallback; disk bytes alone never establish availability. Workstream 6 will replace this with the approved checkpoint model.
- Analyze authority comes only from the current versioned `AnalyzeArtifacts` - Preserve current stage ordering, force/invalidation rules, self-skip behavior,
collection. Preserve fingerprints, dependencies, selection, force behavior, aggregate transition timing, cleanup obligations, remote commit ordering,
and existing session/run projections until their later workstreams; remove and command output except where they directly expose the removed run
only aggregate-only and incidental-file compatibility here. manifest.
- Extraction availability continues to require current input and receipt - Delete tests whose only contract is historical run-manifest persistence.
identity, canonical immutable paths, a complete configured source set, Rewrite mixed tests around session state, command summaries, run-local
checksums, contracts, and Notarius provenance. The manifest schema boundary diagnostics, or remote commit contents, and consolidate redundant mechanism
rejects older records; add no extraction migration reader. assertions rather than recreating a second audit record in tests.
- Unsupported state errors identify the missing/received and supported version - Historical release notes and completed audit documents remain unchanged.
and provide concise migration guidance. Tests assert error categories and Current architecture, CLI, operations, troubleshooting, and internal
small stable fragments, not full prose. documentation must describe session-only authority.
- Current docs must direct operators to replace legacy party config, move aside - Mark only Workstream 4 `Complete`, and only after all stages and final
and regenerate unsupported local state, restore a current committed snapshot
when authoritative, or republish healthy local state. Do not rewrite
historical documents.
- Mark only Workstream 3 `Complete`, and only after all stages and final
validation succeed. validation succeed.
## Instructions For Every Stage ## Instructions For Every Stage
@@ -82,334 +80,316 @@ timing, replace locks, decompose publish, or add cleanup.
Before each stage: Before each stage:
1. Read `docs/development.md`, every file under `docs/policy/`, this plan, 1. Read `docs/development.md`, every file under `docs/policy/`, this plan,
Workstream 3 plus dependency/target sections of Workstream 4 plus the dependency and target sections of
[`refactoring.md`](refactoring.md), Finding 1 of [`refactoring.md`](refactoring.md), Finding 2 and the Workstream-4-relevant
[`contract-audit.md`](contract-audit.md), and rows C01/H43 of boundary in Finding 3 of [`contract-audit.md`](contract-audit.md), and rows
H14, H15, H17, C02, and C03 of
[`audit-decisions.md`](audit-decisions.md). [`audit-decisions.md`](audit-decisions.md).
2. Inspect named implementation and focused tests. Prefer the codebase graph for 2. Inspect the named implementation and focused tests. Prefer the codebase
Go discovery and text search for fields, fixtures, examples, and docs. graph for Go discovery and text search for schemas, paths, fixtures,
3. Confirm worktree state and preserve unrelated changes. Do not enter a later documentation, and serialized field names.
workstream because adjacent code would also benefit. 3. Confirm the worktree state and preserve unrelated changes. Do not enter a
later workstream merely because adjacent lifecycle, analyze, publish, or
cleanup code would benefit from broader refactoring.
During every stage: During every stage:
- Keep the repository building and focused tests passing. Temporary current-only - Keep the repository compiling and focused tests passing. A temporary
migration structure is allowed only when a later stage explicitly removes invocation projection or unused run-manifest domain type may remain only
it; add no compatibility shim or automatic migration reader. when the next numbered stage explicitly removes it; do not introduce a new
- Preserve package ownership, strict deterministic decoding, group workspace compatibility facade.
behavior, bounded I/O, secret redaction, remote verification, restore safety, - Preserve package ownership and acyclic dependency direction. Keep this a
and Linux/macOS/Windows support. deletion-oriented refactor inside the existing `app`, `stage`, `manifest`,
- Keep tests offline and behavior-focused. Delete tests only with their retired and `artifacts` owners.
contract. Update canonical current-behavior docs with the code change. - Preserve the session lock, session-manifest atomic replacement, group
- Run `gofmt` on changed Go, focused tests, and `git diff --check`. Mark a workspace modes, bounded I/O, no-follow publish sources, remote verification,
stage `Completed` only after all exit criteria pass. secret redaction, and Linux/macOS/Windows support.
- Update the canonical current-behavior document owned by a change in the same
stage. Do not edit historical release notes or completed audit findings.
- Keep tests offline, deterministic, and behavior-focused. Remove tests with
the retired contract and retain consequential session-state, data-integrity,
recovery, and remote-commit coverage at the narrowest stable boundary.
- Run `gofmt` on changed Go files, focused tests, and `git diff --check`. Mark a
stage `Completed` only after its exit criteria pass.
## Stage 1 — Establish Explicit Current Manifest Schemas ## Stage 1 — Decouple Publish From The Run Manifest
**Status: Completed** **Status: Pending**
### Goal ### Goal
Create an unambiguous local-state boundary before removing downstream legacy Make publish consume only the session manifest and current run directory so the
branches. runner can stop producing a structured run manifest without losing useful
diagnostic uploads.
### Required Work ### Required Work
1. Add the settled schema constants and required `schema_version` fields in 1. In `internal/stage/publish.go`, replace
`internal/manifest/manifest.go` and `run_manifest.go`; set them in `resolvePublishRunManifestPath` with canonical current-run-root resolution
`New` and `NewRun`. based on resolved campaign, session ID, workspace root, and `m.RunID` using
2. Require exact versions in `LocalStore.Save`, `LoadReader`, `SaveRun`, `artifacts.SessionRunRootForCampaign`. Require that exact root to be a real
and `LoadRunReader`. Missing/unknown versions return a clear migration directory and retain existing symlink/non-directory rejection.
error. Saving a hand-built zero-value manifest fails rather than backfilling. 2. Remove opening, decoding, rewinding, and passing a run-manifest file. Change
3. Require a non-nil stage map; reject nil stage entries and embedded stage current-run collection to inspect `manifest.Manifest` stage records and add
names that are empty or differ from their map keys. Remove load normalization only declared `ArchivePath`, fallback `LocalPath`, `Logs`, and
that synthesizes these required markers, retaining only harmless ordering or `GeneratedConfigs` that resolve within the selected current run root.
cloning. Records referring to canonical session files or an older run must not be
4. Make session and run `ensureStage` initialize the analyze contract version uploaded as current-run diagnostics.
and an empty collection for `analyze`. Make 3. Make an empty current-run diagnostic set valid. Refactor the source-opening
`validateAnalyzeStageState` require that version for every present analyze helper so it opens each allowlisted current-run file directly, with the
stage regardless of lifecycle status. Delete version-zero acceptance. existing regular-file/no-follow and optional checksum verification. It must
5. Update current test construction to use constructors or explicit markers. not require a distinguished manifest file.
Cover missing/supported/unknown versions, nil/mismatched stages, newly 4. Remove the `manifest.json` synthetic run-file entry and the special branch
created analyze state, empty current collections, and aggregate-only that emits `RemoteArtifactTypeRunManifest`. Continue emitting ordinary
rejection. current-run diagnostics as `RemoteArtifactTypeRunFile` with deterministic
6. Update `docs/internal/manifest.md`, `docs/internal/artifacts.md`, `run:<relative-path>` source identities and destinations.
`docs/operations.md`, and `docs/troubleshooting.md` with schema and local 5. Preserve session-manifest commit generation, previous-cache uploads,
recovery guidance. Leave party/remote removal for their stages. configured published outputs, immutable upload verification, lock
revalidation, commit upload, and pointer-last ordering unchanged.
6. Rewrite focused publish tests and helpers to create a run root and populate
session-manifest diagnostic references instead of writing a run manifest.
Cover current-run logs/generated configuration/declared archive outputs,
exclusion of prior-run and session-canonical paths, empty diagnostics,
symlink rejection, deterministic ordering, and absence of newly emitted
`run_manifest` declarations. Retain existing upload integrity and pointer
tests without duplicating them.
7. Update `docs/internal/stage-publish.md` and the run-upload portion of
`docs/operations.md`: the session manifest is the diagnostic allowlist, no
run manifest is uploaded, and `upload_run` may legitimately upload zero
run-local diagnostic files.
### Exit Criteria ### Exit Criteria
- `go test ./internal/manifest ./internal/artifacts ./internal/stage ./internal/app` - `go test ./internal/stage ./internal/artifacts` succeeds.
- Publish succeeds when the current run directory exists but contains no run
manifest and no diagnostics.
- Only session-manifest-declared files confined to the current run root become
`run_file` transfers; older-run and incidental files do not.
- New commits contain no `run_manifest` artifact, while remote decoding still
accepts that historical wire value.
- `git diff --check` succeeds.
## Stage 2 — Make Runner Persistence Session-Only
**Status: Pending**
### Goal
Remove the second persistence transaction from invocation execution while
preserving the existing session-ledger lifecycle and immediate command result.
### Required Work
1. Remove `RunOptions.RunManifestStore` and `RunSummary.RunManifestPath`. Keep
all remaining summary fields and run ID generation. Update direct callers
and CLI rendering only if they refer to the removed path.
2. In `executePlan`, delete run-manifest path resolution, construction,
identity/config projection, initial save, per-stage action/running/skip/
failure/success saves, final success save, and every error path created only
by those operations.
3. After acquiring the session lock, validating/restoring session state, and
resolving invocation identity, explicitly ensure the canonical
`SessionRunRootForCampaign` directory with the ordinary workspace directory
contract. Do not create `manifest.json` or another placeholder there.
4. Replace `persistTerminalFailure` with a narrowly named session-only helper.
It must record the terminal failure in the session manifest when available,
atomically attempt the session save, preserve the originating error, and
join a session-save error without invoking any diagnostic store. Keep the
distinct post-publish-cleanup failure behavior until its later workstream.
5. Simplify all runner failure paths to the new helper. Preserve the existing
order of session identity save, resume validation, running transition,
force invalidation, stage execution, success/failure/self-skip transition,
session save, logging, and post-publish cleanup.
6. Make `applyAnalyzeProjection` session-only at its application boundary so
the runner no longer needs a run-manifest value. The invocation subset may
remain temporarily inside validation until Stage 3 deletes it.
7. Delete run-only helpers such as `invocationIdentity.applyToRunManifest`,
`requestedStageNames`, `applyStageResultToRunManifest`,
`applyEffectiveConfigProvenanceToRun`, and
`setRunStageSemanticConfig` once unused.
8. Rewrite runner, terminal-failure, semantic-resume, assembled-workflow, and
lifecycle tests that currently inject a `RunStore` or load
`RunSummary.RunManifestPath`. Assert the durable outcome through the session
manifest and the immediate invocation outcome through `RunSummary`.
Preserve coverage for cancellation, collaborator/preflight failures,
session-save failure joining, successful and failed stage transitions,
self-skip, force invalidation, semantic evidence, distinct run IDs, and
run-local diagnostic paths. Delete tests whose sole purpose was run-record
creation, terminalization, or historical inspection.
9. Update `docs/policy/architecture.md`, `docs/cli.md`, and the runner portions
of `docs/internal/manifest.md`: one atomic session-manifest update is the
only durable progress transaction; a run ID and run directory remain, but
there is no invocation manifest or persistent command summary.
### Exit Criteria
- `go test ./internal/app ./internal/stage ./internal/manifest` succeeds.
- `executePlan` creates no `runs/<run_id>/manifest.json` and exposes no run
manifest store seam, while run IDs, run directories, diagnostics, session
transitions, and summaries remain available.
- A hypothetical diagnostic-record write cannot fail a stage because no such
persistence operation exists; session-manifest failures remain visible and
authoritative.
- Runner behavior tests obtain durable state only from the session manifest.
- `git diff --check` succeeds.
## Stage 3 — Remove Invocation-Only Analyze Projection
**Status: Pending**
### Goal
Give analyze one in-memory projection—the reconciled session collection—without
prematurely implementing Workstream 6 checkpoint semantics.
### Required Work
1. Remove `Invocation` from `stage.AnalyzeStateProjection` and update its
comment to describe only the reconciled session authority proposed for the
next session-manifest save. Retain the pointer wrapper so “no analyze update”
remains distinguishable from a valid empty collection.
2. In `internal/stage/analyze.go`, delete the separate invocation-record map and
every write, clone, or failure projection associated only with it. Successful
and failed analyze results continue to return the complete reconciled
session collection under the existing rules.
3. Simplify `internal/app/analyze_projection.go`: validate and clone only the
session collection, remove invocation/session subset comparison, apply only
the session collection, and derive aggregate analyze outputs only from that
collection. Retain rejection of projections from non-analyze stages,
contradictory ordinary outputs, malformed records, and illegal skipped or
error result shapes.
4. Preserve `captureAnalyzeState` and `restoreAnalyzeState` for the current
single-save boundary. Do not add manifest-store access to the analyze stage,
persist inside its artifact loop, or change retry/force behavior in this
stage.
5. Rewrite `analyze_projection_test.go`, analyze incremental tests, and mixed
runner tests around one reconciled session collection. Delete assertions
about per-invocation artifact subsets. Retain behavior coverage for partial
failure state, unrelated current records, invalid projections, persistence
failure rollback, and aggregate output derivation.
6. Update `docs/internal/stage-analyze.md` and the analyze-state section of
`docs/internal/manifest.md` to describe one session projection and clearly
leave per-artifact checkpointing as future roadmap work rather than current
behavior.
### Exit Criteria
- `go test ./internal/stage ./internal/app ./internal/manifest` succeeds.
- No production analyze type, result, validator, or test distinguishes session
state from an invocation artifact subset.
- Analyze still performs one end-of-stage session save, retains valid unrelated
records, persists its permitted failure projection, and restores prior
in-memory authority if that save fails.
- No Workstream 6 checkpoint callback or persistence loop has been introduced.
- `git diff --check` succeeds.
## Stage 4 — Delete The Run-Manifest Domain Model
**Status: Pending**
### Goal
Remove the now-unreferenced structured schema, persistence API, canonical file
path, and mechanism tests from their owning packages.
### Required Work
1. Delete `internal/manifest/run_manifest.go`, `RunManifestSchemaVersion`,
`RunManifest`, `RunStageRecord`, run status/action enums, constructors,
transition methods, and all run-only validation/normalization helpers.
2. Remove `manifest.RunStore` and `LocalStore.CreateRun`, `LoadRun`,
`LoadRunReader`, and `SaveRun`. Simplify imports and shared validation only
where the deleted run code made them unnecessary; do not weaken session
manifest validation.
3. Delete `artifacts.SessionRunManifestPathForCampaign` while retaining
`SessionRunsDirForCampaign` and `SessionRunRootForCampaign` as canonical
run-diagnostic and invocation-work paths.
4. Delete `run_manifest_test.go` and run-manifest-only store/path/schema tests.
Remove run-specific portions of otherwise valuable manifest, artifact,
semantic fingerprint, restore, operator, and publish fixtures. Do not replace
serialization round-trip tests for a format that no longer exists.
5. Keep the remote `run_manifest` artifact enum accepted only by remote commit
decoding/validation. Add a concise comment at its declaration explaining
that Narratio no longer emits or interprets it and retains the value solely
so immutable existing commits remain readable. No production symbol in
`manifest`, `app`, or `stage` may refer to it.
6. Update package comments or focused internal documentation affected by the
domain deletion in the same change.
### Exit Criteria
- `go test ./internal/manifest ./internal/artifacts ./internal/app ./internal/stage`
succeeds. succeeds.
- Both manifest kinds round-trip only with exact supported versions. - Except for the explicitly retained `RemoteArtifactTypeRunManifest` wire
- A present analyze stage cannot round-trip without current per-artifact value and its remote-decoder compatibility test, searches for `RunManifest`,
versioning; an empty current collection can. `RunStore`, `CreateRun`, `LoadRun`, `SaveRun`, `RunManifestPath`,
- Load does not synthesize required stage identity or authority. `run_manifest.go`, and the local `runs/<run_id>/manifest.json` contract find
no current production or test implementation.
- Session manifest schema validation and round trips remain fully covered.
- Existing remote commit documents containing the historical `run_manifest`
artifact type still decode and validate, but new publish plans cannot emit
it.
- `git diff --check` succeeds. - `git diff --check` succeeds.
## Stage 2 — Reject Unversioned Party Documents ## Stage 5 — Reconcile Current Documentation And Close Workstream 4
**Status: Completed** **Status: Pending**
### Goal ### Goal
End interpretation of unversioned party files before removing the configuration Prove the session-only target state across the repository and leave one accurate
fields and mode shell that supported them. implementation narrative for the next workstream.
### Required Work ### Required Work
1. Make `ParseParty` require exactly `PartySchemaVersion` in the first and 1. Search current production code, tests, fixtures, examples, scripts, and
only YAML document. Missing/unknown versions identify the supported schema; nonhistorical documentation for run-manifest types, paths, JSON fields,
retain strict malformed, duplicate, ambiguity, and trailing-document checks. stores, publish classifications, invocation projections, and dual-save or
2. Delete `classifyLegacyPartyDocument`, `resolveLegacyParty`, and terminal-synchronization language. Remove stale surfaces or explain the
`party_legacy.go`. For this stage only, the resolved mode shell may remain retained run ID/run directory without implying a structured record.
so all packages compile, but production cannot construct legacy mode. 2. Reconcile canonical owners, especially `docs/policy/architecture.md`,
3. Simplify `resolvePartyInput` to return parsed canonical data and source `docs/cli.md`, `docs/operations.md`, `docs/troubleshooting.md`,
directly, with no classification branch. `docs/internal/overview.md`, `docs/internal/manifest.md`,
4. Replace legacy parser/resolution tests with required-v1, missing/unknown `docs/internal/stage-analyze.md`, `docs/internal/stage-extract.md`, and
version, multi-document, strict-field, alias, identity/order, and `docs/internal/stage-publish.md`. Keep schema definitions in the manifest
deterministic players-projection tests. owner, filesystem/remote behavior in operations, and implementation details
5. Update `docs/integrations/party.md`, the party section of in internal documents rather than duplicating them.
`docs/config.md`, `docs/internal/configuration.md`, and troubleshooting. 3. Do not edit immutable historical release notes or completed audit documents.
Do not yet claim removed config keys are unknown; Stage 3 changes structs. Roadmap references may retain the phrase “run manifest” when describing the
problem and approved removal. Current instructions must not claim the file
is produced or required.
4. Review the affected test suite under `docs/policy/testing.md`. Consolidate
leftover tests that merely encode the deleted write choreography, while
retaining meaningful session durability, transition, recovery, current-run
diagnostics, remote publication, and representative assembled-workflow
coverage.
5. Update Workstream 4 in `refactoring.md` from `Pending` to `Complete` and
update every stage plus the purpose/status section of this plan to
`Completed` only after the target state and all checks are proven. Do not
change later workstream statuses.
6. Run the complete repository validation from `docs/development.md`:
`go test ./...`, `go test -race ./...`, `go vet ./...`, `go build ./...`,
`go test ./internal/doccheck`, and
`go test ./internal/config -run '^TestExamplesLoadAndValidate$'`. Run
`git diff --check` and confirm the worktree contains only intended changes.
### Exit Criteria ### Exit Criteria
- `go test ./internal/config ./internal/stage ./internal/app` succeeds. - The session manifest is the only structured durable local progress record;
- No production code classifies or resolves an unversioned party, and no current code or documentation requires a run manifest.
`party_legacy.go` is absent. - Run IDs, canonical run directories, bounded diagnostics, generated
- Unsupported party schema fails before family expansion or preparation. configuration, receipts, immediate summaries, immutable run prefixes, and
- Canonical parsing and derived players output remain deterministic. remote publication remain functional without a second progress transaction.
- `git diff --check` succeeds. - Publish uses session-manifest evidence, emits no new run-manifest artifact,
and still reads verified historical remote commits without interpreting their
## Stage 3 — Remove Legacy Party And Players Configuration old diagnostic record.
- All repository-wide validation succeeds on the maintained Go toolchain.
**Status: Completed** - Workstream 4 and all five stages are marked `Complete`; Workstream 5 remains
the next pending workstream.
### Goal - `git status --short` is empty after the implementation commit.
Make one campaign party the only configured roster authority and players an
explicitly derived value.
### Required Work
1. Remove `PlayersFile` from `CampaignInputsConfig` and both `PlayersFile`
and `PartyFile` from `SessionInputsConfig`. Strict decode must reject all
three retired YAML paths as unknown unsupported fields.
2. Keep campaign `PartyFile` in resolved stable inputs. Represent generated
players as derived data, not a selectable `ResolvedInputFile`; introduce a
clearly named derived value if prepared-input consumers need one.
3. Remove `PartyMode`, both constants, `PartyDocument`, `IsCanonical`,
and all mode branches. Make `ResolvedParty` hold non-nil
`CanonicalParty` plus source provenance, and make `ParseParty` return
`*CanonicalParty`.
4. Simplify `mergeCampaignSession`, campaign-party loaders, resolved
validation, family expansion, effective digest/source reporting, and config
commands. Party selection always comes from campaign config.
5. Delete `internal/stage/prepare_legacy.go`. Simplify prepare/resume,
extraction references, and semantic contracts to copy canonical party and
render players. Preserve prepared paths, checksums, input kinds, Notarius
selectors, and meaningful `derived_from_party` provenance.
6. Make operator/source rendering show campaign party and derived players, with
no `legacy_player` role or separate player path.
7. Rewrite affected config, stage, app, template, profile, and command tests.
Add strict rejection for all retired keys and an integrated config/prepare
test proving one party produces both prepared documents.
8. Remove legacy roster text/fixtures from `docs/config.md`, `docs/cli.md`,
`docs/internal/configuration.md`, `docs/internal/stage-prepare.md`,
`docs/internal/stage-extract.md`, and `examples/`.
### Exit Criteria
- `go test ./internal/config ./internal/stage ./internal/app` succeeds.
- No production YAML tag accepts `players_file` or session `party_file`.
- No production `PartyMode`, `PartyDocument`, or legacy prepare symbol
remains.
- One campaign v1 party supplies both prepared party and derived players.
- Current docs/examples contain no legacy roster workflow.
- `git diff --check` succeeds.
## Stage 4 — Make Remote Current State Commit-Only
**Status: Completed**
### Goal
Make the versioned commit pointer the sole remote authority for status, restore,
and reuse.
### Required Work
1. Replace legacy missing errors with typed
`CurrentCommitPointerMissingError` keyed to
`S3CurrentCommitPointerKey`. `LoadCurrentState` returns it with
publish/republish guidance when absent and otherwise loads only committed
state.
2. Delete `current_state_legacy.go`, legacy limits,
`ResolveCurrentStateKeys`, and retired key helpers once callers are gone.
Retain current pointer/commit/session-manifest bounds.
3. Require non-nil pointer, commit, and manifest in `CurrentState`; keep
`CurrentPointerKey` and committed manifest key; remove
`CurrentRunIDKey` and legacy-oriented duplication. Update identity errors.
4. Mirror this in `app.RemoteCurrentState`, discovery, status, lock
inspection, restore, and helpers. Status may report missing pointer as not
published; malformed or unsupported current data remains an error.
5. Delete `buildLegacyRestoreActions`, legacy key mapping, prefix listing, and
checksum inference. Require committed restore planning while preserving
audio scope, verification, conflicts, reports, manifest-last order, and
installation safety.
6. Replace legacy fixtures with complete pointer/commit/manifest fixtures.
Cover missing pointer, bad versions/identity, undeclared/missing objects,
checksum/size/generation mismatch, and proof that restore neither lists nor
reads retired keys.
7. Remove legacy remote language from `docs/operations.md`,
`docs/troubleshooting.md`, `docs/internal/manifest.md`,
`docs/internal/artifacts.md`, `docs/internal/command-restore.md`, and
`docs/internal/stage-publish.md`; document republishing.
### Exit Criteria
- `go test ./internal/artifacts ./internal/app ./internal/stage` succeeds.
- Production never reads `current/manifest.json` or `current/run_id.txt`.
- Every successful current load has a verified pointer, commit, and manifest.
- Restore derives all remote scope from the commit without prefix listing.
- `git diff --check` succeeds.
## Stage 5 — Resolve Previous Artifacts From Commit Declarations
**Status: Completed**
### Goal
Use one deterministic source-to-object lookup per previous requirement without
path candidates or remote probing.
### Required Work
1. Rewrite `previouscache.Resolve` around guaranteed committed state. Require
the unique session-manifest declaration and always copy its checksum, size,
generation, and verified content into the plan.
2. For each sorted requirement, derive its canonical source ID and select its
unique `published_output`. Validate and strip the selected run's immutable
published-output prefix from `DestinationKey` to derive the local relative
path; never use current config or previous-manifest outputs for it.
3. Preserve required/optional behavior, deterministic ordering, safe local
paths, and checksum/size/generation metadata.
4. Delete legacy candidate/basename matching, manifest/config fallbacks,
candidate `Exists` calls, probing ambiguity errors, and unused derivation
helpers. Delete the test-only `BuildPlan` alias; call `Resolve`.
5. Test exact declarations, no candidate `Exists` or list calls,
required/optional outcomes, unsafe destinations, duplicate-source rejection,
and verified metadata through prepare/restore integration.
6. Update `docs/internal/stage-prepare.md`,
`docs/internal/command-restore.md`, `docs/internal/artifacts.md`,
`docs/operations.md`, and troubleshooting.
### Exit Criteria
- `go test ./internal/previouscache ./internal/stage ./internal/app` succeeds.
- Resolution contains no candidate, basename/config fallback, ambiguity probe,
or compatibility alias.
- Every hydration traces to one verified commit declaration.
- Optional absence skips and required absence fails without probing.
- `git diff --check` succeeds.
## Stage 6 — Make Local Artifact Evidence Manifest-Only
**Status: Completed**
### Goal
Remove aggregate and incidental paths so transcript, extraction, and analyze
consumers require current manifest evidence.
### Required Work
1. Rewrite `ResolveSessionArtifact` and its private candidate logic to require
a succeeded registered producer and exactly one output matching both
`Kind` and `SourceID`. Require safe path, producer run ID, and valid
checksum; verify checksum and registered content before returning. Reject
ambiguous/malformed evidence.
2. Delete `fallback.canonical_path`, canonical-path probing, filename
fallback, and old-candidate deduplication. Missing evidence remains typed
unavailable even when expected bytes exist.
3. Update render, extract input identity, transcript resolution, and analyze
built-in resolution to use this path while retaining stage context, content
checks, and semantic fingerprints.
4. Remove `analyzeReconciliationLegacy` and the version-zero reconciliation
branch. Unsupported in-memory state is non-resumable/corrupt, not legacy
state eligible for recovery.
5. Audit catalog hydration, analyze inputs, publish discovery, operator
inspection, and projections: configured analyze output authority comes only
from a current `AnalyzeArtifacts` record and its output evidence, never
aggregate outputs or configured paths. Do not implement Workstream 6
checkpointing.
6. Retain only strict extraction proof in `InspectExtractionEvidence`:
succeeded stage, matching input, canonical bundle, receipt, exact lane set
plus index, verified JSON/checksums, contracts, and Notarius provenance.
Delete any acceptance of missing contract/provenance; do not redesign the
adapter.
7. Test that incidental files, aggregate-only analyze outputs,
missing/failed/stale/unselected records, mismatched checksums, and incomplete
extraction evidence remain unavailable. Retain positive coverage for all
built-in transcript sources, configured extraction lanes, and analyze
outputs.
8. Update `docs/internal/artifacts.md`, `docs/internal/stage-analyze.md`,
`docs/internal/stage-extract.md`, `docs/internal/stage-publish.md`,
`docs/internal/manifest.md`, `docs/config.md`, operations, and
troubleshooting without legacy/fallback language.
### Exit Criteria
- `go test ./internal/artifacts ./internal/manifest ./internal/stage ./internal/app`
succeeds.
- Disk files cannot establish transcript or analyze availability without
current evidence; aggregate analyze outputs cannot substitute.
- Extraction lacking receipt, contract, provenance, complete sources, or
verified bytes cannot hydrate the catalog.
- Positive current transcript/extraction/analyze/publish/operator flows work.
- `git diff --check` succeeds.
## Stage 7 — Complete The Purge And Validate The Repository
**Status: Completed**
### Goal
Remove residual compatibility material, validate the current-only architecture,
and close Workstream 3 without entering later work.
### Required Work
1. Search active code, tests, fixtures, examples, and current docs for retired
remote keys/readers, previous candidates, unversioned party modes,
`players_file`, session party overrides, aggregate analyze authority,
incidental artifact fallback, missing manifest schemas, and extraction
evidence without contract/provenance.
2. Delete unused constants, fields, types, errors, helpers, aliases, files,
fixtures, and imports belonging to those paths. Do not remove unrelated
adapter defaults, optional-input behavior, or later-workstream seams merely
because they use “fallback.”
3. Review canonical docs under the documentation policy for consistent current
behavior and actionable migration. Leave `docs/releases/`, audits, and
decision history unchanged.
4. Run `go test ./...`, `go test -race ./...`, `go vet ./...`, documented
docs/example validation, and supported Linux/macOS/Windows release builds.
Cross-builds prove compilation only.
5. Review tests against testing policy: retain rejection and positive tests at
every authority boundary without recreating deleted algorithms in tests.
6. Mark only Workstream 3 `Complete` in `refactoring.md` and all stages here
`Completed`. Accurately record unavailable native-platform evidence.
### Exit Criteria
- Full tests, race tests, vet, docs/examples, and release cross-builds succeed.
- No runtime branch accepts or infers a retired Workstream 3 representation.
- Each current manifest, party, remote snapshot, previous input, transcript,
extraction artifact, and analyze artifact has one documented authority.
- Only Workstream 3 is newly complete and `git diff --check` succeeds.
## Open Questions ## Open Questions
None. The approved audits, roadmap, policies, and current implementation make None. The approved audits, current architecture, and decisions above are
this plan decision-complete. sufficient to implement this workstream without further product or policy
choices.