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 Status: planned; no implementation stages are complete.
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.
Planning baseline: `b2db323`, including input-destination remediation at Audience: a Luna coding agent implementing one numbered stage per prompt, in
`315f464`. The previous completed input-destination implementation record is order. The [feature roadmap](source-version-checks.md) owns target behavior and
preserved at `315f464:docs/roadmap/implementation.md` in Git history. The broader accepted policy; this plan owns concrete implementation decisions and execution.
[consumer request](promptkit-feature-request.md#requested-addition-relative-import-destinations) Planning baseline: `d9f08ff7198ad5a8fb5c49a43e7ccdad2ad0e707`.
also proposes independent specification headers, which are outside this plan.
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 ## Working instructions
- Start with `AGENTS.md`, [development.md](../development.md), applicable policies, - Read `AGENTS.md`, [development.md](../development.md), and applicable policies.
and working-tree inspection. Use graph-first code discovery and preserve This work involves [architecture](../policy/architecture.md),
unrelated changes. Read existing import and placement contracts before edits. [testing](../policy/testing.md), and [documentation](../policy/documentation.md).
- Implement one stage at a time with its relevant tests/documentation. Record Use graph-first discovery, verify live sources, and preserve unrelated work.
actual commands, revisions, results, and limitations here; mark only completed - Implement one stage at a time. Record completion, actual commands, toolchain,
stages and commit each validated nonempty unit with a plain-English message. results, limitations, and implementation revisions here. Commit each validated
- Follow the root-owned facade and private engine/document/YAML boundaries. nonempty unit with a short plain-English message.
Reuse paths, placement, composition, inheritance, version ownership, history, - Keep public types root-owned with explicit engine conversions. Reuse semantic
and resource contexts. No public Go entry point, source-header API, namespace Paths, documents, composition, overlay, version validation, sensitivity, and
registry, or second merger is needed. inspection. No second loader, public parser nodes, generic transformation
- Specification-header checking and consumption remain deferred. Ordinary hooks, or consumer-specific policy.
`version` data, the main-owned checker, exact-path numeric conversion, and - Default mode preserves current behavior, including effective-path lookup,
callback timing keep their existing behavior. Examples must work without the main checker timing, and protected-path failures. Enabled modes deliberately
broader request's combined header example. select source-local declarations and non-main consumption. Do not broaden
- Roadmap exclusions define this delivery, not new permanent prohibitions. Do these changes into unrelated default-mode fixes.
not add directory discovery, caps, key-name grammars, root-reset syntax, - Do not add equality/SemVer rules, non-null requirements, numeric coercion,
arbitrary callbacks, or stronger security/release guarantees. path-form restrictions, source uniqueness policies, limits, dependencies,
- Keep Stage 2 behavior-preserving before Stage 3 accepts new syntax. Once toolchain changes, or release gates. Declaration acceptance is not fragment
accepted, syntax must work through existing import entry points, not only path schema conformance. Exclusions describe this delivery, not new permanent bans.
imports or only root loads. - Internal stages may test modes before exposing them publicly. Keep Go/current
- Use focused offline tests while iterating and `./scripts/check.sh` before documentation accurate to each delivered boundary; the roadmap owns the target.
committing production changes. Documentation-only work needs whitespace and - Use focused offline tests while iterating and `./scripts/check.sh` for each
local-link checks. Ownership race checks belong to Stages 6 and 9. Reuse production-code unit. Documentation-only units need local-link and whitespace
unchanged coverage; do not assert helper-call counts, allocation identity, checks. Reuse existing tests; avoid a full mode/source/tier/path cross-product,
exact diagnostic prose, or a cross-product of already protected cases. helper-call assertions, allocation identity, or exact message snapshots.
- No independent benchmarks, performance thresholds, dependency changes, No independent benchmarks or performance thresholds are required.
toolchain upgrades, or new release gates are required. Prefer copying path - Do not rewrite accepted ADR decisions, publish, select a release version,
segments once per declaration and existing bounded tree processing; introduce upgrade consumers, or retire completed roadmap records. Public struct additions
no public complexity guarantee. and enabled-mode path interpretation need minor-release compatibility guidance
- Do not push, tag, publish, upgrade downstream dependencies, rewrite accepted during separately authorized release preparation.
ADR decisions, or remove unfinished work. Completed records retire 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 1. Add root-owned `type SourceVersionMode uint8` with consecutive constants
`path`/`glob` and `optional`. Its value is a sequence of strings. Omission `SourceVersionModeDefault` (zero), `SourceVersionModeIfPresent`, and
and `[]` mean zero additional segments. Null, a scalar (including a pointer `SourceVersionModeRequired`. Add `SourceVersionMode SourceVersionMode`
string), and any non-string member produce `CodeImportInvalid`. No coercion: to `Options[T]` and `LayeredOptions[T]`, not Definition, Input, or YAML.
quote numeric-looking keys when YAML would otherwise parse them as numbers. Mirror privately and convert explicitly. Unknown modes, or enabled modes
2. Construct a relative `Path` of literal mapping keys and reuse without a usable VersionRule and checker, produce `CodeOptionsInvalid`
`normalizeDestination`. Empty strings, dots, dot-dot, slash/tilde-containing, before source access or callbacks. Keep existing rule/path validation.
and numeric-looking strings keep their literal meaning. Existing exact 2. Add root-owned `SourceVersionCheck` with `Path Path`, `Version Version`,
`configkit` and `extends` reservations apply. Do not trim keys, split `Location *Location`, and `Redacted bool`. Add
dots/slashes, clean filesystem paths, infer sequence indices, impose a `VersionCheck *SourceVersionCheck` to SourceInfo. Nil means no enabled
collection grammar, or add syntax aliases. declaration processing occurred. A non-nil record with Present false records
3. Validate shapes/reservations in `parseImportDeclaration`, before traversal observed absence, including optional omissions whose checker was skipped; it
can suppress an optional missing target or unmatched glob. Invalid shapes does not claim a successful callback or acceptance. On a malformed selected
identify source-local `/configkit/imports/<index>/destination`; invalid value or overlap failure, retain only known presence/null, path, and location
members identify its indexed child and actual member location. Follow with conservative redaction; never expose arbitrary scalar/container content.
`nodeImportDiagnostic` conventions and keep messages value-free. Preserve Read/parse failures before this phase leave the record nil.
unknown-field, duplicate-key, path/glob, and optional rules. No new public Reuse Version's absent/null/text model.
error code/type, all-errors aggregation, or error-order guarantee is needed. 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 5. Carry the configured local rule and an effective main-owned rule separately.
immediate parent's effective destination explicitly through Enabled modes derive the latter once by prefixing main's Destination using
`walkDeclarations`. Append each declaration's relative path once and pass semantic segments. Use it consistently for remaining-payload protection,
that already computed child destination to `visitPath`. Recursive walks use inheritance/CLI checks, decoding's exact-path integer exception, and application
the child's effective destination. Remove the single metadata. Default mode uses the configured effective path unchanged. Never
`importTraversal.destination` context rather than mutating/restoring it. mutate caller rules or repeatedly prefix a path.
5. Add a small private destination-append helper in `destination.go`, unless a 6. Read each declaration from its original source document before mounting or
semantically suitable general helper already exists. Copy semantic segments consumption. Keep contextual numeric-key/index resolution, empty/escaped keys,
into owned storage without pointer-string round trips, filesystem operations, parsed tokens, and explicit indices. No mapping-only/root-only restriction;
or repeatedly extending a growing prefix with `Path.Key`. Its inputs are selecting a root mapping simply fails ordinary version-type validation.
validated mapping paths. Place each body once, not once per ancestor. 7. Missing members, unavailable indices, and obstructing non-containers mean the
6. Every glob match receives the same computed child destination. requested declaration is absent, as with current document lookup. Distinguish
`expandImportGlob` remains about physical matching. Turning a match into a causes privately for accurate nearest locations, not to invent rejection of
path declaration must not append its suffix again. Nested context must not an ancestor's domain value. If-present non-main absence skips the checker and
leak into siblings, later matches, or later inputs. records absence; required absence is `CodeVersionError` before callback.
7. Use the child destination for source records, placement, fragment-version A present unsupported selected value is `CodeVersionType`, not absence.
checks, wrapper accounting, and recursion. Keep source-record creation at its Actual main absence in if-present mode still reaches its checker once;
existing point so imports that later fail retain their effective destination. required mode rejects it first. NoSource is not a document and preserves the
`ImportedFrom` still identifies the physical path/glob declaration, not the existing single absent-main callback in both enabled modes.
destination list. Source IDs, namespaces, acquisition order, active cycles, 8. Reuse strict decimal recognition and exact Version.Text. No machine-integer
physical identity, and strict-group repetition rules remain unchanged. conversion or comparison with main. Required null reaches the checker and can
8. Remove the post-traversal assignment in `assembleBaseInputTracked` that be accepted. Warnings alone succeed and accepted non-main headers are consumed.
overwrites every imported source's destination. Set the selected entry's 9. Enabled declaration checkers and their Validation paths use the current
per-load `parsedSource.source.Destination` before import-context setup so source's local coordinates for every role, including mounted main. Resolve
early `sourceInfos` fallback copies retain entry placement. Leave correctly primary/related locations against that original source. Generated header
assigned children untouched. Preserve `315f464`'s Mapping value-error diagnostics also use source-local paths; do not rebase them to phantom payload
rebasing and root behavior; do not rebase syntax/read/directive failures. 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 11. Validate source-local controls before consumption can erase malformed
checking imported version ownership. Existing composition/history retain the directives. Reuse import/overlay validation and inheritance-control
placed source applications. Strict peers conflict, tiers recursively overlay, recognition, not per-fragment inheritance expansion. Reject actual overlap
sequences stay atomic, and sibling inheritance follows precedence. Do not add with configkit directive structure or an extends control, including headers
post-load merging or per-fragment decoding, defaults, callbacks, or headers. inside import declarations or invalid control subtrees. Unrelated siblings
10. Reuse current depth, node, source, byte, import-depth, glob-entry, projection, and ordinary keys containing those spellings remain allowed. Missing headers
and history limits. Charge each actual body's wrappers once using its full follow their mode; they do not suppress independently invalid directives.
accumulated destination, not only the suffix. Preserve raw source accounting. Add no error-order guarantee.
Placement adds no source bytes, source records, import nesting, or glob 12. Retain main's node. Remove exactly an accepted non-main mapping member or
visits beyond existing accounting. A glob declaration/ancestor walk itself sequence element in an owned payload tree. Preserve authored ancestors,
adds no payload. Omitted/empty suffixes reproduce baseline charges. newly empty mappings/sequences, sibling order, and physical node locations.
11. Malformed syntax fails even when optional input is absent. Resource charging Sequence deletion shifts later payload indices; evidence keeps original
remains tied to actual contributions: a valid optional no-match creates no coordinates. Removing a member inside a sequence element keeps that element,
source or wrappers; an actual empty body materializes its full destination. even when empty. No null placeholders, ancestor pruning, or Source mutation.
Use existing placed-body bounds and source/import diagnostics. Add no 13. Extract source-root imports from original content; consume headers in its
destination-length limit or rejection solely because an absent optional application body before placement/composition. Underlay roots and all imports
contribution's unused path would be deep. are non-main; selected overlays are also non-main. Check remaining placed
12. Preserve authored locations and source-root fallback for synthetic mappings. payload against effective main ownership. Consumption does not permit
Resource contexts remain physical and survive inheritance/overlays. forbidden overlay controls, sequence alignment, or CLI ownership bypass.
Metadata, history, sensitivity, rendering, diffs, detached records, and 14. Charge original acquired bytes/nodes once, including consumed headers. Apply
complete-on-return behavior reuse their existing mechanisms; no new existing placed-body bounds and full-destination wrapper charges to remaining
inspection API or retained loading handle is needed. payload. Keep source/depth/glob accounting, records, resource contexts, and
13. This is additive YAML functionality. Existing valid imports and Go physical repetition unchanged. Acquired header-only mappings retain their
signatures keep their contracts. Treat it as minor-release work; version empty body/ancestors and placement; NoSource/optional absent sources add no
selection, notes, retirement, and publication remain separate tasks. Do not document or evidence. No new cap or full-source clone is required.
edit published release notes.
## Stage 1 — Capture the baseline and record the extension ### Evidence and sensitivity
Status: complete. Scope: baseline evidence and one ADR; no production code. 15. Carry private evidence per acquired SourceID in per-load acquisition/assembly
state, separate from application history. Retain an owned scalar/absence,
1. Read the feature roadmap, relative-import request/acceptance rows, applicable original local and mounted semantic paths, location, and the ancestor-shape
policies, ADR 0011, and the owner map below. Confirm the worktree and baseline. context needed for classification. Capture key/index intent before deletion.
Run `./scripts/check.sh`; record revision, local Go version, results, and Retain only needed context, not entire source-tree clones or loading handles.
environmental limitations here. 16. At publication classify evidence at its original mounted path and ancestors
2. Locate existing parser, host/native import, glob, repetition, version, with existing schema tags, predicate, historical projected sensitivity,
placement-accounting, resource, history, and facade coverage. Root and inheritance, and recorded-dependency propagation. Include evidence-only
inherited placement are the compatibility baseline; header rows in the candidates in classification without adding them to Metadata paths, payload
broader request are not acceptance requirements for this plan. applications, rendering, or Diff. Do not infer original sequence shape from
3. Write `docs/adr/0012-relative-import-destinations.md` after confirming the shifted payload or round-trip through pointer strings. Reuse dependency
next unused number. Record the selected syntax and immediate-parent-relative closure rather than building a weaker independent redactor. Retained header
semantics as an Accepted extension to ADR 0011. Use the repository format. text never triggers credential lookup.
Keep implementation status in the roadmap and rejected choices only under 17. Sanitize source records before public conversion; early records remain
Alternatives Considered. Focus on ConfigKit, without downstream semantics. conservatively redacted. Final successful evidence uses completed sensitivity,
4. Note the extension in ADR 0011's status/navigation if needed; preserve its retaining historical classification despite replacement. Main's normal
accepted decision text. Record the additive minor-release assessment without payload/history remains intact. Consumed non-main headers are only source
selecting a version or adding release gates. evidence: equal payloads with different headers must not acquire effective
differences merely from that evidence.
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.
## Implementation owner map ## Implementation owner map
Use graph discovery to confirm current symbols and locations before editing: | Responsibility | Existing owners to inspect and extend |
- `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 |
| --- | --- | | --- | --- |
| 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` | | Public options, callbacks, records, conversions | `lifecycle.go`, `layered.go`, `records.go`, `conversion.go`, `diagnostic.go` |
| 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` | | Options and per-load coordination | `internal/engine/options.go`, `load.go`, `load_request.go`, `layered.go` |
| 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` | | Acquisition, directives, placement, overlay | `internal/engine/load_input.go`, `imports.go`, `directives.go`, `destination.go`, `selected_overlay.go` |
| 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` | | Checking and semantic paths | `internal/engine/validation.go`, `document_walk.go`, `version_path_test.go` |
| Host/native source records, direct and inherited resources, physical resource bases, and detached destinations | `TestFacadeRelativeImportDestinationsForRootAndMountedLoads`, `TestFacadeRelativeImportDestinationsPreserveNativeResourceContexts`, `TestLayeredImportedInheritedValuesRetainResourceContexts`, and existing source-equivalence/resource-context suites | | Evidence copies, errors, publication | `internal/engine/records.go`, `diagnostic.go`, `load_result.go` |
| 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 | | Classification and propagation | `internal/engine/secret.go`, schema secret-path helpers, `secret_propagation_test.go`, `render_test.go` |
| 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` | | 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` |
| 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` |
The public acceptance rows about file/reader/mapping sources reuse Private helper names/file splits may follow the implementation while preserving
`facade_equivalence_test.go`, `TestFacadeInputDestinationsAcrossSourceKinds`, these decisions. A new internal package solely for headers is unnecessary.
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.
## Open Questions ## Validation commands
None required for this feature. Selected list syntax and existing placement Use the applicable subset during each stage; add new tests under the
contracts resolve the public choices; this plan settles context, diagnostic, SourceVersion name family so focused checks include them. Existing test owners
and accounting details within them. Report a newly discovered incompatibility remain authoritative. Commands run from the repository root with dependencies
with evidence and alternatives rather than adding a restriction or implementing already available; these are development checks, not new release gates.
the separate source-header proposal.
```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 # Shared Source Version Checks Roadmap
Status: design decisions settled; implementation has not started. Execute the Status: design decisions settled; implementation has not started. The
stages below in order. This roadmap develops the partially accepted source-version request in [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) [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 using the consumer's single `Definition.Version` policy. The design direction
below incorporates the maintainer's subsequent decisions on lookup, consumption, 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. 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 The consumer selects a load-wide enum on ordinary and layered options. Its zero
value retains current behavior; exact exported names remain implementation design value retains current behavior; the implementation plan selects exported names.
work. The same `Definition.Version` can be reused across loads with different The same `Definition.Version` can be reused across loads with different
strictness. The three modes are: strictness. The three modes are:
| Mode | Missing non-main declaration | Present non-main declaration | | 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 dedicated checked-version evidence. Existing sensitivity and inspection are
primarily organized around application paths and retained application trees. 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 - One checker can accept several distinct source declarations. Rejected acquired
API, participation, main-path, inspection, and edge-case decisions. Define header declarations fail the load even when later tiers would replace their payload.
lookup for nested paths and distinguish a missing member from an obstructing - Absence, explicit null, strings, exact decimal integers, and malformed selected
non-container ancestor. Specify consumption without broadening it into a generic transformation values follow the shared version vocabulary and selected mode.
API. Preserve authored ancestors when consuming nested mapping headers as agreed; - Main retains its own declaration and is checked once; mounted main uses the
apply the agreed sequence-element removal and structural-overlap rejection rules. 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 Independent specification policies, release preparation, and publication are
compatibility under repository policy. Do not rewrite accepted ADR decisions or outside this feature's completion criteria.
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.
## Agreed Edge-Case Decisions ## Agreed Edge-Case Decisions
The maintainer has accepted all three decisions below. Together with the mode The maintainer has accepted all three decisions below. Together with the mode
API location, source participation, main-path handling, source-record evidence, API location, source participation, main-path handling, source-record evidence,
and nested mapping ancestor preservation above, these settle the discussed and nested mapping ancestor preservation above, these settle the discussed
product decisions. Exact public names and internal mechanics remain implementation product decisions. The [implementation plan](implementation.md) selects public
work; the feature is not yet implemented. names and integration mechanics; the feature is not yet implemented.
### Sensitivity of consumed declaration evidence ### Sensitivity of consumed declaration evidence