Files
narratio/docs/roadmap/implementation.md

507 lines
32 KiB
Markdown

# ConfigKit Adoption Implementation Plan
Status: Pending
Implement the [ConfigKit adoption roadmap](configkit-adoption.md) in the order
below. The target is Narratio v2.0.0: ConfigKit v0.1.1, the reduced platform
matrix, and the artifact-authoring workflow described there. Each stage is a
bounded implementation assignment for a gpt-5.6-terra coding agent. Mark a stage
complete only after its changes and acceptance checks succeed; record a short
completion and verification note beside its status.
## Instructions for every stage
- Read `docs/development.md` and all three policies under `docs/policy/`.
Read the relevant roadmap section and the stage-specific sources listed below.
Paths identify starting points, not an exhaustive edit allowlist; inspect callers
and tests before changing a package boundary.
- Use the tagged ConfigKit public API. The local `../ConfigKit` checkout is useful
reference material, but verify its version before relying on it. The module
cache for v0.1.1 is an alternative. Do not require a sibling checkout, a local
`replace`, a Go workspace, an upstream patch, or an unpinned revision to build.
- Keep Narratio domain policy in `internal/config`, startup and selectors in
`internal/app`, and credential delivery in the owning adapters. Do not build
a general configuration framework around ConfigKit.
- Keep each stage buildable and run focused behavioral tests for its changed
boundary. Temporary migration helpers may exist between stages only where
named here; they must not introduce runtime format auto-detection or fallback.
- Update each canonical current-behavior document when its behavior changes.
The roadmap remains the owner of unimplemented work. Preserve historical
release notes; their descriptions of old platforms and formats are history.
- Tests use real ConfigKit and temporary files, with fake external adapters or
storage where needed. Use synthetic credentials and isolate environment
mutation; such tests must not run in parallel. Retain domain and security
coverage, remove superseded mechanism tests, and avoid exact diagnostic prose
or private callback choreography assertions.
- Do not tag or publish v2.0.0 as part of this plan. Release preparation belongs
here; release authorization and tag publication are a later task. The existing
release completion boundary remains successful upstream tag push, with no CI
polling or waiting.
## Decisions that apply across stages
The roadmap is authoritative for product scope. These implementation choices
make that scope concrete:
- Enable ConfigKit imports and profile selection for pipeline files only.
Campaign, session, and party are single-source definitions with imports and
profiles disabled. Preserve their domain schemas and source-relative inputs.
Omitted or empty profile and the exact name `default` select the base; other
names use ConfigKit's fixed `profiles/<name>.yml` convention.
- Defaults apply to absent fields. Explicit empty/zero/false/null values follow
ConfigKit decoding and then domain validation; do not refill invalid explicit
values with legacy defaults. Optional null stage sections remain absent;
required sections fail domain validation rather than being resurrected.
- Keep ConfigKit metadata/result snapshots separate from runtime-only Narratio
state. ConfigKit discards ignored and unexported fields when detaching values;
attach root paths, retained party bytes, family catalogs, and digest metadata
after loading. No validator may mutate bound configuration.
- Use one Narratio-owned safe effective projection for the final expanded
pipeline. It contains configuration values and credential reference names,
never resolved credential bytes. It feeds show, semantic diff, digest, and
catalog data. ConfigKit metadata remains the authority for input provenance;
Narratio adds only domain-generated attribution.
- Rename `storage.s3.access_key_id_env` to `access_key_id`,
`storage.s3.secret_access_key_env` to `secret_access_key`, and
`audita.llm_api_key_env` to `llm_api_key`. Each is an optional `*configkit.Secret`.
An explicit reference always resolves during loading, even if the associated
stage will not execute. Require both S3 fields together or neither. With neither,
retain the AWS SDK default credential chain; do not synthesize mandatory secret
references that would break role-based authentication or local-only inspection.
With no Audita reference, preserve its existing downstream credential discovery.
Explicit references replace Narratio's old per-adapter environment lookup.
- Keep absent S3 credentials out of defaults; migration examples explicitly name
the existing AWS variables when static credentials are intended. A non-nil
missing/empty reference fails instead of silently falling back. This preserves
provider-managed credentials while making explicit configuration trustworthy.
- `config artifacts` uses the existing configuration command selectors and text
output convention. No new JSON mode, artifact creation wizard, inferred filename
identity, or profile catalog is added.
- Preserve the roadmap's unique base artifact definition rule explicitly:
ConfigKit rejects conflicting leaves but can compose disjoint children of the
same mapping. Use its public source metadata to reject an ordinary artifact key
declared by multiple base files, even if their fields are disjoint. Apply the
same rule to family keys. A selected profile may override or extend a definition.
This is a narrow Narratio declaration rule, not a different merge algorithm.
- Relax only the obsolete configuration/secrets filesystem restrictions identified
by the roadmap. Do not remove session restore, cleanup, publication, workspace
confinement, or ordinary shared-workspace mode guarantees as collateral work.
## Stage 1 — Reduce the platform and release matrix
Status: Complete — Reduced CI and release output to Linux amd64/arm64 and macOS
arm64, removed Windows-only runtime implementations and accommodations, and
verified focused tests, all three cross-builds, exact asset names, and embedded
version reporting.
Read: roadmap “Platform Contract”; `scripts/build-release-assets.sh`,
`scripts/check-release-candidate.sh`, `.woodpecker/`, `internal/releasecheck`,
`docs/release.md`, and platform-specific files in application, file operations,
and subprocess packages.
1. Make Linux amd64, Linux arm64, and macOS arm64 the only maintained build and
release targets. Remove Windows suffix/packaging branches and macOS amd64
targets from scripts, workflows, tests, and current documentation.
2. Delete Windows-only implementations and tests; simplify paired build-tag
files where the remaining implementations can be shared. Preserve portable
code when retaining it adds no special support machinery. Preserve functioning
Unix subprocess cancellation, locking, and file operations on both supported OSes.
3. Retain the local Linux verification gates and cross-build gates for all three
published assets. Do not introduce a native macOS runner requirement or claim
that cross-compilation verifies runtime behavior.
4. Update architecture/operations platform statements and contributor/release
guidance. Keep existing release protections and the no-CI-wait boundary intact.
Acceptance: focused platform/subprocess/fileops/releasecheck tests pass; build all
three targets with `CGO_ENABLED=0`; verify the asset builder produces exactly the
three expected versioned binaries and the host binary reports the supplied version.
Existing release tests still prove guarded publication. No current support promise
or asset list retains Windows or macOS amd64.
## Stage 2 — Separate configuration normalization from validation
Status: Complete — Added explicit deterministic pipeline normalization before
validation, made Notarius validation read-only on accepted and rejected inputs,
documented the boundary, and verified config race tests plus app/stage consumers.
Read: `internal/config/load.go`, `defaults.go`, `normalize.go`, `validate*.go`,
`artifact_families.go`, and ConfigKit's “Recorded application resolution”,
“Semantic validation”, and “Defaults and typed decoding” contracts.
1. Separate value-producing normalization from read-only validation, including
Notarius reference/output normalization currently performed by
`validateNotarius`. Audit all validators for map, slice, pointer, and scalar
mutations, including changes that would occur only on error paths.
2. Keep reusable domain normalization ordinary package code. Validation checks the
already normalized candidate and must work for both loaded and programmatically
constructed values without silently fixing them.
3. Inventory defaults in `load.go`: static defaults, per-map-entry/list-element
defaults, and inherited or presence-sensitive defaults. Retain named constants
in `defaults.go`. This inventory should guide code and concise comments, not
become a permanent parallel defaults document.
4. Keep the current loader calling normalization explicitly before validation
during this preparatory stage. The ConfigKit resolver replaces that loading
choreography in Stage 4. Preserve family expansion as an explicit domain step.
Acceptance: focused configuration tests prove normalization is deterministic and
validation does not mutate accepted or rejected inputs. Cover representative
Notarius normalization/collision handling and existing artifact/publish rules.
Do not add a separate mutation test for every trivial validator.
## Stage 3 — Replace composition-dependent effective projection
Status: Complete — Introduced one typed safe projection for effective YAML,
semantic values, source paths, and the versioned v3 digest; removed composition
parsing from those consumers and verified ordering, expansion, relocation,
nil/empty, exact-integer, CLI diff, and semantic-resume behavior.
Read: `internal/config/effective_pipeline.go`, `effective_digest.go`,
`pipeline_composition.go`, `internal/app/config_commands.go`, the config-diff
implementation, and `docs/internal/configuration.md`.
1. Introduce one package-owned, schema-specific safe projection of the effective
pipeline. Use explicit typed projections with stable configuration field names;
preserve null versus empty containers and exact integers. Ordinary nested
configuration types may be reused where they contain no runtime state.
Credential fields must be projected explicitly as reference names when Stage 7
changes their types. Do not introduce a generic reflection schema engine.
2. Render this projection as deterministic YAML using the existing YAML encoder;
encoding output is not a replacement YAML loader. Produce semantic records
directly from the safe projection using standard JSON encoding/decoding with
number preservation if a plain value tree is useful. Do not reparse YAML or
reconstruct `compositionNode` trees to compare or hash effective values.
3. Make show, diff values, and digest use that common projection. Mapping order is
immaterial; sequences remain atomic for diff; nil and empty remain distinct.
Exclude family declarations once expanded, all runtime metadata, profile names,
source locations, and raw credentials. Preserve logical Notarius path handling
so moving an equivalent bundle does not change its digest.
4. Version the changed digest encoding explicitly using the package's digest
version constant. Digest/profile metadata remains provenance, never a blanket
resume cache key. Keep stage/artifact semantic evidence behavior intact.
5. Decouple enumeration of effective field paths from the legacy composition
renderer. Input ownership can still come from the current loader until Stage 4.
Acceptance: show/diff/digest tests cover equivalent monolithic/split values,
different map insertion order, null/empty distinction, family-expanded outputs,
and bundle relocation. A meaningful artifact change changes the digest; formatting
and profile naming alone do not. Existing semantic resume tests pass. No effective
projection consumer needs the custom composition parser/renderer.
## Stage 4 — Cut pipeline loading over to ConfigKit
Status: Complete — Replaced pipeline composition with ConfigKit v0.1.1 imports,
fixed-path profile selection, fresh typed defaults, recorded resolution, source
metadata adaptation, and duplicate base artifact/family enforcement; removed the
legacy parser and verified all tests plus the configuration race suite.
Read: ConfigKit v0.1.1 `docs/config.md`, `docs/consumers/README.md`, and its
Narratio-shaped compiled example; Narratio `internal/config/load.go`,
`composition.go`, `pipeline_composition.go`, and profile/composition tests.
1. Pin `gitea.maximumdirect.net/eric/ConfigKit v0.1.1` in `go.mod`/`go.sum`.
Implement a small pipeline definition using `Load`, `File`, enabled imports,
`Options.Profile`, defaults, recorded resolution, and read-only validation.
2. Migrate static defaults to fresh default values. Apply map-entry, list-element,
and inherited defaults with `Resolution.Default`/`IsExplicit`; use recorded
normalization for transformations from Stage 2. Do not call old post-decode
zero-filling defaults. Remove `NormalizeConfig.UnmarshalYAML` and its private
presence bit. Include publication list-entry defaults, optional section
allocation, and trim's Scriptorium requirement in this conversion.
3. Perform file-local semantic checks in the definition. Defer checks needing
canonical party expansion or campaign/session context to the existing explicit
resolution boundary; do not reject references to future concrete family members
merely because the campaign has not loaded yet. Run full checks after expansion.
4. Replace pipeline composition and profile loaders. `configkit.imports` is the
only directive; no `composition` or `_configkit` alias is accepted. Pass profile
selection directly under the agreed convention; unselected overlays are not read.
`LoadPipelineProfilePair` may remain a thin pair of independent loads, with no
shared parse cache or paired source-snapshot promise.
5. Adapt ConfigKit sources and metadata to Narratio's existing reporting records.
Translate paths structurally using public path APIs, not error-message parsing.
Preserve multiple contributing locations for composite/profile-owned mappings
and distinguish defaults/resolution from authored values.
Check artifact/family map-entry ownership for duplicate base declarations using
those locations; ignore synthetic defaults and allow the selected overlay.
6. Attach runtime metadata only after load succeeds. Preserve root-relative runtime
path interpretation and capture logical paths before making them absolute.
Retain family declarations and original ConfigKit metadata for later expansion.
7. Replace generic mechanism tests with a small integration set proving actual
Narratio wiring. Convert fixtures affected by this stage. Delete
`composition.go`, obsolete pipeline traversal/overlay/presence machinery, and
their redundant tests once the callers are migrated.
Acceptance: a real root with imports and a testing overlay loads; duplicate claims
fail with useful source attribution, including two base files contributing disjoint
fields to one artifact or family key; base/default selection works; malformed
unselected profiles do not fail base loading. Omitted defaults and representative
explicit false/zero/empty/null inputs obey the new semantics. Invalid domain values
still fail. Commands use the new pipeline loader with no format fallback. Update
`docs/config.md` and configuration internals for the implemented boundary.
## Stage 5 — Migrate campaign, session, and canonical party loading
Status: Complete — Migrated campaign, session, and canonical-party documents to
independent ConfigKit definitions, preserved bounded session inspection, exact
party bytes and metadata-derived authored order, and retained identity, source,
family-expansion, and validation behavior; verified all tests and focused races.
Read: `internal/config/load.go`, `party.go`, `party_resolution.go`,
`artifact_families.go`, session-template tests, `internal/app/config_loader.go`,
and ConfigKit source/schema/version contracts.
1. Use separate ConfigKit definitions for campaign, session, and party. Replace
`decodeStrictYAML*` and the custom party YAML-node parser. Model the party input
as the existing string schema version and character-keyed typed map, with the
existing `alias` list, ordered class list, and optional positive class level.
2. Keep party domain checks: valid IDs, required display names and classes,
trimmed/control-free names, case-insensitive name/alias ambiguity, and duplicate
class checks. Validate the required version through `VersionRule`. Keep an
exact independent copy of authored bytes outside ConfigKit's schema object.
3. Preserve authored character order using successful metadata source coordinates
for the single party input when constructing `CanonicalParty.Characters`.
Preserve class/alias sequence order naturally. Family expansion and players
projection continue using their existing deterministic ID sorting. Do not keep
a second YAML parse just to recover mapping order.
4. Preserve the narrow session placeholder rejection before typed load, expected
session/previous-session identity checks, campaign selection, stable-input
precedence, and local versus remotely downloaded session provenance.
Retain the initially loaded pipeline/campaign during remote session acquisition.
5. Where bytes must be retained or inspected before `ConfigKit.Bytes`, bound the
initial read too, using the existing fileops bounded-read helper and a named
package constant of 8 MiB matching the pinned source limit. Otherwise prefer
`ConfigKit.File`. Do not read an unbounded file and rely on later rejection.
6. Complete post-party family and publish-rule expansion, then full cross-config
validation and digest refresh. Keep generated origins outside the library
snapshot. Remove unused decoder plumbing and obsolete party parsing tests.
Acceptance: retained authored party bytes are identical; domain errors, aliases,
class order, family origins, and derived players are correct. Local and remote
session loads preserve identity, input path bases, and the original pipeline.
Unknown fields and disabled directives fail through ConfigKit. Focused config,
prepare/extract, and application loading tests pass.
## Stage 6 — Move secrets bootstrap before all configuration loads
Status: Complete — Added invocation-scoped ConfigKit secrets bootstrap before
all pipeline loads and adapter construction, exposed consistent explicit and
conventional directory selection across the CLI, removed the retired pipeline
schema and custom loader, and verified focused, full, and race test suites.
Read: roadmap “Credential and Secrets Convention”; ConfigKit's bootstrap
contract; `internal/app/secrets_env*.go`, `config_loader.go`, `config_commands.go`,
`object_store.go`, command dependencies, and command argument owners.
1. Add a shared `--secrets-dir` selector to every CLI path that loads a pipeline,
including configuration inspection/diff, execution aliases, planning, publish,
and session/storage operations. Route all through one command-owned bootstrap
context. Help/version and commands that do not load configuration do not bootstrap.
2. Discover the root pipeline first. An explicit relative directory is based on
caller CWD; otherwise choose `secrets/` beside the resolved root pipeline.
An explicitly empty flag is invalid. Missing conventional directories are
skipped; missing explicit directories and unreadable/invalid existing directories
fail. Use ConfigKit's selected-directory symlink behavior without custom rejection.
3. Call `LoadSecretsDir` at most once per command before any ConfigKit load or
adapter creation, including both loads of config diff and remote session lookup.
Use invocation state, not a package-global `sync.Once`. A new command gets its
own bootstrap; library config loaders themselves never mutate the environment.
4. Present safe bootstrap warnings/failures through stderr or the existing safe
diagnostic boundary, never into YAML show output. Preserve the partial report
on bootstrap failure. Do not add rollback or reinterpret ConfigKit file rules.
5. Remove late bootstrap calls in object-store and runner composition, the custom
directory reader and permission platform files, `pipeline.secrets`, its defaults
and validators, and their obsolete tests. Convert affected fixtures immediately.
Acceptance: test absent conventional directory, explicit override from another
CWD, invalid explicit directory, already-set empty/nonempty environment values,
and bootstrap failure before adapter construction. A diff invocation and a remote
session acquisition each bootstrap once. Config inspection requires no session,
workspace writes, manifests, or runtime clients. Update CLI, config, operations,
architecture, and troubleshooting to the new bootstrap/permission contract.
## Stage 7 — Resolve typed credentials and protect all output boundaries
Status: Complete — Migrated S3 and Audita credentials to optional ConfigKit
typed references, passed resolved values directly to runtime adapters, preserved
the AWS default provider chain when unconfigured, and verified reference-only
inspection, provenance, generated configuration, manifest, and diagnostic
boundaries with focused, full, and race test suites.
Read: ConfigKit “Typed secret references” and rendering contracts;
`internal/config/config.go`, `defaults.go`, `validate_adapters.go`, the safe
projection from Stage 3, `internal/adapters/storage/s3_backend.go`,
`internal/adapters/audita/subprocess.go`, and their composition callers.
1. Implement the three renamed optional typed fields and S3 pair policy above.
Reject old `_env` schema keys; remove their default-name and lookup helpers.
Convert maintained fixtures with synthetic environment setup where references
are present. Do not add credentials to unrelated local pipeline fixtures.
2. Pass resolved S3 values to the SDK adapter's explicit static provider only when
the pair is configured. With neither, preserve its default provider chain.
Pass Audita the resolved value and safe reference name; deliver the value only
through the child environment's existing `AUDITA_LLM_API_KEY` override.
Do not re-read the environment for an explicitly resolved reference.
3. Adapt every serialization, digest, source/diff output, diagnostic, generated
invocation config, manifest, and provenance caller to safe reference names.
Never YAML-marshal ConfigKit's opaque secret directly or call `Value()` in an
inspection path. Secret changes alone must not alter effective digests or
invalidate artifact evidence; reference-name changes may change provenance.
4. Keep ConfigKit errors structured and safe. Domain validation messages must
avoid raw credential values; do not unwrap private parser errors or interpolate
whole trusted configuration structs into error messages.
5. Preserve downstream tool ownership for Notarius/Scriptorium credentials that
Narratio does not configure. Do not add a parallel credential schema for them.
Acceptance: use distinctive synthetic secrets to prove no leakage in show, sources,
diff, catalog-ready projections, success/failure diagnostics, manifests, or generated
Audita configuration. Verify the child receives the credential and an environment
change after loading does not change explicit delivery. Test S3 paired references,
partial-pair rejection, missing effective references, and nil SDK fallback offline.
Update adapter and credential documentation and remove obsolete lookup tests.
## Stage 8 — Infer and normalize artifact dependencies once
Status: Complete — Finalized one normalized artifact graph from explicit ordering
edges and configured-artifact inputs (including rewritten family members), retained
edge origins for diagnostics, and verified focused/full tests plus the full race
suite and an assembled input-only analyze workflow.
Read: `internal/config/validate_scriptorium.go`, `artifact_families.go`,
`internal/artifactpolicy`, `internal/artifacts`, analyze planning/execution, and
their artifact dependency and semantic-evidence tests.
1. At the final configuration resolution boundary, union explicit `depends_on`
with configured-artifact input references. Use the existing source-ID parser;
do not infer edges from filenames, arbitrary strings, or non-artifact inputs.
2. Infer after family member inputs become concrete `narratio.artifact.<key>`
sources. Normalize, deduplicate, and sort the effective dependency list once.
Keep explicit ordering-only dependencies valid. Repeated finalization must not
accumulate edges or alter ordering. Store source-edge attribution separately
from the effective graph for diagnostics and generated provenance.
3. Apply existing existence, self-reference, enabled-dependency, output, and cycle
validation to the union. Remove the error requiring an input to be repeated in
`depends_on`. Retain diagnostics pointing to the explicit list entry or the
input that contributed an invalid edge, including family origin where relevant.
4. Ensure execution, targeted analysis, planning, prerequisite closure, reuse,
forced regeneration, and semantic evidence consume this same concrete graph.
No adapter or command may infer a second graph. Refresh final projection/digest
after inference; equivalent explicit and inferred declarations compare equally.
Acceptance: cover input-only dependency ordering, duplicate explicit/inferred edges,
ordering-only edges, missing/self/cyclic references, and rewritten family inputs.
Use an assembled fake-artifact workflow to prove upstream output is supplied to a
dependent artifact and failure/resume retains successful predecessors. Existing
force/selection and invalidation tests remain valid. Update config and analyze
internals with the implemented inference rule.
## Stage 9 — Add the effective artifact catalog command
Status: Complete — Added the read-only `config artifacts` catalog over finalized
configuration, including effective dependencies and definition/family/party
provenance; documented it and verified focused, full, and race test suites.
Read: `internal/app/config_commands.go`, config diff/source rendering, the safe
projection and family-origin catalogs, and `docs/cli.md`.
1. Add `narratio config artifacts` to dispatch and help. Reuse ordinary pipeline,
profile, campaign, campaign-file, and secrets-directory parsing/resolution.
Resolve a campaign when families require it or when explicitly selected; a
pipeline with only ordinary artifacts can be inspected without a campaign.
2. Render one stable record per effective concrete artifact in key order with
key, `narratio.artifact.<key>` source ID, defining source location(s), enabled
state, output path, and sorted effective dependencies. Family members additionally
identify family key, character ID, defining family source, and party source.
3. Derive identity from the map key. A profile may contribute to an existing
artifact, so report contributing definition locations instead of inventing
a single filename owner. Use a deterministic escaped tabular text rendering;
include a header and no records for an empty catalog. Propagate writer errors.
4. Use the same finalized state as show/sources/diff and runtime configuration.
No session download, adapter initialization, manifest access, or workspace
materialization is allowed. Secret bootstrap remains the agreed startup exception.
Acceptance: CLI tests cover ordinary and generated artifacts, disabled entries,
profile-added/overridden artifacts, empty catalog, no-campaign ordinary inspection,
required-campaign failure for families, stable ordering, and no runtime side effects.
Check identity stays the same after moving an artifact file without changing its key.
Document the command in its canonical CLI owner and link to config layout examples.
## Stage 10 — Finish the operator layout and v2 migration documentation
Status: Pending
Read: roadmap “Artifact Definition Ergonomics” and “Compatibility and Migration”;
`examples/README.md`, existing example bundles and their loader test,
`docs/config.md`, `docs/operations.md`, `docs/release.md`, and internal configuration
and artifact documentation.
1. Convert maintained pipeline examples to a production base with explicit
`configkit.imports`, `artifacts/<key>.yml`, `artifact-families/<key>.yml`, and
`profiles/testing.yml`. Each recommended artifact/family file defines exactly
one explicit map entry. Fold old production overlays into the base.
2. Include an input-only dependency example and at least two character-family
examples sharing a campaign-owned party roster. Keep supported inline artifacts
legal; file layout is guidance, not a filename-based validation requirement.
3. Update the example validation harness to load root configurations and selected
testing profiles, not attempt to load each imported fragment as a full pipeline.
Use synthetic environment setup for explicit references. No example includes
real credentials or depends on local tools/cloud services to validate.
4. Consolidate canonical documentation updates from earlier stages. Remove current
references to old composition/profile catalogs, default-profile configuration,
secrets.env_dir, credential `_env` fields, credential-free inspection guarantees,
paired diff snapshots, and removed platform support. Explain explicit-value and
null changes without promising reloadable inspection output.
5. Add `docs/releases/v2.0.0.md` using the release-note structure, with a concrete
migration checklist linking to the canonical config/CLI docs and examples.
Include static S3-reference migration versus SDK credential discovery, new
inspection prerequisites, artifact input dependency inference, and platform
removals. Do not claim publication or edit older immutable release notes.
Acceptance: `go test ./internal/doccheck` and
`go test ./internal/config -run '^TestExamplesLoadAndValidate$'` pass. Walk through
the new operator examples with config validate/show/sources/diff/artifacts offline.
Their identities, family members, origins, and testing overrides agree.
## Stage 11 — Verify the complete migration and remove remaining scaffolding
Status: Pending
Read: the whole feature roadmap, completed stage notes, and the current test and
release procedures. Review the diff from the commit introducing this plan.
1. Audit every roadmap requirement against current code and executable evidence.
Remove temporary migration adapters and any residual generic YAML parser,
composer, profile traversal, explicit-presence store, old secrets loader,
decoder hooks, or unused tests. `gopkg.in/yaml.v3` may remain for output encoding
and unrelated external formats; it must not supply a second configuration loader.
2. Confirm result-owned snapshots versus final expanded configuration are handled
consistently; every inspection/runtime path sees normalized inferred dependencies
and generated publish rules. Recheck secret safety and semantic resume boundaries.
3. Inspect current platform conditions and asset lists. Retain historical notes but
no active Windows/macOS amd64 obligation. Compare owned production/test code
before and after; report removals and any remaining complexity with reasons.
Do not chase a LOC quota by removing useful domain checks or regressions.
4. Run the repository gates with the maintained Go 1.26 toolchain:
```sh
go test ./...
go test -race ./...
go vet ./...
go build ./...
go test ./internal/doccheck
go test ./internal/config -run '^TestExamplesLoadAndValidate$'
```
5. Run `scripts/check-release-candidate.sh v2.0.0` after the release note and all
candidate changes exist. This also verifies module hygiene and all three
release assets with `GOWORK=off`. Resolve failures; do not bypass checks or
publish a tag. Record native versus cross-build evidence accurately.
Acceptance: all gates pass and every roadmap outcome has direct evidence. No
dependency on the sibling ConfigKit checkout remains. Record completion and any
best-effort platform limitations, then hand off for a separate release decision.
## Open Questions
None required before implementation. The agreed roadmap and the explicit choices
above resolve the migration decisions. Upstream credential-free inspection and
native macOS arm64 CI remain deferred, not prerequisites for this plan.