diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 4469719..9523d61 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -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//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. diff --git a/docs/roadmap/source-version-checks.md b/docs/roadmap/source-version-checks.md index 76ebb25..03987ac 100644 --- a/docs/roadmap/source-version-checks.md +++ b/docs/roadmap/source-version-checks.md @@ -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