Plan shared source version checks

This commit is contained in:
2026-10-15 14:24:51 +00:00
parent d9f08ff719
commit 70c95bf660
2 changed files with 455 additions and 605 deletions

View File

@@ -1,519 +1,440 @@
# Implement relative import destinations
# Implement shared source version checks
Status: complete. All nine implementation stages are complete; this document
preserves sequencing decisions and completion evidence. The
[feature roadmap](relative-import-destinations.md) owns the approved target and
syntax; this document owns implementation decisions, sequencing, and evidence.
Status: planned; no implementation stages are complete.
Planning baseline: `b2db323`, including input-destination remediation at
`315f464`. The previous completed input-destination implementation record is
preserved at `315f464:docs/roadmap/implementation.md` in Git history. The broader
[consumer request](promptkit-feature-request.md#requested-addition-relative-import-destinations)
also proposes independent specification headers, which are outside this plan.
Audience: a Luna coding agent implementing one numbered stage per prompt, in
order. The [feature roadmap](source-version-checks.md) owns target behavior and
accepted policy; this plan owns concrete implementation decisions and execution.
Planning baseline: `d9f08ff7198ad5a8fb5c49a43e7ccdad2ad0e707`.
The completed relative-import plan and evidence replaced here remain at
`d9f08ff:docs/roadmap/implementation.md`. Its roadmap and remediation are
complete, not instructions for this sprint.
## Working instructions
- Start with `AGENTS.md`, [development.md](../development.md), applicable policies,
and working-tree inspection. Use graph-first code discovery and preserve
unrelated changes. Read existing import and placement contracts before edits.
- Implement one stage at a time with its relevant tests/documentation. Record
actual commands, revisions, results, and limitations here; mark only completed
stages and commit each validated nonempty unit with a plain-English message.
- Follow the root-owned facade and private engine/document/YAML boundaries.
Reuse paths, placement, composition, inheritance, version ownership, history,
and resource contexts. No public Go entry point, source-header API, namespace
registry, or second merger is needed.
- Specification-header checking and consumption remain deferred. Ordinary
`version` data, the main-owned checker, exact-path numeric conversion, and
callback timing keep their existing behavior. Examples must work without the
broader request's combined header example.
- Roadmap exclusions define this delivery, not new permanent prohibitions. Do
not add directory discovery, caps, key-name grammars, root-reset syntax,
arbitrary callbacks, or stronger security/release guarantees.
- Keep Stage 2 behavior-preserving before Stage 3 accepts new syntax. Once
accepted, syntax must work through existing import entry points, not only path
imports or only root loads.
- Use focused offline tests while iterating and `./scripts/check.sh` before
committing production changes. Documentation-only work needs whitespace and
local-link checks. Ownership race checks belong to Stages 6 and 9. Reuse
unchanged coverage; do not assert helper-call counts, allocation identity,
exact diagnostic prose, or a cross-product of already protected cases.
- No independent benchmarks, performance thresholds, dependency changes,
toolchain upgrades, or new release gates are required. Prefer copying path
segments once per declaration and existing bounded tree processing; introduce
no public complexity guarantee.
- Do not push, tag, publish, upgrade downstream dependencies, rewrite accepted
ADR decisions, or remove unfinished work. Completed records retire during
separately authorized release preparation.
- Read `AGENTS.md`, [development.md](../development.md), and applicable policies.
This work involves [architecture](../policy/architecture.md),
[testing](../policy/testing.md), and [documentation](../policy/documentation.md).
Use graph-first discovery, verify live sources, and preserve unrelated work.
- Implement one stage at a time. Record completion, actual commands, toolchain,
results, limitations, and implementation revisions here. Commit each validated
nonempty unit with a short plain-English message.
- Keep public types root-owned with explicit engine conversions. Reuse semantic
Paths, documents, composition, overlay, version validation, sensitivity, and
inspection. No second loader, public parser nodes, generic transformation
hooks, or consumer-specific policy.
- Default mode preserves current behavior, including effective-path lookup,
main checker timing, and protected-path failures. Enabled modes deliberately
select source-local declarations and non-main consumption. Do not broaden
these changes into unrelated default-mode fixes.
- Do not add equality/SemVer rules, non-null requirements, numeric coercion,
path-form restrictions, source uniqueness policies, limits, dependencies,
toolchain changes, or release gates. Declaration acceptance is not fragment
schema conformance. Exclusions describe this delivery, not new permanent bans.
- Internal stages may test modes before exposing them publicly. Keep Go/current
documentation accurate to each delivered boundary; the roadmap owns the target.
- Use focused offline tests while iterating and `./scripts/check.sh` for each
production-code unit. Documentation-only units need local-link and whitespace
checks. Reuse existing tests; avoid a full mode/source/tier/path cross-product,
helper-call assertions, allocation identity, or exact message snapshots.
No independent benchmarks or performance thresholds are required.
- Do not rewrite accepted ADR decisions, publish, select a release version,
upgrade consumers, or retire completed roadmap records. Public struct additions
and enabled-mode path interpretation need minor-release compatibility guidance
during separately authorized release preparation.
## Resolved implementation decisions
## Concrete implementation decisions
### Syntax and validation
### Public options and evidence
1. Add one optional import-declaration field, `destination`, beside existing
`path`/`glob` and `optional`. Its value is a sequence of strings. Omission
and `[]` mean zero additional segments. Null, a scalar (including a pointer
string), and any non-string member produce `CodeImportInvalid`. No coercion:
quote numeric-looking keys when YAML would otherwise parse them as numbers.
2. Construct a relative `Path` of literal mapping keys and reuse
`normalizeDestination`. Empty strings, dots, dot-dot, slash/tilde-containing,
and numeric-looking strings keep their literal meaning. Existing exact
`configkit` and `extends` reservations apply. Do not trim keys, split
dots/slashes, clean filesystem paths, infer sequence indices, impose a
collection grammar, or add syntax aliases.
3. Validate shapes/reservations in `parseImportDeclaration`, before traversal
can suppress an optional missing target or unmatched glob. Invalid shapes
identify source-local `/configkit/imports/<index>/destination`; invalid
members identify its indexed child and actual member location. Follow
`nodeImportDiagnostic` conventions and keep messages value-free. Preserve
unknown-field, duplicate-key, path/glob, and optional rules. No new public
error code/type, all-errors aggregation, or error-order guarantee is needed.
1. Add root-owned `type SourceVersionMode uint8` with consecutive constants
`SourceVersionModeDefault` (zero), `SourceVersionModeIfPresent`, and
`SourceVersionModeRequired`. Add `SourceVersionMode SourceVersionMode`
to `Options[T]` and `LayeredOptions[T]`, not Definition, Input, or YAML.
Mirror privately and convert explicitly. Unknown modes, or enabled modes
without a usable VersionRule and checker, produce `CodeOptionsInvalid`
before source access or callbacks. Keep existing rule/path validation.
2. Add root-owned `SourceVersionCheck` with `Path Path`, `Version Version`,
`Location *Location`, and `Redacted bool`. Add
`VersionCheck *SourceVersionCheck` to SourceInfo. Nil means no enabled
declaration processing occurred. A non-nil record with Present false records
observed absence, including optional omissions whose checker was skipped; it
does not claim a successful callback or acceptance. On a malformed selected
value or overlap failure, retain only known presence/null, path, and location
with conservative redaction; never expose arbitrary scalar/container content.
Read/parse failures before this phase leave the record nil.
Reuse Version's absent/null/text model.
Redaction preserves presence/null, empties classified Text, and sets Redacted.
3. Evidence Path is source-local, with semantic segment intent resolved against
original source shape where possible. Present declarations retain their actual
authored location; absence uses the nearest available source location, not an
invented header coordinate. Destination and source identity already belong
to SourceInfo. Add no new query API, raw-node field, expected-version value,
or string/integer discriminator.
4. Clone the record, Path, and Location at all query/conversion/error boundaries.
Callback-time source queries and failed-load source records expose conservative
text-redacted evidence until final classification is available. Successful
final inspection may expose unclassified text; previous copies stay detached.
Keep raw evidence separate from public-safe source records. Do not extend a
failed load to finish classification or introduce a failed-load evidence API.
### Traversal and source records
### Lookup, checking, and diagnostics
4. Add a private relative-destination field to `importDeclaration`. Pass the
immediate parent's effective destination explicitly through
`walkDeclarations`. Append each declaration's relative path once and pass
that already computed child destination to `visitPath`. Recursive walks use
the child's effective destination. Remove the single
`importTraversal.destination` context rather than mutating/restoring it.
5. Add a small private destination-append helper in `destination.go`, unless a
semantically suitable general helper already exists. Copy semantic segments
into owned storage without pointer-string round trips, filesystem operations,
or repeatedly extending a growing prefix with `Path.Key`. Its inputs are
validated mapping paths. Place each body once, not once per ancestor.
6. Every glob match receives the same computed child destination.
`expandImportGlob` remains about physical matching. Turning a match into a
path declaration must not append its suffix again. Nested context must not
leak into siblings, later matches, or later inputs.
7. Use the child destination for source records, placement, fragment-version
checks, wrapper accounting, and recursion. Keep source-record creation at its
existing point so imports that later fail retain their effective destination.
`ImportedFrom` still identifies the physical path/glob declaration, not the
destination list. Source IDs, namespaces, acquisition order, active cycles,
physical identity, and strict-group repetition rules remain unchanged.
8. Remove the post-traversal assignment in `assembleBaseInputTracked` that
overwrites every imported source's destination. Set the selected entry's
per-load `parsedSource.source.Destination` before import-context setup so
early `sourceInfos` fallback copies retain entry placement. Leave correctly
assigned children untouched. Preserve `315f464`'s Mapping value-error
rebasing and root behavior; do not rebase syntax/read/directive failures.
5. Carry the configured local rule and an effective main-owned rule separately.
Enabled modes derive the latter once by prefixing main's Destination using
semantic segments. Use it consistently for remaining-payload protection,
inheritance/CLI checks, decoding's exact-path integer exception, and application
metadata. Default mode uses the configured effective path unchanged. Never
mutate caller rules or repeatedly prefix a path.
6. Read each declaration from its original source document before mounting or
consumption. Keep contextual numeric-key/index resolution, empty/escaped keys,
parsed tokens, and explicit indices. No mapping-only/root-only restriction;
selecting a root mapping simply fails ordinary version-type validation.
7. Missing members, unavailable indices, and obstructing non-containers mean the
requested declaration is absent, as with current document lookup. Distinguish
causes privately for accurate nearest locations, not to invent rejection of
an ancestor's domain value. If-present non-main absence skips the checker and
records absence; required absence is `CodeVersionError` before callback.
A present unsupported selected value is `CodeVersionType`, not absence.
Actual main absence in if-present mode still reaches its checker once;
required mode rejects it first. NoSource is not a document and preserves the
existing single absent-main callback in both enabled modes.
8. Reuse strict decimal recognition and exact Version.Text. No machine-integer
conversion or comparison with main. Required null reaches the checker and can
be accepted. Warnings alone succeed and accepted non-main headers are consumed.
9. Enabled declaration checkers and their Validation paths use the current
source's local coordinates for every role, including mounted main. Resolve
primary/related locations against that original source. Generated header
diagnostics also use source-local paths; do not rebase them to phantom payload
fields. Ordinary payload diagnostics remain effective-path diagnostics.
Default version diagnostics are unchanged. Reuse `CodeVersionError` for
missing-required/structural-overlap failures, `CodeVersionType` for malformed
values, and existing checker error/warning/hook codes. No new code is needed.
10. Keep callback lifetime, safe generic returned-error handling, and synchronous
execution. Check main once from its own declaration, never a composed value.
Check other documents as acquired, before composition can hide rejection.
Do not promise a new inter-source callback order or exhaustive acquisition
after failure. Build schema successfully before callbacks; enabled mode may
prepare it before acquisition, without changing the default pipeline.
Defaults, decoding, resolution, secret lookup, and validation still run once
on the assembled application.
### Assembly, limits, and compatibility
### Consumption and structural boundaries
9. Strip source-root directives before placing each application body and
checking imported version ownership. Existing composition/history retain the
placed source applications. Strict peers conflict, tiers recursively overlay,
sequences stay atomic, and sibling inheritance follows precedence. Do not add
post-load merging or per-fragment decoding, defaults, callbacks, or headers.
10. Reuse current depth, node, source, byte, import-depth, glob-entry, projection,
and history limits. Charge each actual body's wrappers once using its full
accumulated destination, not only the suffix. Preserve raw source accounting.
Placement adds no source bytes, source records, import nesting, or glob
visits beyond existing accounting. A glob declaration/ancestor walk itself
adds no payload. Omitted/empty suffixes reproduce baseline charges.
11. Malformed syntax fails even when optional input is absent. Resource charging
remains tied to actual contributions: a valid optional no-match creates no
source or wrappers; an actual empty body materializes its full destination.
Use existing placed-body bounds and source/import diagnostics. Add no
destination-length limit or rejection solely because an absent optional
contribution's unused path would be deep.
12. Preserve authored locations and source-root fallback for synthetic mappings.
Resource contexts remain physical and survive inheritance/overlays.
Metadata, history, sensitivity, rendering, diffs, detached records, and
complete-on-return behavior reuse their existing mechanisms; no new
inspection API or retained loading handle is needed.
13. This is additive YAML functionality. Existing valid imports and Go
signatures keep their contracts. Treat it as minor-release work; version
selection, notes, retirement, and publication remain separate tasks. Do not
edit published release notes.
11. Validate source-local controls before consumption can erase malformed
directives. Reuse import/overlay validation and inheritance-control
recognition, not per-fragment inheritance expansion. Reject actual overlap
with configkit directive structure or an extends control, including headers
inside import declarations or invalid control subtrees. Unrelated siblings
and ordinary keys containing those spellings remain allowed. Missing headers
follow their mode; they do not suppress independently invalid directives.
Add no error-order guarantee.
12. Retain main's node. Remove exactly an accepted non-main mapping member or
sequence element in an owned payload tree. Preserve authored ancestors,
newly empty mappings/sequences, sibling order, and physical node locations.
Sequence deletion shifts later payload indices; evidence keeps original
coordinates. Removing a member inside a sequence element keeps that element,
even when empty. No null placeholders, ancestor pruning, or Source mutation.
13. Extract source-root imports from original content; consume headers in its
application body before placement/composition. Underlay roots and all imports
are non-main; selected overlays are also non-main. Check remaining placed
payload against effective main ownership. Consumption does not permit
forbidden overlay controls, sequence alignment, or CLI ownership bypass.
14. Charge original acquired bytes/nodes once, including consumed headers. Apply
existing placed-body bounds and full-destination wrapper charges to remaining
payload. Keep source/depth/glob accounting, records, resource contexts, and
physical repetition unchanged. Acquired header-only mappings retain their
empty body/ancestors and placement; NoSource/optional absent sources add no
document or evidence. No new cap or full-source clone is required.
## Stage 1 — Capture the baseline and record the extension
### Evidence and sensitivity
Status: complete. Scope: baseline evidence and one ADR; no production code.
1. Read the feature roadmap, relative-import request/acceptance rows, applicable
policies, ADR 0011, and the owner map below. Confirm the worktree and baseline.
Run `./scripts/check.sh`; record revision, local Go version, results, and
environmental limitations here.
2. Locate existing parser, host/native import, glob, repetition, version,
placement-accounting, resource, history, and facade coverage. Root and
inherited placement are the compatibility baseline; header rows in the
broader request are not acceptance requirements for this plan.
3. Write `docs/adr/0012-relative-import-destinations.md` after confirming the
next unused number. Record the selected syntax and immediate-parent-relative
semantics as an Accepted extension to ADR 0011. Use the repository format.
Keep implementation status in the roadmap and rejected choices only under
Alternatives Considered. Focus on ConfigKit, without downstream semantics.
4. Note the extension in ADR 0011's status/navigation if needed; preserve its
accepted decision text. Record the additive minor-release assessment without
selecting a version or adding release gates.
Validate: whitespace and local-documentation-link checks. Done: baseline and
decision are recorded; implemented behavior is unchanged.
Baseline evidence (2026-10-14): revision `934c1022e038115475c1d33dd85216855b8be522`
on `main`; the worktree was clean and four commits ahead of `origin/main`.
Local toolchain: `go1.26.8 linux/amd64`. `./scripts/check.sh` passed, including
format/whitespace checks, all Go tests, vet, build, examples, local links, and
package-boundary checks. No environmental limitations. Existing coverage is
centered in `internal/engine/parse_test.go`, `imports_test.go`, `glob_test.go`,
`native_filesystem_test.go`, `version_path_test.go`, and the `destination_*_test.go`
files; public/lifecycle coverage includes `facade_destination_test.go`,
`facade_layered_test.go`, `facade_version_test.go`,
`facade_resource_context_test.go`, `facade_inheritance_test.go`, and
`facade_diff_test.go`, with engine resource and history coverage in
`resource_context_test.go` and `inheritance_history_test.go`.
Done: baseline and decision are recorded; implemented behavior is unchanged.
## Stage 2 — Refactor traversal to explicit per-document placement
Status: complete. Scope: private context plumbing; old syntax remains unchanged.
1. Add the relative-destination slot to `importDeclaration`, initially zero for
all parsed declarations. Add the destination-append helper and bounded
literal-path/ownership tests using existing Path conventions.
2. Give `walkDeclarations` the parent's destination, compute each child once,
pass it into `visitPath`, and pass that child path to recursive walks. Remove
the traversal's uniform destination field and update private callers/tests.
Initialize the first walk from the entry Input destination.
3. Use the per-call destination in records, `placeDocument`, version checks,
and wrapper accounting. Leave glob matching unchanged; each match receives
the computed child path without re-appending relative segments.
4. Narrow source-record assignment per decision 8. Check import-context/open
failures, imported parse failures, successful imports, and the completed
Mapping error regression. Exported fields/signatures remain unchanged.
5. Add one small engine fixture with private nonzero declaration destinations
proving accumulation and sibling/glob isolation before parsing is enabled.
Public syntax and complete acceptance follow Stage 3.
Validate: `go test ./internal/engine -run 'Import|Glob|Destination|Grouped'`,
`go test . -run 'Destination|FacadeLayered|Mapping'`, and `./scripts/check.sh`.
Done: baseline loads remain equivalent; all placement consumers use explicit
document context and no uniform setter can erase per-import placement.
Evidence (2026-10-14): based on `a8beb3e62014cb960f3c922c79cd98bd04a657e7`,
using `go1.26.8 linux/amd64`. The focused engine command, the root destination,
layered, and Mapping regression tests, and `./scripts/check.sh` all passed. The
private traversal fixture verifies nested accumulation, sibling isolation, and
one shared destination across glob matches; failure fixtures verify entry
placement survives import-context and imported-parse errors. No limitations.
## Stage 3 — Accept and document the selected YAML syntax
Status: complete. Scope: directive parsing and first complete public behavior.
1. Parse sequence-of-strings `destination` in `parseImportDeclaration`.
Construct literal keys, normalize with existing destination validation, and
retain the relative path. Use `CodeImportInvalid` and actual declaration or
member nodes for failures; retain path/glob locations independently.
2. Add table-driven parser coverage: omission, `[]`, valid nonempty lists,
empty/slash/tilde/dot/numeric strings, null/scalar/non-string failures, and
exact reserved versus substring keys. Preserve mutual exclusion of path/glob,
unknown-field failures, and optional's boolean type. One invalid optional
missing path and one unmatched glob prove validation precedes suppression;
no full cross-product is needed.
3. Add public ordinary-root `Load` and mounted layered entry cases. Include
path/glob imports, a child with its own import, a subsequent sibling, and
multiple matches. Assert final values and individual source destinations;
context leakage must fail the test.
4. Update canonical import/input-destination sections in `docs/config.md` when
syntax lands. Qualify uniform inherited-placement claims with omission;
explicit suffixes accumulate from the immediate parent. No Go API change.
Validate: focused engine import/glob/destination tests, public import-destination
tests, local links, and everyday check. Done: syntax works across existing
import-capable entry points and acquisition forms, not a silently ignored or
root/path-only subset.
Evidence (2026-10-14): based on `49c0c6d908c0746a0ae49a332691c383ac3ff941`,
using `go1.26.8 linux/amd64`. Engine import/glob/destination tests, root public
destination and mounted-load tests, `TestLocalDocumentationLinks`, and
`./scripts/check.sh` all passed. Coverage includes literal keys, malformed
shapes and members with source-local coordinates, validation before optional
missing/unmatched suppression, and ordinary-root plus mounted layered loads.
No limitations.
## Stage 4 — Verify composition and effective version ownership
Status: complete. Scope: assembly interactions; reuse existing algorithms.
1. Cover disjoint same-destination contributions, different destinations,
ancestor overlaps, and collisions with explicitly wrapped content. Equal and
unequal non-mapping overlaps remain strict conflicts. Verify an upper tier
cannot repair a lower strict-group conflict.
2. Exercise deliberate upper-tier overrides: recursive maps, retained omitted
fields, atomic sequences, and an ordinary version-only override retaining
the rest of the prompt. Overlay/CLI paths stay application-rooted.
3. Verify accumulated placement governs imported protected-path/ancestor claims
and ordinary nested `version` fields remain payload. Main's hook runs once
at its existing point; exact-path numeric conversion does not spread. Reuse
current inheritance/overlay/CLI version guards where they prove unchanged
behavior.
4. Test repeated physical sources at distinct logical destinations, including
direct-input/import aliases and cycles reached through changed placement.
Keep original inclusion routes/locations; add no namespace uniqueness.
Validate: `go test ./internal/engine -run 'Import|Destination|Compose|Overlay|Override|Version|Grouped'`
and everyday check. Done: relative placement changes neither tier semantics nor
the main-owned version contract.
Evidence (2026-10-14): based on `4635ef08d5cbeec0b1a1f316cff59cf99e70eba0`,
using `go1.26.8 linux/amd64`. The engine import/destination/composition/overlay/
override/version/grouped suite, root destination/layered/version suite, and
`./scripts/check.sh` all passed. New coverage exercises strict peer behavior,
wrapped-content conflicts, lower-tier conflict preservation, nested protected
version paths, main-checker timing, and repeated/cyclic physical sources under
changed destinations. Existing destination overlay tests continue to verify
root-scoped upper tiers. No limitations.
## Stage 5 — Verify accumulated resource accounting
Status: complete. Scope: limit regressions and any necessary narrow correction.
1. Audit `placeDocument`, `destinationWrapperNodeCount`, `importAccounting`,
and composition totals. Each body uses the full effective destination for
depth/wrapper nodes, charged once. Keep raw directives in acquired accounting.
Synthetic wrappers add no bytes, source count, glob visits, or import depth.
2. Add below/at/above cases with small private limit fixtures where existing
seams permit. Cover a short suffix whose accumulated path exceeds placed
depth, empty bodies at nested destinations, and several glob matches sharing
aggregate nodes. Derive counts from fixture helpers, not copied defaults.
3. Verify valid optional missing/unmatched sources create no source record or
wrappers, including when their unused destination would be deep. An actual
empty mapping is explicit. Reuse Stage 3 for malformed optional declarations.
4. Confirm later overlays/CLI and history/expansion checks see correct totals.
Reuse baseline tests; introduce no cap, performance assertion, or new failure
precedence merely for this feature.
Validate: focused import/destination/limit/override tests and everyday check.
Done: accumulation cannot bypass current bounds or falsely charge absent input.
Evidence (2026-10-14): based on `430985c6293ca8f9151149f1af34481ac325eed3`,
using `go1.26.8 linux/amd64`. The focused engine import/glob/destination/grouped/
overlay/override/history/inheritance suite and `./scripts/check.sh` passed.
Exact, below, and above node-budget fixtures cover nested empty imports and
multiple glob matches using their accumulated destinations. Additional cases
verify accumulated depth bounds and that absent optional path/glob contributions
at unused depth add no source or wrapper charge. Existing
`TestSelectedOverlayAndCLIUsePlacementNodeCharges` continues to cover later
overlay/CLI accounting. No limitations.
## Stage 6 — Preserve diagnostics, source inspection, and resource contexts
Status: complete. Scope: coordinates, detached records, and resource ownership.
1. Check entry/child/grandchild source records' individual destinations, kinds,
IDs, physical paths, and ImportedFrom locations. Include public failure
records after imported parse and effective-path version/composition errors;
preserve existing reporting completeness.
2. Directive failures identify source-local paths and actual locations.
Composition/typed-validation failures use effective paths with authored
content coordinates. Keep syntax/read failures and Mapping rebasing at their
established boundaries; never prefix all diagnostic paths.
3. Use temporary host files and a native-filesystem fixture to prove physical
joins stay relative to the declaring file as destinations change. Exercise
byte/reader/mapping entries with existing explicit filesystem contexts where
applicable; imported files keep existing acquisition contracts. Reuse source
equivalence tests rather than duplicate a whole matrix.
4. Through resolution/result APIs, follow a direct and inherited resource field
to its original filesystem/base, including a lower value surviving override.
Application/test code owns opening the resource.
5. Mutate returned copies, repeat queries, and compare independent loads to
verify detached destination storage. Confirm library acquisition handles
close before return and existing failure cleanup remains covered.
Validate: focused public import/destination and engine resource/provenance/
diagnostic/import tests, `go test -race ./internal/engine`, and everyday check.
Done: logical placement is inspectable without changing physical identity,
filesystem lifetime, or the public facade boundary.
Evidence (2026-10-14): based on `43e55dfa85963d050d5899aec9d96f4ef637ebf6`,
using `go1.26.8 linux/amd64`. Focused public facade import/destination/resource
tests, the engine import/destination/provenance/diagnostic/resource suite,
`go test -race ./internal/engine`, and `./scripts/check.sh` all passed. New
coverage verifies exact host and native physical source paths, IDs, kinds,
effective destinations, declaration locations, native resource opens from
their declaring directories, detached destination copies across repeated and
independent loads, and public source/diagnostic records for imported parse,
source-local directive, effective-path composition/version, and typed validation
failures. Existing layered inheritance/context and source-acquisition tests
cover inherited lower values, explicit filesystem contexts, and cleanup. No
limitations.
## Stage 7 — Verify inheritance, history, sensitivity, and diffs
Status: complete. Scope: retained placed data and one final application lifecycle.
1. Resolve a sibling parent/child supplied by separate relative imports after
all tiers. Reuse nested inheritance/cancellation tests; add no cross-collection
lookup semantics.
2. Compare a relative-import load with equivalent wrapped/per-input-placed
inputs. Values, presence, and safe diff equality agree; physical source
locations may naturally differ.
3. Cover historical contributions, replaced/removed descendants, effective-path
and field-tag sensitivity, inherited fields, and a recorded derived value
using existing dependencies. Check effective rendering, explanations/history,
and bilateral diffs with disposable canaries. Preserve the existing
Redacted/HiddenChanged distinction.
4. Verify defaults, decode, resolution, secret lookup, and semantic validation
use the final assembled shape without per-fragment callbacks. No source header
is checked, consumed, coerced, or retained as a new evidence type. Failures
still return no usable partial result.
Validate: engine `Import|Destination|Inheritance|Secret|Sensitivity|Explain|Diff`
tests, representative facade tests, and everyday check. Done: the feature feeds
existing inspection/completion mechanisms without reconstructing them.
Evidence (2026-10-14): based on `6458dbd`, using `go1.26.8 linux/amd64`. The
engine import/destination/inheritance/secret/sensitivity/explanation/diff suite,
representative facade import/destination/resource tests, and
`./scripts/check.sh` all passed. New integration coverage resolves siblings
from separate relative imports after a higher-tier parent replacement, then
checks inherited secret fields, one-time defaults/resolution/validation/secret
lookup, effective-path sensitivity, derived-value history, safe explanations,
and bilateral redacted diffs. Relative-import output also matches equivalent
wrapped placement in values, field presence, and safe diffs. Existing nested
inheritance and displaced-descendant tests continue to cover cancellation and
removed descendants. No limitations.
## Stage 8 — Demonstrate ordinary and mounted collection entries
Status: complete. Scope: maintained public examples and their behavior tests.
1. Add a compact ordinary-root example: its entry imports metadata and a fragment
with `destination: [prompts]`, using existing `Load` import opt-in and no
Input destination or header policy.
2. Add/adapt a maintained layered example under `examples/consumers`. Mount an
entry beneath collection keys and let its YAML declare metadata/prompt/profile
placement, including a nested import. Keep the application schema declaration
main-owned. The entry has no consumed specification header; collection/prompt
version labels are ordinary payload.
3. Include peer composition, local sibling inheritance, an upper-tier version-only
domain override, and a source-relative resource query where representative.
Reuse current example types/fixtures; keep imports compact and necessary.
4. Test final values, source placement, presence, and resource context through
supported APIs. Applications select sources/tiers and interpret resources;
add no source rewriting, generic merging, or provenance reconstruction.
Link maintained examples from the consumer guide.
Validate: `go test ./examples/consumers`, applicable executable `Example` tests,
local links, and everyday check. Done: ordinary and layered workflows operate
without the deferred source-header proposal.
Evidence (2026-10-14): based on `a20ba0a`, using `go1.26.8 linux/amd64`.
`go test ./examples/consumers`, root executable examples, local documentation
links, and `./scripts/check.sh` passed. The ordinary-root sample uses `Load`
with import opt-in and entry-authored root/prompt placement. The mounted
collection example now declares metadata, prompt, and profile destinations in
its entry YAML and exercises nested imports, while Go selects only the mount
and main-owned schema policy. Behavior checks cover strict peer composition,
post-tier prompt/profile inheritance, the version-only operator tier, effective
source placement, and reading inherited prompt content from its source context.
No limitations.
## Stage 9 — Reconcile documentation and audit the complete feature
Status: complete. Scope: final consistency and evidence; no publication work.
1. Reconcile `docs/config.md`, declaration comments, consumer guide, component
overview, and development reading/test maps. Change only affected material.
Distinguish input entry placement and per-import effective placement; remove
unqualified uniform-inheritance claims. Add ADR navigation. Update architecture
policy only as needed to recognize the extension and link exact behavior to
its canonical contract.
2. Map each relative-import request row and roadmap behavior to specific tests
or examples here. Include root/layered loads, host/native acquisition, literal
keys, parser failures, peer/glob isolation, composition/version ownership,
failure records, resources, disclosure/history/diffs, accumulated limits, and
empty/absent contributions. Explain reused evidence; header rows stay deferred.
3. Review the baseline-to-candidate diff for accidental strengthening: extra
naming rules/caps, weakened containment/repetition, root resets, shifted
callbacks/version phases, error-order promises, header processing, or expanded
merge/secret semantics. Check explicit per-document traversal and the absence
of a uniform post-traversal source overwrite.
4. Run `./scripts/check.sh` and
`GOTOOLCHAIN=local GOPROXY=off go test -race ./...`. Record revision, Go version,
commands, results, and limitations. Check links and root/private boundary
coverage; no performance claims or new release gates.
5. Mark this plan and the relative-import roadmap complete only when code, tests,
maintained examples, and canonical docs agree. Preserve the broader request's
unfinished header proposal. Retain completed records until separately
authorized release preparation; no release/downstream upgrade is implied.
Done: authors can declare immediate-parent-relative path/glob destinations in
existing import-capable loads with coherent values, provenance, bounds, and
ownership. Independent specification headers remain a separate future decision.
Evidence (2026-10-14): starting revision `08e03f6`, using
`go1.26.8 linux/amd64`. The local documentation-link plus root/private boundary
tests, `GOTOOLCHAIN=local GOPROXY=off go test -race ./...`, and
`./scripts/check.sh` all passed. The implementation diff from the recorded
baseline was reviewed: production changes are limited to per-import YAML
parsing, immediate-parent traversal/placement, and retaining each source's
effective destination. It adds no public API, source-header processing, key-name
grammar, new limit, root reset, callback/version phase, precedence, or secret
semantics. The request-to-evidence matrix above covers the accepted import-
destination rows; the unfinished independent-header proposal remains separate.
No limitations. Release preparation and publication were not performed.
15. Carry private evidence per acquired SourceID in per-load acquisition/assembly
state, separate from application history. Retain an owned scalar/absence,
original local and mounted semantic paths, location, and the ancestor-shape
context needed for classification. Capture key/index intent before deletion.
Retain only needed context, not entire source-tree clones or loading handles.
16. At publication classify evidence at its original mounted path and ancestors
with existing schema tags, predicate, historical projected sensitivity,
inheritance, and recorded-dependency propagation. Include evidence-only
candidates in classification without adding them to Metadata paths, payload
applications, rendering, or Diff. Do not infer original sequence shape from
shifted payload or round-trip through pointer strings. Reuse dependency
closure rather than building a weaker independent redactor. Retained header
text never triggers credential lookup.
17. Sanitize source records before public conversion; early records remain
conservatively redacted. Final successful evidence uses completed sensitivity,
retaining historical classification despite replacement. Main's normal
payload/history remains intact. Consumed non-main headers are only source
evidence: equal payloads with different headers must not acquire effective
differences merely from that evidence.
## Implementation owner map
Use graph discovery to confirm current symbols and locations before editing:
- `internal/engine/directives.go`: `importDeclaration`,
`parseImportDeclaration`, `parseImportDirective`, `splitImportDirectives`,
and source-local diagnostic construction.
- `internal/engine/imports.go`: `importTraversal`,
`loadImportedWithAccessTracked`, `walkDeclarations`, `visitPath`, and shared
accounting. `glob.go` owns physical matching and its ordering.
- `internal/engine/destination.go`: `normalizeDestination`, `placeDocument`,
`destinationWrapperNodeCount`, and source-destination assignment.
- `internal/engine/load_input.go`: `assembleBaseInputTracked`, early failures,
context handoff, and completed Mapping diagnostic remediation.
- Existing assembly/lifecycle: `load_request.go`, `load.go`, `compose.go`,
`inheritance_load.go`, and metadata/history/rendering/diff owners.
- Root inspection: `records.go`, `conversion.go`, `layered.go`, and existing
public destination/import tests. No new exported Go surface.
- Behavioral foundations: engine `imports_test.go`, `glob_test.go`,
`destination_import_test.go`, `destination_accounting_test.go`,
`destination_diagnostic_test.go`, `destination_provenance_test.go`,
`destination_integration_test.go`, `destination_import_lifecycle_test.go`;
root `facade_destination_test.go` and `facade_resource_context_test.go`; and
maintained consumer fixtures/tests. Reuse owners rather than duplicate suites.
## Relative-Import Behavior Evidence
The accepted relative-import scenarios in the broader request are covered by
the following focused owners. Existing test suites are cited where this work
reuses their unchanged contracts; independent source-header checking remains
deferred and is not represented as implemented evidence.
| Behavior | Evidence |
| Responsibility | Existing owners to inspect and extend |
| --- | --- |
| Omitted/empty destinations, literal key sequences, malformed shapes and source-local member locations | `TestParseImportDestinationUsesLiteralStringSegments`, `TestParseImportDestinationRejectsInvalidShapesAndMembers`, and `TestImportDestinationValidationPrecedesOptionalSuppression` in `internal/engine/imports_test.go`; root and mounted behavior in `TestFacadeRelativeImportDestinationsForRootAndMountedLoads` |
| Immediate-parent accumulation, sibling isolation, same suffix for glob matches, and physical traversal | `TestImportTraversalUsesPerDeclarationDestinations`, host/native import tests in `internal/engine/destination_import_test.go`, existing physical ordering in `internal/engine/glob_test.go`, and `TestFacadeRelativeImportDestinationsPreserveNativeResourceContexts` |
| Peer conflicts, tier overlays, version ownership, cycle/repetition identity, and main-owned checker scope | `TestRelativeImportDestinationsKeepStrictCompositionBoundaries`, `TestRelativeImportDestinationsUseEffectiveVersionOwnership`, `TestRelativeImportDestinationsKeepMainVersionCheckScoped`, and `TestLayeredDestinationsDoNotChangeRepeatedSourceIdentity` in `internal/engine/destination_import_test.go`; `TestFacadeSameFragmentMountsAtSeparateCollectionDestinations` |
| Public failure records, source-local directive errors, effective paths, original content coordinates, and complete failure reporting | `TestFacadeRelativeImportFailuresRetainSourceRecordsAndCoordinates`, `TestEntryDestinationSurvivesImportSetupAndParseFailures`, existing imported diagnostic/remediation tests, and `TestFacadeDestinationMappingFailurePaths` |
| Host/native source records, direct and inherited resources, physical resource bases, and detached destinations | `TestFacadeRelativeImportDestinationsForRootAndMountedLoads`, `TestFacadeRelativeImportDestinationsPreserveNativeResourceContexts`, `TestLayeredImportedInheritedValuesRetainResourceContexts`, and existing source-equivalence/resource-context suites |
| Final sibling inheritance, defaults/decode/resolution/secret lookup/validation lifecycle, history, sensitivity, explanations, rendering, and bilateral diffs | `TestRelativeImportsFeedFinalInheritanceAndInspectionLifecycle`, `TestRelativeImportMatchesWrappedPlacementAndSafeDiff`, existing nested inheritance/cancellation and displaced-descendant tests, and the destination-sensitive diff suite |
| Accumulated depth/node accounting, multiple glob contributions, actual empty mappings, and absent optional path/glob imports | `TestImportedEmptyBodiesChargeFullRelativeDestinations`, `TestGlobMatchesChargeTheirSharedRelativeDestination`, `TestRelativeImportDestinationUsesAccumulatedDocumentDepth`, and `TestAbsentOptionalImportsDoNotChargeUnusedDeepDestinations` in `internal/engine/destination_accounting_test.go` |
| Ordinary and mounted consumer workflows, application-owned resource opens, and guide links | `Example_rootRelativeImports` and `TestPromptBundleUsesRelativeImportDestinations` in `examples/consumers/layered_test.go`; `TestCollectionBundleAssemblesMountedPeersAndResources` and `TestCollectionPeerPromptConflictsRemainStrict` in `examples/consumers/destinations_test.go` |
| Public options, callbacks, records, conversions | `lifecycle.go`, `layered.go`, `records.go`, `conversion.go`, `diagnostic.go` |
| Options and per-load coordination | `internal/engine/options.go`, `load.go`, `load_request.go`, `layered.go` |
| Acquisition, directives, placement, overlay | `internal/engine/load_input.go`, `imports.go`, `directives.go`, `destination.go`, `selected_overlay.go` |
| Checking and semantic paths | `internal/engine/validation.go`, `document_walk.go`, `version_path_test.go` |
| Evidence copies, errors, publication | `internal/engine/records.go`, `diagnostic.go`, `load_result.go` |
| Classification and propagation | `internal/engine/secret.go`, schema secret-path helpers, `secret_propagation_test.go`, `render_test.go` |
| Compatibility tests | Engine `load_test.go`, `imports_test.go`, `selected_overlay_test.go`, `load_request_test.go`, `destination_*_test.go`; root `facade_version_test.go`, `facade_layered_test.go`, `facade_destination_test.go`, `records_test.go` |
The public acceptance rows about file/reader/mapping sources reuse
`facade_equivalence_test.go`, `TestFacadeInputDestinationsAcrossSourceKinds`,
and the explicit-filesystem import tests. The rows about protected paths,
source-local resource ownership, history, and disclosure reuse the input
destination, inheritance, resource-context, and diff owners named above; this
feature adds integration checks rather than a duplicate cross-product. The
broader request's independent source-header rows remain proposals for separate
consideration.
Private helper names/file splits may follow the implementation while preserving
these decisions. A new internal package solely for headers is unnecessary.
## Open Questions
## Validation commands
None required for this feature. Selected list syntax and existing placement
contracts resolve the public choices; this plan settles context, diagnostic,
and accounting details within them. Report a newly discovered incompatibility
with evidence and alternatives rather than adding a restriction or implementing
the separate source-header proposal.
Use the applicable subset during each stage; add new tests under the
SourceVersion name family so focused checks include them. Existing test owners
remain authoritative. Commands run from the repository root with dependencies
already available; these are development checks, not new release gates.
```sh
GOTOOLCHAIN=local GOPROXY=off go test ./internal/engine -run 'SourceVersion|Version|Import|Underlay|Overlay|Destination'
GOTOOLCHAIN=local GOPROXY=off go test ./internal/engine -run 'SourceVersion|Secret|Sensitivity|History|Inheritance|Resolution'
GOTOOLCHAIN=local GOPROXY=off go test . -run 'SourceVersion|Version|Layered|SourceInfo|Destination|PublicFacadeBoundary|DependencyImportBoundary'
GOTOOLCHAIN=local GOPROXY=off go test ./examples/consumers
GOTOOLCHAIN=local GOPROXY=off go test . -run '^TestLocalDocumentationLinks$'
GOTOOLCHAIN=local ./scripts/check.sh
GOTOOLCHAIN=local GOPROXY=off go test -race ./...
git diff --check
```
## Stage 1 — Capture the baseline and record the extension
1. Confirm the worktree/baseline; read the roadmap, plan, applicable policies,
contract, and relevant ADRs. Run the everyday check and record revision,
toolchain, results, and environmental limitations.
2. Write Accepted ADR `0013-shared-source-version-checks.md` after checking the
number is unused. Record one policy, modes, source-local checking, consumption,
evidence, and retained main protection. Focus on ConfigKit's selected choice;
rejected choices belong only in Alternatives Considered. Keep sequencing here.
3. Preserve prior accepted decision text. Add status/navigation links where
useful. Note struct additions and enabled mounted-main interpretation as
minor-release considerations; do not select a version or write release notes.
Validate: local-link test and whitespace. Done: baseline and accepted decision
recorded, with no runtime changes.
## Stage 2 — Share version interpretation without changing defaults
1. Separate reusable value interpretation and callback reporting from checkVersion,
retaining its default entry point, absence/null/text, exact integers, warnings,
safe errors, primary/related locations, and context closure.
2. Reuse existing scalar/path/hook/lifetime tests; add only missing protection for
the refactor. Introduce a small private result separating checked value and
diagnostics. Failure decisions must use severity, not slice length.
3. Do not globally rewrite unrelated diagnostic plumbing or public behavior.
Validate: engine version/validation and facade version tests; everyday check.
Done: shared mechanisms exist with unchanged default behavior.
## Stage 3 — Implement source-local extraction and exact consumption
1. Add a private processor receiving original document, local rule, source role,
destination, and mode. Implement decisions 6–12, including missing/obstructed
lookup and pre-consumption structural overlap.
2. Return owned remaining payload, original import declarations, and private
evidence with original segment/ancestor context. No second parser, fragment
decoding, or mutation of reusable input.
3. Add focused tests for vocabulary, missing/obstructed locations, malformed
selected nodes, literal/parsed numeric keys and indices, empty ancestors,
sequence deletion, and actual versus unrelated structural overlap.
Validate: helper/version-path/directive/inheritance-control tests and everyday
check. Done: the processor is tested independently of public loading.
## Stage 4 — Add private mode state and main-document integration
1. Add the engine mode to ordinary/layered options and loadRequest. Validate it at
both entry points before source access. Underlay helper options must not be
treated as standalone loads missing the shared rule.
2. Carry local/effective rules, source roles, warnings, and evidence in per-load
state. Let acquired inputs return evidence and nonfatal diagnostics.
3. In enabled mode, check actual main before imports/composition, retain its node,
and prepare schema before callbacks. Skip the old later main check only in
enabled mode. Preserve NoSource's absent callback and default timing.
4. Thread effective protection through typed conversion, inheritance, CLI, and
application inspection while keeping declaration callbacks local. Test mounted
main, absence/NoSource, null acceptance, invalid options before reading, and
exactly one main callback.
Validate: load/grouped/version/destination/hook tests and everyday check. Done:
private enabled main behavior works without changing old callers.
## Stage 5 — Integrate recursive imports, warnings, and accounting
1. Thread shared state through import entry/traversal. Check each acquired child
once against its own local header, then place and compose remaining payload.
Keep nested/glob effective destinations and original directive discovery.
2. Apply effective main protection afterward. Preserve physical identity,
cycle/repetition, optional absence, source records, resource contexts, and raw
node/byte charges. Header-only acquired mappings still contribute empty bodies.
3. Propagate warnings to load diagnostics without aborting traversal. Update only
relevant callers currently treating any diagnostic as failure.
4. Cover nested/glob imports, mounted relative destinations, accepted unequal
declarations, rejected hidden declarations, required omissions, safe locations,
optional missing sources, raw accounting, and default import.version failures.
Reuse existing containment/glob/source-kind tests.
Validate: import/glob/destination/accounting/version tests and everyday check.
Done: imports use one policy without lost warnings or changed physical traversal.
## Stage 6 — Integrate direct underlays and their strict groups
1. Thread state through acquireUnderlayGroup/grouped assembly. Direct underlays
are non-main; imports reuse Stage 5. Preserve layers, indices, contexts,
evidence, and warnings across groups.
2. Consume local headers before strict composition, then protect remaining placed
payload. Preserve tier precedence, empty containers, raw budgets, and reusable
sources in allowed separate tiers.
3. Cover accepted distinct peer declarations, a rejected underlay hidden by main,
required absence, empty/NoSource groups, mounted nested headers, retained
payload conflicts, and unchanged default underlay.version failures.
Validate: grouped/underlay/destination/version tests and everyday check. Done:
direct and imported underlays follow the same checking policy.
## Stage 7 — Integrate selected overlays and final ownership checks
1. Process overlay headers after parse/structural validation, before remaining
payload protection and application. Reuse shared state in ordinary and layered
overlay loading; preserve source identity, namespaces, close behavior, and raw
node/byte charges.
2. Carry accepted warnings through assembly. Keep overlay-control restrictions,
and effective main protection through CLI and inheritance.
3. Cover accepted/required/rejected overlay headers, warnings, unchanged default
behavior, ordinary CLI fields without header requirements, mounted-main
protection, and protected payload after nested/sequence consumption. Sequence
evidence stays original while remaining indices shift.
Validate: overlay/override/inheritance/version tests and everyday check. Done:
all document roles are integrated privately; synthetic operations are exempt
from header checks, not from existing protection.
## Stage 8 — Expose the public load-wide mode
1. Add root mode/constants/option fields and both conversions from decision 1.
Preserve zero-value behavior and root-owned boundaries.
2. Add external-package tests for ordinary/layered enabled loads, zero-mode
compatibility, invalid mode/rule before reading, and reuse of one Definition
with different modes. Use representative source-kind coverage.
3. Document implemented mode behavior in Go declarations, including local versus
effective interpretation. Evidence remains private until Stage 11; do not
claim it is publicly available yet.
Validate: facade version/layered/source and boundary tests; everyday check.
Done: both supported public load APIs expose the implemented modes.
## Stage 9 — Classify evidence at original paths and ancestors
1. Include declaration paths/ancestors in final classification candidates,
independently of effective/historical Metadata indexes. Do not add consumed
nodes to applications or explanation replay.
2. Apply schema-tag and predicate rules using original mounted semantic context,
including tags beneath dynamic containers and ancestor classification.
Preserve numeric-key/index intent before sequence shifts; consumed paths need
not survive final decoding. Reuse existing redaction mechanisms.
3. Test private evidence with disposable canaries: unclassified text, direct/
ancestor tags and predicates, original sequence shape versus shifted payload,
and null/absence. Keep raw evidence private throughout this stage.
Validate: source-version/sensitivity/rendering tests and everyday check. Done:
direct/ancestor classification is correct without making headers payload history.
## Stage 10 — Preserve historical and dependency sensitivity
1. Connect evidence candidates to existing historical, inheritance, and recorded
dependency propagation. Later replacement or consumption must not erase
applicable classification; do not invent new propagation policy.
2. Consider evidence-only paths even when absent from final metadata. Keep
Resolution.Record's existing schema-path validity; do not invent dependencies
on headers solely to create tests.
3. Cover displaced historical classification and legitimate recorded dependencies,
with inheritance where applicable. Ensure neighboring unclassified evidence
remains visible and no synthetic effective/history/diff paths are introduced.
Validate: source-version/history/inheritance/resolution/sensitivity tests,
`go test -race ./internal/engine`, and everyday check. Done: established
sensitivity closure applies without polluting payload history.
## Stage 11 — Publish detached sanitized source evidence
1. Add private/public SourceVersionCheck and SourceInfo.VersionCheck records.
Extend both conversions and all clone paths, including callback source queries,
successful inspection, and existing LoadError source access.
2. Before final classification, expose conservative sanitized records; after
successful classification, freeze final sanitized evidence. Keep local paths,
physical locations, absence/null, and unchecked distinction. Raw evidence
stays in private state; no loading handle is retained.
3. Add facade/copy tests mutating nested paths/locations and records. Repeated
queries and independent loads remain unaffected. Delete sources after load
and verify evidence/resource metadata without reopening files.
4. Cover early acquisition and later resolver/validator failures plus callback
source queries with canaries. Default and synthetic CLI records stay nil.
Validate: record/conversion/source/version/ownership and public boundary tests,
root/engine race checks, and everyday check. Done: existing public source
inspection surfaces safely expose detached evidence.
## Stage 12 — Audit lifecycle agreement and compatibility
1. Map tests to every roadmap participation row/edge decision; add only missing
cross-boundary regressions with one primary owner per behavior.
2. Verify final values, zero/false/null presence, defaults, exact-path integer
conversion, resolution, secret lookup, and validation after consumption.
Hooks see one assembled configuration. Accepted declarations need not match.
3. Compare equal payloads with differing consumed headers: evidence changes but
effective rendering/history/Diff gain no consumed fields. Main history stays
normal. Cover empty ancestors and ordinary versions outside the header path.
4. Check physical contexts after placement/inheritance/precedence, existing
accounting boundaries, all supported document source kinds, and default
import/underlay/overlay/CLI/version compatibility.
5. Run `./scripts/check.sh` and
`GOTOOLCHAIN=local GOPROXY=off go test -race ./...`. Record actual evidence;
do not claim untested platforms or consumer adoption. Consumer checks are not
new release gates.
Done: all target behavior has public-boundary evidence and deterministic checks
pass, without extra contract restrictions or redundant coverage.
## Stage 13 — Add maintained adoption examples
1. Add a small executable example showing if-present and required adoption with
one Definition.Version policy, accepted distinct declarations, main/import/
underlay or overlay sources, and safe evidence inspection.
2. Include a mounted input illustrating local lookup and effective main
protection. Keep ordinary release metadata at another path; no consumer-side
second load/merge, collection checker, or implicit schema migration.
3. Keep copyable assets in examples with tests for final payload and safe output.
Reuse existing examples for remaining source plumbing; do not print canaries
or promise callback ordering.
Validate: example/consumer tests, links, and everyday check. Done: tested examples
demonstrate the coherent shared policy with reduced consumer plumbing.
## Stage 14 — Reconcile documentation and finish the audit
1. Update Go docs and docs/config.md as canonical owners for modes, participation,
local diagnostics, consumption, effective protection, mounted main, evidence
states/disclosure, and default behavior. Explain conservative callback-time
redaction and declared compatibility versus final validation. Link from
consumer guidance, development, and internal overview.
2. Update the architecture ownership summary where needed, linking to contract
and ADR rather than duplicating mechanics. Preserve previous accepted ADR
decisions. Reconcile obsolete design/consumption notes in the source request.
Repair completed relative-import roadmap/remediation links that meant the old
overwritten plan, using the Git-history pointer above.
3. Audit for accidental default checks, equality/non-null rules, path grammar,
fragment decoding, ordering promises, extra uniqueness/caps, unsafe evidence
queries, and new release gates. Match every roadmap outcome to test evidence.
4. Mark plan/roadmap complete only after all stages pass. Run everyday checks,
full race suite after code corrections, and final link/whitespace checks.
Commit the validated unit; leave a clean workspace. Do not publish or retire
completed records in this stage.
Done: implementation, coverage, documentation, and approved scope agree. No
product questions remain open under the roadmap and concrete decisions above.

View File

@@ -1,7 +1,9 @@
# Shared Source Version Checks Roadmap
Status: design decisions settled; implementation has not started. Execute the
stages below in order. This roadmap develops the partially accepted source-version request in
Status: design decisions settled; implementation has not started. The
[implementation plan](implementation.md) owns execution order, concrete API and
integration decisions, and completion evidence. This roadmap develops the
partially accepted source-version request in
[PromptKit's proposal](promptkit-feature-request.md#partially-accepted-addition-shared-source-specification-checks)
using the consumer's single `Definition.Version` policy. The design direction
below incorporates the maintainer's subsequent decisions on lookup, consumption,
@@ -17,8 +19,8 @@ Different accepted declarations may coexist: ConfigKit does not require exact
equality with the main declaration, impose SemVer, or invent an expected value.
The consumer selects a load-wide enum on ordinary and layered options. Its zero
value retains current behavior; exact exported names remain implementation design
work. The same `Definition.Version` can be reused across loads with different
value retains current behavior; the implementation plan selects exported names.
The same `Definition.Version` can be reused across loads with different
strictness. The three modes are:
| Mode | Missing non-main declaration | Present non-main declaration |
@@ -164,118 +166,45 @@ destinations are implemented; the
dedicated checked-version evidence. Existing sensitivity and inspection are
primarily organized around application paths and retained application trees.
## Ordered implementation plan
## Acceptance outcomes
### 1. Finalize the contract and integration design
The completed feature supports all three modes through ordinary and layered
public loading, with these observable outcomes:
Select exact public mode and evidence type names within the agreed load-wide
API, participation, main-path, inspection, and edge-case decisions. Define header
lookup for nested paths and distinguish a missing member from an obstructing
non-container ancestor. Specify consumption without broadening it into a generic transformation
API. Preserve authored ancestors when consuming nested mapping headers as agreed;
apply the agreed sequence-element removal and structural-overlap rejection rules.
- One checker can accept several distinct source declarations. Rejected acquired
declarations fail the load even when later tiers would replace their payload.
- Absence, explicit null, strings, exact decimal integers, and malformed selected
values follow the shared version vocabulary and selected mode.
- Main retains its own declaration and is checked once; mounted main uses the
enabled mode's source-local interpretation, while NoSource and default mode
retain their documented behavior.
- Every participating document role and supported acquisition kind follows the
same selected policy. Synthetic field operations and absent sources add no
document-header requirement.
- Accepted non-main headers are consumed exactly, preserving authored empty
containers and ordinary sequence-removal semantics. Remaining payload retains
strict composition, precedence, protected-path rules, and ordinary versions
outside the selected header path.
- Source evidence is detached, physically attributed, available without reopening
files, and subject to the agreed sensitivity rules. Warnings survive successful
checks; generated failure messages remain safe.
- Effective values, presence, provenance, history, inheritance, rendering, diffs,
and resource contexts agree with remaining application payload. Consumed
declarations remain separate source evidence; main history stays ordinary.
- Maintained public examples demonstrate gradual and required adoption with one
policy. Current API/configuration documentation describes the delivered
contract, and existing default-mode behavior remains covered.
Record the change to main-only version ownership in an ADR and review public API
compatibility under repository policy. Do not rewrite accepted ADR decisions or
describe the feature as implemented before it lands. Existing default behavior
must remain covered; tests must not turn incidental acquisition ordering or
allocation choices into new guarantees.
Completion: the three modes and every participating source role have defined
lookup, callback, consumption, failure, and inspection semantics.
### 2. Share declaration checking and integrate source acquisition
Separate reusable version-value interpretation and checker reporting from the
current main-only invocation. Carry the selected mode through ordinary and
layered root APIs into the engine. Resolve source-local locations before mounting
and perform non-main checks before composition or precedence can mask them.
Consume only accepted non-main headers, retain their evidence, and apply existing
placement to the remaining body. Integrate direct inputs, recursive imports, and
selected overlays according to the selected participation contract. Continue
checking remaining payload for protected-path claims. Preserve source identity,
resource contexts, and applicable load accounting; consumed input still counts
as acquired input rather than bypassing source limits.
Avoid duplicate main checks or a second load of any document. Preserve the main
declaration's final value and typed conversion behavior. Ensure warnings do not
become failures merely because acquisition helpers previously treated any returned
diagnostic as fatal. Keep returned hook errors safe and callback contexts closed.
Completion: optional and required checks work across participating sources,
incompatible superseded input fails, and disabled-mode loads remain unchanged.
### 3. Expose evidence and verify lifecycle agreement
Add the selected root-owned inspection records and explicit conversions. Retain
source-local declarations and physical locations without fabricating effective
payload paths. Apply the agreed disclosure treatment to retained evidence,
including declarations consumed before final sensitivity evaluation. Return
detached records and preserve evidence when source files subsequently disappear.
Check agreement among configuration, provenance, history, rendering, and diff:
main remains represented normally; consumed headers remain source evidence;
ordinary version payload remains ordinary. Verify diagnostics identify the
actual source even when several documents use the same local header path.
Follow existing load-error reporting rather than promising exhaustive evidence
for documents never acquired after an earlier failure.
Completion: consumers can inspect checked declarations without reopening files,
and evidence does not leak sensitive values or alter effective-value semantics.
### 4. Add public acceptance coverage and update documentation
Use focused engine tests for vocabulary, extraction, and consumption; root tests
for public options and detached evidence; and executable consumer examples for
multi-file loading. Cover these distinct behaviors without duplicating all
existing import and composition tests:
- all modes, with absent, null, string, decimal-integer, and malformed values;
- multiple versions accepted by one checker without equality enforcement;
- required missing declarations and incompatible inputs hidden by later layers;
- main preservation and no duplicate callback, including the chosen mounted-main
interpretation and `NoSource` behavior;
- direct underlays, transitive/glob imports, overlays, and every document source
kind; no header requirement for synthetic field overrides;
- source-local lookup before input and relative-import destination placement;
- nested-header consumption and retained empty containers; sequence-element
removal with shifted payload indexes and original evidence coordinates;
- structural-directive overlap rejection without rejecting unrelated header paths
or ordinary keys containing directive spellings; remaining payload protection;
- ordinary release/prompt version fields outside the header path;
- warning propagation, safe checker failures, real source locations, and absent
header location fallbacks;
- inspectable detached evidence and disclosure using disposable canaries, including
classified header/ancestor paths, historical classification, and safe failures;
- consumed-header exclusion from effective rendering/diffs, with retained main
history and unchanged resource-relative behavior;
- default-mode compatibility, including existing fragment version rejection.
Demonstrate gradual adoption with optional checks and full declaration coverage
with required checks, using one policy. Do not include independent collection
checkers in examples. Update Go declaration documentation, the configuration
contract, consumer guidance, and internal overview as behavior lands; reconcile
the source-header request's earlier remaining-design notes then.
Follow the [development guide](../development.md) and
[testing policy](../policy/testing.md): focused checks during implementation,
the everyday check before handoff, ownership race checks where applicable, and
documentation-link validation. No independent performance benchmarks are part of
this roadmap. Release preparation and publication are separate work.
Completion: the agreed source coverage and three modes work through supported
public APIs, inspection and disclosure agree with the contract, and validation
and documentation are complete. Independent specification policies are not
required to complete this feature.
Independent specification policies, release preparation, and publication are
outside this feature's completion criteria.
## Agreed Edge-Case Decisions
The maintainer has accepted all three decisions below. Together with the mode
API location, source participation, main-path handling, source-record evidence,
and nested mapping ancestor preservation above, these settle the discussed
product decisions. Exact public names and internal mechanics remain implementation
work; the feature is not yet implemented.
product decisions. The [implementation plan](implementation.md) selects public
names and integration mechanics; the feature is not yet implemented.
### Sensitivity of consumed declaration evidence