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