From d9f08ff7198ad5a8fb5c49a43e7ccdad2ad0e707 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Thu, 15 Oct 2026 14:05:25 +0000 Subject: [PATCH] Settle source version edge-case decisions --- docs/roadmap/source-version-checks.md | 74 ++++++++++----------------- 1 file changed, 27 insertions(+), 47 deletions(-) diff --git a/docs/roadmap/source-version-checks.md b/docs/roadmap/source-version-checks.md index 5ed7507..76ebb25 100644 --- a/docs/roadmap/source-version-checks.md +++ b/docs/roadmap/source-version-checks.md @@ -1,7 +1,7 @@ # Shared Source Version Checks Roadmap -Status: planned; 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. Execute the +stages below in order. 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, @@ -83,8 +83,8 @@ Preserve normal safe diagnostics, warning behavior, callback lifetime, and disclosure rules. Evidence will be attached to existing source inspection as a detached declaration record, distinguishing unchecked sources, checked absence, present null/text, and redaction, with local path and physical location. The -remaining sensitivity decision below governs disclosure; retaining evidence does not authorize -unredacted exposure of sensitive values or arbitrary malformed input. +agreed sensitivity rules below govern disclosure; retaining evidence does not +authorize unredacted exposure of sensitive values or arbitrary malformed input. ### Participation and unchanged boundaries @@ -135,7 +135,7 @@ root-only main restriction is introduced. For nested mapping headers, consume only the selected non-main declaration and retain authored ancestor containers, including newly empty mappings. This avoids removing additional input presence or changing unrelated default/composition -behavior. Sequence-element and structural-directive cases remain open below. +behavior. Sequence-element and structural-directive behavior is settled below. ## Current baseline @@ -168,13 +168,12 @@ destinations are implemented; the ### 1. Finalize the contract and integration design -Resolve the Open Decisions below. Select exact public mode and evidence type -names within the agreed load-wide API, participation, main-path, and inspection -design. 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 +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; -settle sequence-element consumption and structural-directive overlaps below. +apply the agreed sequence-element removal and structural-overlap rejection rules. 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 @@ -240,12 +239,15 @@ existing import and composition tests: - 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, empty containers, structural-path interactions, - and remaining payload protection; +- 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; +- 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. @@ -267,16 +269,17 @@ 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. -## Open Decisions +## Agreed Edge-Case Decisions -These are recommendations for further discussion, not accepted restrictions or -implemented behavior. The mode API location, source participation, main-path -handling, source-record evidence, and nested mapping ancestor preservation above -have been agreed. +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. ### Sensitivity of consumed declaration evidence -Recommendation: classify declaration evidence using its original source shape +Classify declaration evidence using its original source shape at its mounted application path, including classified ancestors. Preserve the header as private evidence long enough to apply applicable existing field-tag, predicate, historical, and recorded-dependency sensitivity rules; consumption @@ -298,16 +301,9 @@ load errors before full sensitivity is available, mask its text unless applicabl classification can already be established safely; this does not require a new failed-load evidence API or continuing a failed load to finish classification. -Alternative: always redact declaration text in public source evidence. This -simplifies classification and prevents disclosure, but hides ordinary version -identifiers that the consumer explicitly wants to inspect. Conversely, treating -headers as inherently public would be simpler but would bypass existing -classification where the configured header path or its ancestor is sensitive. -Prefer normal classification rather than either blanket rule. - ### Headers that are sequence elements -Recommendation: support consumption of a selected sequence element by deleting +Support consumption of a selected sequence element by deleting that element, retaining the sequence and its order among remaining elements. Later indexes shift in the remaining payload; an emptied sequence remains `[]`. This is ordinary removal, not a merge strategy. Retain the header's original @@ -321,35 +317,19 @@ path forms. Verify protected-path and typed behavior where main retains an eleme but non-main payloads have shifted indexes; do not invent alignment or bypass normal sequence replacement, decoding, or ownership rules to make such inputs fit. -Alternative: reject headers whose selected node is a sequence element in enabled -modes, while permitting mapping-member headers nested inside sequences. This -avoids index shifts and may be easier for consumers to reason about, but narrows -supported header locations and is not required for correctness if deletion is -specified. Replacing the element with null would preserve indexes but fabricate a -payload value and could change decoding; it is not the recommended interpretation -of consumption. - ### Overlap with structural directives -Recommendation: reject an actual overlap between a checked header and an existing +Reject an actual overlap between a checked header and an existing structural directive node with a structured error in enabled modes. A value must not simultaneously serve as a consumed specification declaration and as import or inheritance control. Include a header selected inside an import declaration or at an `extends` control; preserve ordinary structural validation so malformed controls cannot disappear through consumption. Use source-local paths and real -locations for these errors. This is a proposed semantic restriction to approve, -not an existing general prohibition on nested header paths. +locations for these errors. This is an explicitly accepted, narrow restriction +for enabled source checks, not a general prohibition on nested header paths. Limit the rule to structural overlap, not substrings in ordinary keys. A header at `metadata.version` is not blocked merely because its source also contains `configkit.imports`, and a key such as `extends_version` is not an `extends` control. Missing headers remain governed by the selected mode; existing invalid directives still fail independently. - -Alternative: interpret structural directives first, then allow the same node to -serve as a checked and consumed header. This can be defined and avoids a new -path restriction, but gives one value two unrelated roles: for example, an -accepted version string could also name an import file or inheritance parent. -It also needs extra ordering and retained-control rules to keep consumption from -canceling behavior. Prefer an explicit overlap error over that dual interpretation; -there is no identified consumer need for sharing these roles.