8.5 KiB
Integer schema versions: implementation plan
Status: in progress. The feature roadmap owns the intended behavior and architecture; this document owns execution and progress.
Execution rules
Execute stages sequentially. Each stage is a bounded assignment for one gpt-5.6-terra coding agent: one coherent outcome, targeted files, focused tests, and a reviewable handoff. Do not delegate or parallelize dependent stages by default. No stage authorizes changing downstream repositories or publishing a tag.
Before each stage, read development, the relevant task-specific policies, the roadmap, and the preceding handoff. Inspect the worktree and preserve unrelated work. Prefer the repository's code graph for code discovery, and verify current symbols rather than assuming the file inventory below is frozen.
Keep every stage green: add behavioral coverage alongside its implementation, run
the stated focused commands and ./scripts/check.sh, and update implemented
contracts in the same change. Do not relax tests unrelated to this feature.
Record files changed, commands/results, remaining risks, and the next stage here.
Commit a coherent stage when committing is authorized; otherwise hand off its diff.
Stage 1 — Deliver the checker-to-decoder vertical slice
Status: complete (2026-09-12). Depends on: none.
Scope: validation.go, the private decoding plumbing in decode.go and
load_result.go, necessary private call sites, and focused version/decode tests.
- Add the shared private integer-text recognition and extend
checkVersionaccording to the roadmap. Preserve diagnostics, callback order, and public types. - Thread per-load version-path context to recursive decoding; enable integer to plain-string decoding only at that path. Do not mutate source/history trees or type-wide descriptors. Keep no-rule decoder callers strict.
- Add public-load coverage for integer and string
4intostringand*string, identical checker text, absent/null states, and unsupported version kinds. - Keep the suite green by updating the existing integer-version rejection test in
load_test.go. Inexamples/consumers/consumers_test.go, remove integer input from the structural-rejection expectation or convert it to the appropriate success/domain-policy assertion; do not merely delete migration coverage. - Update
Version/VersionRulecomments, the configuration contract's version and conversion sections, and stale consumer claims that all integer versions must be rewritten. Describe only behavior implemented by this stage.
Acceptance: a full load of version: 4 with a configured rule and string-backed
field succeeds and stores "4"; without the rule it still fails strict decoding.
An unrelated integer-to-string field still fails. Existing accepted input remains
unchanged. Both checking and decoding are implemented before this stage is done.
Validation: go test . -run 'Version|Decode',
go test ./examples/consumers, then the everyday checker.
Completion record: checker and load-local decoder support landed with strict
no-rule and unrelated-field behavior retained. Focused package tests, consumer
tests, and ./scripts/check.sh pass with Go 1.26.7 on Linux. Stage 2 should expand
the scalar, destination-type, and semantic-path boundary matrix.
Stage 2 — Close scalar and path-boundary gaps
Status: not started. Depends on: Stage 1.
Scope: focused tests in load_test.go, decode_test.go, and relevant path/decoder
helpers only where those tests expose defects. Avoid broad schema refactoring.
- Cover zero, negative integer,
-0, a decimal identifier beyond int64 range, empty string, fractional/exponent numbers, booleans, and containers. Check parser rejection remains separate for non-JSON numeric spellings; reuse parser coverage. - Exercise a nonstandard nested version path, an escaped mapping key, contextual numeric path tokens, and sibling fields sharing a named string type. Prove conversion is path-scoped rather than descriptor-wide or name-based.
- Cover named strings and pointer wrappers; show integer destinations and dynamic values retain ordinary types/range errors, while custom text codecs, durations, and secret-reference destinations do not gain integer coercion.
- Verify unsupported kinds prevent the version callback, accepted integer input reaches application policy, and rejection by that policy prevents later hooks. Assert codes, semantic paths, and locations, not incidental message wording.
Acceptance: the target scalar/destination matrix is covered with lean table-driven tests, no silent overflow/rounding, and no coercion leakage to unrelated fields or loads. Expand a stage-1 test instead of duplicating the same behavior.
Validation: go test . -run 'Version|Decode|Path', then the everyday checker.
Stage 3 — Verify provenance and pipeline invariants
Status: not started. Depends on: Stage 2.
Scope: explain_test.go, provenance_test.go, import/profile/override and secret
test owners as needed. Production changes only for demonstrated integration gaps.
- Add an end-to-end integer-version case asserting final string configuration, effective string rendering, original numeric history, and the existing decoding reconciliation event. Confirm locations, explicitness, and historical lookup.
- Exercise equal-valued defaults and detached repeated loads/queries so conversion does not masquerade as resolution or mutate retained input.
- Verify integer versions do not bypass fragment-version rejection, profile version protection, or CLI overlap checks; extend existing owners rather than recreating each suite. Include a nonstandard version path where practical.
- Check sensitive original/effective version snapshots remain redacted and that the conversion adds no secret resolution or credential-bearing diagnostics. Use synthetic fixtures and existing lookup seams, never real credentials.
Acceptance: typed configuration, metadata, rendering, and explanation agree; the only intentional change is the version input/decoding exception. If inspection needs repair, retain original input rather than suppressing its history.
Validation: go test . -run 'Version|Import|Profile|Override|Provenance|Explain|Secret',
go test -race ./..., then the everyday checker.
Stage 4 — Complete consumer evidence and release readiness
Status: not started. Depends on: Stage 3.
Scope: maintained Notarius-shaped examples/fixtures, consumer documentation, documentation consistency review, and validation handoff. No downstream app edits.
- Make integer
version: 4and quotedversion: "4"representative successful Notarius-shaped inputs with the same string-backed application result. Configure the example's application checker consistently; do not bypass version policy. - Retain negative examples for unsupported application versions and non-integer version kinds, with stable diagnostic codes/paths. Verify unrelated dynamic option integers and runtime conversions remain unchanged.
- Audit current documentation and Go examples for string-only claims. Keep historical release notes, extraction records, and ADR rationale historical; repair navigation without rewriting historical decisions. Transfer completed target descriptions from the roadmap to canonical owners.
- Run the full release checker using the command below (or qualifying cached toolchains selected under the release runbook). Report actual versions and results.
- Hand off the compatibility assessment and remaining release work. Select an unused version with the maintainer; create version-matched notes only for a real candidate. A changed rejection contract must be reviewed explicitly; do not reuse the v0.1.1-only policy exception.
Acceptance: complete consumer regression and all available automated gates pass; no current documentation promises unimplemented behavior. Mark implementation complete separately from publication. Exact-commit Linux/macOS checks, candidate commit/push, release-note approval, roadmap retirement, tagging, and clean consumer retrieval follow the release procedure when separately authorized. Unavailable macOS evidence is a release blocker, not permission to waive the gate.
Validation: go test ./examples/consumers, go test . -run '^Example', the everyday
checker, and the full release checker:
CONFIGKIT_BASELINE_TOOLCHAIN=go1.25.5 \
CONFIGKIT_NEWER_TOOLCHAIN=go1.26.7 \
./scripts/release-check.sh
Rerun exact-commit release checks after any later candidate or roadmap-retirement changes.