Plan relative import destination implementation
This commit is contained in:
@@ -1,580 +1,394 @@
|
||||
# Implement configuration input destinations
|
||||
# Implement relative import destinations
|
||||
|
||||
Status: complete. Stages 1–12 are implemented and audited. The
|
||||
[feature roadmap](input-destinations.md) owns the approved behavior and rationale; the
|
||||
[consumer request](promptkit-feature-request.md#public-acceptance-scenarios)
|
||||
supplies the public acceptance scenarios. This document owns execution and
|
||||
completion evidence. Planning baseline: `6353598`.
|
||||
Status: planned. Execute Stage 1 through Stage 9 in order, one focused stage per
|
||||
Luna implementation prompt. The
|
||||
[feature roadmap](relative-import-destinations.md) owns the approved target and
|
||||
syntax; this document owns implementation decisions, sequencing, and evidence.
|
||||
|
||||
Planning baseline: `b2db323`, including input-destination remediation at
|
||||
`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.
|
||||
|
||||
## Working instructions
|
||||
|
||||
- Start each stage with `AGENTS.md`, [development.md](../development.md), the
|
||||
applicable policies, and working-tree inspection. Use graph-first code
|
||||
discovery. Preserve unrelated changes and previously completed stages.
|
||||
- Implement only that stage and its supporting tests/documentation. Mark it
|
||||
complete here with actual commands and evidence, then commit the nonempty
|
||||
validated unit with a short plain-English message. Subsequent stages remain
|
||||
planned. A stage is not complete solely because its narrow tests pass.
|
||||
- Keep early mechanics private until the complete engine behavior is ready.
|
||||
Root destination fields land in Stage 10. Ordinary root loading must remain
|
||||
working throughout. Do not publish a partially supported public placement API.
|
||||
- Follow the existing engine/document/YAML boundaries. Reuse strict composition,
|
||||
recursive overlay, sibling inheritance, paths, history, and sensitivity.
|
||||
No dependencies, toolchain changes, alternate mergers, mount registry,
|
||||
per-fragment lifecycle, import-destination syntax, resource discovery, or new
|
||||
release gates are needed. These are scope boundaries, not new prohibitions
|
||||
on separately approved future work.
|
||||
- Update current-behavior documentation when public behavior lands; keep future
|
||||
claims here or in the roadmap until then. Add the ADR in Stage 1 under the
|
||||
documentation policy's accepted-decision exception.
|
||||
- Use focused offline tests while iterating; run `./scripts/check.sh` before
|
||||
committing production changes. Documentation-only stages need whitespace and
|
||||
local-link checks. Stage 12 adds full ownership/race validation. Tests protect
|
||||
observable behavior, not wrapper allocation or helper-call counts. Reuse
|
||||
coverage rather than repeat an entire loading matrix at every layer.
|
||||
- No benchmark campaign or public complexity guarantee is required. Prefer
|
||||
straightforward bounded walks and wrapping each acquired contribution once;
|
||||
avoid rescanning all preceding contributions for every new input.
|
||||
- Do not push, tag, publish, update downstream dependencies, or retire unfinished
|
||||
records. Release compatibility review is separate from publication.
|
||||
- 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.
|
||||
|
||||
## Resolved implementation decisions
|
||||
|
||||
1. Add root-owned `Input.Destination Path` and `SourceInfo.Destination Path`,
|
||||
mirrored privately in engine input/source records. Extend `loadInput` and
|
||||
explicit root/engine conversion and cloning. No new loading entry point,
|
||||
public wrapper type, option, or origin field is needed. Ordinary `Load`
|
||||
continues to supply root placement.
|
||||
2. The zero path means root. Validate `Path.valid()` and reject every explicit
|
||||
index segment, including a negative index. Normalize parsed tokens to literal
|
||||
mapping-key segments: `/0` means the key `0`, not sequence element zero.
|
||||
Empty, dot, dot-dot, slash-containing, tilde-containing, and numeric keys keep
|
||||
existing semantic-path meaning. Do not split dots, interpret filesystem
|
||||
traversal, enforce identifier grammar, or add namespace uniqueness.
|
||||
3. Reject destination segments equal to `configkit` or `extends`: placement
|
||||
would introduce a reserved mapping key with a mapping value. Substrings such
|
||||
as `myextends` are ordinary keys. This preserves the approved structural
|
||||
rules rather than adding an application naming policy. Source-root import
|
||||
directives are still processed before placement.
|
||||
4. Validate destination shape/reservations for all declared inputs during
|
||||
grouped option preflight, before reading any source. Reuse
|
||||
`CodeOptionsInvalid` for invalid destination declarations; include the
|
||||
offending semantic path when representable, with no fabricated physical
|
||||
location. An invalid source still follows existing source-option validation.
|
||||
A valid destination on `NoSource` contributes no nodes, source record, or
|
||||
budget charges. No extra error type or exact message contract is introduced.
|
||||
5. Separate acquired source syntax from application placement. Retain original
|
||||
parsed source metadata for filesystem/directive handling. Strip source-root
|
||||
directives, then wrap each application body at the normalized destination
|
||||
before fragment version checks and strict composition. Imports inherit the
|
||||
same destination transitively. Do not wrap both a source application and its
|
||||
recomposed result; every retained application must already use effective
|
||||
coordinates. Content roots remain mappings under existing source contracts.
|
||||
6. Wrapping a body at `Keys("a", "b")` creates `{a: {b: body}}` as private
|
||||
document mappings. Actual body nodes and entries keep their physical source
|
||||
coordinates. Introduced mappings/entries use the contributing document's root
|
||||
location as a documented source fallback, not purported authored coordinates.
|
||||
They have the same contributing source ID and create no synthetic source.
|
||||
Retained history trees remain immutable and separate from assembly mutation.
|
||||
7. A present empty body creates explicit destination mappings, including an
|
||||
import-only source whose application body is empty. It still cannot clear
|
||||
lower mappings. A missing optional import and `NoSource` remain absent. Empty
|
||||
source text remains the existing invalid document, not an empty mapping.
|
||||
8. `VersionRule.Path` stays an effective application path. Check main once after
|
||||
its own imports compose and before underlays/overlay/CLI, at the existing
|
||||
phase. Imported and underlay claims are checked against placed application
|
||||
content, including scalar/null/sequence ancestors replacing a protected path.
|
||||
A mapping ancestor with no protected descendant is not a version claim.
|
||||
Mounted domain `version` fields are ordinary data. Existing inheritance,
|
||||
selected-overlay, CLI protection and exact-path numeric conversion remain;
|
||||
no nested blanket conversion or additional fragment checker is introduced.
|
||||
9. Placement does not alter physical source identity, filesystem namespace,
|
||||
source IDs, acquisition order, imported-from locations, or resource contexts.
|
||||
Repeated physical sources in one strict group still fail even at different
|
||||
destinations. The same physical source in separate tiers retains the existing
|
||||
independent source applications/records and each record's own destination.
|
||||
Overlay and CLI source records have root `Destination`; they are not mounted
|
||||
merely because main is mounted. Active layered overlays retain their explicit
|
||||
independent filesystem selection and application-root meaning.
|
||||
10. Value-level paths use effective coordinates. Keep genuine source-local
|
||||
import-directive diagnostics and parse/read failures at their original
|
||||
locations; do not invent a logical child path when parsing cannot identify
|
||||
one. Prefix existing application-relative diagnostic paths exactly once
|
||||
where available. Preserve structured codes, related physical locations,
|
||||
deterministic ordering, and value-free messages.
|
||||
11. Use current depth/node limits, not a new destination cap. With root depth
|
||||
zero, each destination segment adds one level and, under `countInputNodes`,
|
||||
one mapping node plus one key. Retain current raw input accounting (including
|
||||
directives); charge only the additional `2 * segmentCount` synthetic nodes
|
||||
per acquired body, once, to the shared input budget. Placement adds no bytes,
|
||||
acquired sources, import nesting, or glob visits. Validate placed application
|
||||
depth and per-document node bounds before composition; share accounting
|
||||
across inputs and imports. Precheck wrapper depth/count before allocating
|
||||
wrappers. Use existing source/import limit diagnostics in their acquisition
|
||||
contexts; retain projection, expansion, and history bounds independently.
|
||||
Root placement adds no charge or new rejection. NoSource adds none either.
|
||||
12. Cloned source records include independently owned destination paths at every
|
||||
existing publication boundary: results, load errors, metadata/inspection,
|
||||
callback input information, and root conversion. Passive resource contexts
|
||||
remain keyed by the real source identity; inspection must work without an
|
||||
open configuration handle after load. This does not extend caller-owned
|
||||
filesystem or callback resource lifetimes.
|
||||
### Syntax and validation
|
||||
|
||||
## Stage 1 — Record the decision and capture the baseline
|
||||
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.
|
||||
|
||||
Status: complete. Scope: decision record and evidence, no feature code.
|
||||
### Traversal and source records
|
||||
|
||||
1. Read the roadmap, request, relevant policies, and ADRs 0001, 0003, 0006,
|
||||
0008, and 0009. Inspect the owners identified in the roadmap and the function
|
||||
map below. Confirm the baseline and worktree before starting.
|
||||
2. Run `./scripts/check.sh`; record the commit, Go version, and results here.
|
||||
Locate existing coverage for root loading, strict underlays, version ownership,
|
||||
repeated sources, history, resource contexts, and detached records.
|
||||
3. Write `docs/adr/0011-input-destinations.md` after confirming the number is
|
||||
unused. Record the approved input-placement decision as Accepted, with the
|
||||
roadmap owning implementation status. Follow the repository ADR format.
|
||||
Focus on ConfigKit, put rejected options only in Alternatives Considered,
|
||||
and avoid negative parallelism elsewhere. No PromptKit-specific semantics.
|
||||
4. Record the compatibility assessment under the release policy: adding fields
|
||||
preserves zero-value/keyed-literal use, but callers using unkeyed literals
|
||||
for `Input` or `SourceInfo` must migrate to keyed literals. Treat the feature
|
||||
as minor-release work; select a version and write its note only during
|
||||
separately authorized release preparation.
|
||||
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.
|
||||
|
||||
Validated: `./scripts/check.sh` (go1.26.8 linux/amd64) passed on candidate
|
||||
`d3d468a8b47d780787fca329ff65b107d98ca59f`; this includes formatting,
|
||||
whitespace, local documentation links, tests, vet, and build. The planning
|
||||
baseline `6353598bd6cce2eb78a5fe990e144cc0cadf1280` is present in history. The
|
||||
worktree was clean before this stage.
|
||||
### Assembly, limits, and compatibility
|
||||
|
||||
Coverage located for later destination work:
|
||||
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.
|
||||
|
||||
- Root and equivalent source loading: `TestEquivalentSourceFormsPreserveInputSemantics`
|
||||
(`facade_equivalence_test.go`) and
|
||||
`TestFacadeLayeredZeroUnderlaysMatchesOrdinaryLoad` (`facade_layered_test.go`).
|
||||
- Strict underlays and group budgets: `TestGroupedLoadStrictConflictsRepetitionAndBudgets`
|
||||
and `TestGroupedLoadPrecedenceSourceOrderAndSingleLifecycle`
|
||||
(`internal/engine/load_request_test.go`).
|
||||
- Version ownership and imported claims: `TestLoadRejectsImportConflictsAndFragmentVersions`
|
||||
(`internal/engine/imports_test.go`) and version-path coverage in
|
||||
`internal/engine/load_test.go`.
|
||||
- Repeated physical sources: `TestRepeatedImportsAcrossTiersAndReaderConsumption`
|
||||
(`facade_equivalence_test.go`).
|
||||
- History and source contexts: `TestUnderlayHistoryRetainsLaterMappingContributors`
|
||||
(`facade_underlay_origins_test.go`) and
|
||||
`TestFacadeSourceContextsFollowOriginsWithoutQueryIO`
|
||||
(`facade_resource_context_test.go`).
|
||||
- Detached records: `TestLoadMetadataReflectsDefaultsInputAndDetachedRecords`
|
||||
(`internal/engine/load_test.go`) and
|
||||
`TestMetadataQueriesReturnDetachedRecords` (`internal/engine/metadata_test.go`).
|
||||
## Stage 1 — Capture the baseline and record the extension
|
||||
|
||||
The decision is recorded in [ADR 0011](../adr/0011-input-destinations.md).
|
||||
Compatibility assessment: adding the two public fields breaks callers using
|
||||
unkeyed literals for `Input` or `SourceInfo`; keyed and zero-value use remains
|
||||
compatible. The release policy permits the intentional pre-1.0 contract change
|
||||
in a minor release when the release note states impact and migration. Version
|
||||
selection and release-note preparation remain out of scope until separately
|
||||
authorized. No feature code or current behavior contract changed.
|
||||
Status: planned. Scope: baseline evidence and one ADR; no production code.
|
||||
|
||||
## Stage 2 — Add private destination normalization and wrapping
|
||||
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.
|
||||
|
||||
Status: complete. Scope: pure private mechanics with bounded unit tests.
|
||||
Validate: whitespace and local-documentation-link checks. Done: baseline and
|
||||
decision are recorded; implemented behavior is unchanged.
|
||||
|
||||
1. Add a small engine helper file for normalized mapping-only destinations and
|
||||
constructing placed document bodies. Follow decisions 2–7; keep helpers
|
||||
private and avoid introducing a second path abstraction.
|
||||
2. Validate invalid paths, explicit indices, and exact reserved tokens. Normalize
|
||||
parsed numeric tokens into keys, preserving literal text and pointer escaping.
|
||||
3. Build wrappers without mutating the supplied tree. Preserve body locations;
|
||||
give introduced entries/mappings the source-root fallback. Implement depth and
|
||||
node measurement/prechecks usable with existing limits, including the extra
|
||||
synthetic-node count; aggregate charging is wired in Stage 7.
|
||||
4. Cover root identity/equivalence, nested empty mapping, literal/escaped/numeric
|
||||
keys, invalid index/path, exact versus substring reserved keys, owned paths,
|
||||
unchanged body coordinates, and bounded wrapper checks. Do not count helper
|
||||
invocations or fix an allocation strategy in tests.
|
||||
## Stage 2 — Refactor traversal to explicit per-document placement
|
||||
|
||||
Validated with `go test ./internal/engine -run 'Destination|PlaceDocument'`
|
||||
and `./scripts/check.sh` (go1.26.8 linux/amd64); both passed. The private
|
||||
helpers normalize mapping-only destinations, preserve authored nodes and source
|
||||
coordinates, and check per-document depth/node bounds before allocating wrappers.
|
||||
No loader accepts a new public field yet.
|
||||
Status: planned. Scope: private context plumbing; old syntax remains unchanged.
|
||||
|
||||
## Stage 3 — Integrate private non-import input placement
|
||||
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.
|
||||
|
||||
Status: complete. Scope: engine request plumbing and ordinary acquired bodies.
|
||||
Validate: `go test ./internal/engine -run 'Import|Glob|Destination|Grouped'`,
|
||||
`go test . -run 'Destination|FacadeLayered'`, 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.
|
||||
|
||||
1. Add destination fields to engine `Input`, `loadInput`, and `SourceInfo`.
|
||||
Preserve ownership through engine `LoadLayered` request construction,
|
||||
`cloneSourceInfo`, and source-record copies. Keep the root facade unchanged.
|
||||
2. Extend grouped preflight to validate/normalize destinations before source
|
||||
reads. Use the existing diagnostic accumulator and options-invalid category.
|
||||
Ordinary `Load` supplies root placement through its existing request adapter.
|
||||
3. Thread placement into `assembleBaseInputTracked` without confusing raw
|
||||
`parsedSource` with effective `assembledInput.document`. Preserve the root
|
||||
path through existing wrappers/callers. For imports-disabled acquisition,
|
||||
validate disabled directives on raw content, place the body, and retain the
|
||||
destination on the acquired source record. NoSource still short-circuits.
|
||||
4. Use engine loads to cover mounted main and underlay bodies, omitted versus
|
||||
explicit root destinations, empty mapping versus NoSource, and preflight
|
||||
rejection without consuming a test-owned reader. Reuse current source-kind
|
||||
acquisition tests; full source equivalence is verified publicly in Stage 10.
|
||||
## Stage 3 — Accept and document the selected YAML syntax
|
||||
|
||||
Validated with `go test ./internal/engine -run 'Destination|PlaceDocument|Grouped'`
|
||||
and `./scripts/check.sh` (go1.26.8 linux/amd64); both passed. Private non-import
|
||||
placement reaches assembly, with root behavior unchanged. Imports are the next
|
||||
private integration step.
|
||||
Status: planned. Scope: directive parsing and first complete public behavior.
|
||||
|
||||
## Stage 4 — Carry placement through import acquisition
|
||||
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.
|
||||
|
||||
Status: complete. Scope: source-local directives and placed imported applications.
|
||||
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.
|
||||
|
||||
1. Thread a normalized destination through `loadImportedDocumentsTracked`,
|
||||
`loadImportedWithAccessTracked`, and `importTraversal`, retaining root defaults
|
||||
for current private callers. Place the selected body's application content
|
||||
after `splitImportDirectives`; do the same for every imported body.
|
||||
2. Set placement on selected/imported source records, including error records
|
||||
once a source has been acquired. Keep `ImportedFrom` at the physical directive.
|
||||
Run imported `fragmentVersionClaim` against placed bodies and retain placed
|
||||
bodies in `state.documents` before `composeDocuments` builds applications.
|
||||
3. Leave filesystem joins, containment, glob traversal, optional missing inputs,
|
||||
active cycles, visited identities, and acquisition IDs/order unchanged.
|
||||
Destination must not become part of the repeated-source identity key.
|
||||
4. Test native and host transitive imports, nested source-root directives,
|
||||
import-only bodies, and mounted imported protected versus ordinary version
|
||||
paths. Verify a repeated file at two destinations in one group still fails,
|
||||
including an import/direct-input alias. Reuse cycle/containment regressions.
|
||||
## Stage 4 — Verify composition and effective version ownership
|
||||
|
||||
Validated with `go test ./internal/engine -run 'Destination|PlaceDocument|Import|Grouped'`
|
||||
and `./scripts/check.sh` (go1.26.8 linux/amd64); both passed. Retained imported
|
||||
contributions have effective placement and physical source identity, with no
|
||||
double wrapping or application-level directive leakage.
|
||||
Status: planned. Scope: assembly interactions; reuse existing algorithms.
|
||||
|
||||
## Stage 5 — Complete strict tiers and main version ownership
|
||||
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.
|
||||
|
||||
Status: complete. Scope: assembly and version interactions, not a new merger.
|
||||
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.
|
||||
|
||||
1. Review `acquireUnderlayGroup`: version checks must use placed content, and
|
||||
documents taken from `acquired.composition.applications` must already be
|
||||
placed. Recompose strict peers with ordinary `composeDocuments`; preserve
|
||||
per-source applications, origins, UnderlayIndex, and input accounting.
|
||||
2. In `executeLoadRequest`, main's version check uses its placed main/import
|
||||
composition at the existing point. `assembleLayeredInput` recursively overlays
|
||||
completed underlay groups beneath main, selected overlay, and CLI as before.
|
||||
Do not mount the final assembly or prepend main's destination to upper tiers.
|
||||
3. Test disjoint same-destination peers, different destinations, equal and unequal
|
||||
conflicts, ancestor/descendant destinations, and a strict conflict despite an
|
||||
upper override. Verify recursive mapping overlays, atomic sequences, null,
|
||||
explicit false/zero, and version-only domain overrides retaining lower fields.
|
||||
4. Exercise mounted main with a nested VersionRule, absent root declarations,
|
||||
imported/underlay direct and ancestor claims, and nonclaiming mapping ancestors.
|
||||
Check the hook runs once and does not inspect each fragment independently.
|
||||
Preserve exact configured-path integer conversion and ordinary nested typing.
|
||||
## Stage 5 — Verify accumulated resource accounting
|
||||
|
||||
Validate: destination/composition/overlay/version/grouped tests and everyday
|
||||
check. Validated with `go test ./internal/engine -run 'LayeredDestination'`,
|
||||
`go test ./internal/engine -run 'Destination|Composition|Overlay|Version|Grouped'`,
|
||||
and `./scripts/check.sh` (go1.26.8 linux/amd64); all passed. The new mounted
|
||||
cases verify strict same-tier conflicts and disjoint composition, independent
|
||||
destinations and nested paths, recursive/atomic overlay behavior, explicit
|
||||
null/false/zero, and main-only nested version checking after imports compose.
|
||||
Done: placed and authored equivalents agree on values and conflicts; main
|
||||
ownership and lifecycle timing are preserved.
|
||||
Status: planned. Scope: limit regressions and any necessary narrow correction.
|
||||
|
||||
## Stage 6 — Reconcile diagnostic coordinate systems
|
||||
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.
|
||||
|
||||
Status: complete. Scope: useful paths without fictional source locations.
|
||||
Validate: focused import/destination/limit/override tests and everyday check.
|
||||
Done: accumulation cannot bypass current bounds or falsely charge absent input.
|
||||
|
||||
1. Audit early acquisition, import, fragment-version, and composition failures.
|
||||
Use one narrow path-prefix translation where diagnostics genuinely identify
|
||||
application content; do not blanket-prefix every diagnostic or double-prefix
|
||||
diagnostics already produced by placed trees.
|
||||
2. Preserve syntax/read/directive locations and related import sites. Value
|
||||
conflicts and later typed/resolver/validation failures use effective paths
|
||||
but original content coordinates. Invalid introduced structure identifies
|
||||
the destination declaration rather than a nonexistent source wrapper line.
|
||||
3. Add focused assertions for a mounted conflict with two real sources, a mounted
|
||||
decode or validation error, an imported version error, invalid destination,
|
||||
and malformed source-local directives. Test stable codes/paths/locations and
|
||||
nil results, not whole messages or callback choreography.
|
||||
## Stage 6 — Preserve diagnostics, source inspection, and resource contexts
|
||||
|
||||
Validate: destination/diagnostic/import/version/decode tests and everyday check.
|
||||
Validated with `go test ./internal/engine -run 'LayeredDestinationDiagnostics'`,
|
||||
`go test ./internal/engine -run 'Destination|Diagnostic|Import|Version|Decode'`,
|
||||
and `./scripts/check.sh` (go1.26.8 linux/amd64); all passed. The mounted
|
||||
conflict, decode, and imported-version assertions use effective application
|
||||
paths with authored source locations; invalid destinations have no physical
|
||||
location; malformed source-root directives retain their authored path and
|
||||
location. Later value diagnostics are produced from placed trees, while directive
|
||||
diagnostics retain their raw source coordinates. Post-review remediation also
|
||||
rebases known Mapping value-builder failure paths, which are produced before
|
||||
placement. `TestFacadeDestinationMappingFailurePaths` covers mounted main and
|
||||
underlay failures, escaped keys and sequence-index intent, cycles, unchanged
|
||||
root paths, and unchanged source-constructor failures. Its mounted value cases
|
||||
failed before the fix and pass afterward.
|
||||
Done: diagnostics consistently distinguish application paths from source syntax.
|
||||
Status: planned. Scope: coordinates, detached records, and resource ownership.
|
||||
|
||||
## Stage 7 — Complete shared placement accounting
|
||||
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.
|
||||
|
||||
Status: complete. Scope: resource bounds with no new public limit system.
|
||||
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.
|
||||
|
||||
1. Wire Stage 2's prechecks and synthetic-node charges into both tracked ordinary
|
||||
acquisition and import traversal, using `importAccounting` and current limit
|
||||
structures. Charge each source body once, including empty import bodies.
|
||||
2. Preserve existing raw byte/source/node accounting and imported directive
|
||||
inspection. Additional wrappers count in per-body depth/node checks and
|
||||
shared aggregate nodes; recomposition must not charge them again. Ensure
|
||||
selected overlays and CLI start from totals including placement charges.
|
||||
3. Test below/at/above relevant bounds using small private limit fixtures where
|
||||
existing seams permit; add a narrow private seam if necessary. Cover deep
|
||||
body plus destination, many shallow mounted inputs, imported wrappers, and
|
||||
empty mappings. Verify root placement and NoSource do not add charges.
|
||||
Preserve history/expansion limits; do not turn fixture values into defaults.
|
||||
## Stage 7 — Verify inheritance, history, sensitivity, and diffs
|
||||
|
||||
Validated with `go test ./internal/engine -run 'Destination|Import|Grouped|Overlay|Override'`
|
||||
and `./scripts/check.sh` (go1.26.8 linux/amd64); both passed. New coverage in
|
||||
`TestDestinationPlacementCountsAgainstSharedNodeBudget`,
|
||||
`TestMultipleMountedInputsSharePlacementCharges`,
|
||||
`TestImportedEmptyBodiesChargeEachDestinationWrapper`,
|
||||
`TestSelectedOverlayAndCLIUsePlacementNodeCharges`, and
|
||||
`TestNoSourceAndRootPlacementAddNoWrapperCharges` checks totals below, at, and
|
||||
above the boundary, multiple shallow inputs, imported empty bodies, and charging
|
||||
of upper tiers from mounted inputs. `TestPlaceDocumentRootAndBounds` continues
|
||||
to cover per-document depth/node boundaries; existing grouped accounting tests
|
||||
cover unchanged raw source/byte charging. Done: placement cannot bypass current
|
||||
budgets and introduces no unrelated caps.
|
||||
Status: planned. Scope: retained placed data and one final application lifecycle.
|
||||
|
||||
## Stage 8 — Preserve provenance, history, and source resource contexts
|
||||
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.
|
||||
|
||||
Status: complete. Scope: engine inspection and retained evidence.
|
||||
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.
|
||||
|
||||
1. Audit `compositionOrigins`, `completeCompositionOrigins`, application replay,
|
||||
metadata construction/finalization, and source-record cloning against placed
|
||||
applications. Prefer feeding placed trees into existing processing rather
|
||||
than adding another path-offset index or rewriting final metadata afterward.
|
||||
2. Verify explicit destination containers, actual leaves, composite origins,
|
||||
superseded/removed descendants, and root/source fallbacks. Historical and
|
||||
effective indexes keep independently owned paths and existing shape semantics.
|
||||
3. Preserve source-ID resource contexts through imports, surviving lower-tier
|
||||
values, and inheritance. Test completed-result and resolution-time context
|
||||
queries against real relative files, without making ConfigKit open the
|
||||
referenced application resource or retain loading handles.
|
||||
4. Exercise the same physical source in separate tiers with different placement,
|
||||
inspect each source record, and verify independent destination paths. Repeat
|
||||
inspection after comparison and independent loads to detect retained mutation.
|
||||
## Stage 8 — Demonstrate ordinary and mounted collection entries
|
||||
|
||||
Validated with `go test ./internal/engine -run 'Destination|Metadata|Provenance|History|Resource|SourceContext'`,
|
||||
`go test -race ./internal/engine`, and `./scripts/check.sh` (go1.26.8
|
||||
linux/amd64); all passed. `TestLayeredDestinationsRetainOriginsHistoryAndDetachedRecords`
|
||||
checks synthetic-container fallback locations, authored leaf coordinates,
|
||||
composite origins, removed-descendant history, and the same host file retained
|
||||
at distinct destinations in separate tiers before and after comparison and an
|
||||
independent load. `TestLayeredImportedInheritedValuesRetainResourceContexts`
|
||||
uses real temporary files to verify resolution-time and completed-result
|
||||
relative-resource lookup through an imported surviving parent and its inherited
|
||||
child. Existing metadata and resource-context tests continue to cover detached
|
||||
records and loading-handle closure. Done: inspection explains effective
|
||||
placement and physical origin without consumer reconstruction.
|
||||
Status: planned. Scope: maintained public examples and their behavior tests.
|
||||
|
||||
## Stage 9 — Verify final inheritance, sensitivity, and lifecycle integration
|
||||
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.
|
||||
|
||||
Status: complete. Scope: complete private engine behavior before facade exposure.
|
||||
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.
|
||||
|
||||
1. Resolve sibling inheritance only after full source precedence using the
|
||||
existing expansion path. Cover a child and parent supplied by separate peers,
|
||||
nested destination-local siblings, cancellation, and an inherited relative
|
||||
resource retaining its declaring context. Cross-collection search is unchanged.
|
||||
2. Reuse existing inheritance-version, overlay, and CLI guards; add targeted
|
||||
mounted cases for actual protected paths and their ancestors. Do not reject
|
||||
unrelated inheritance merely because it shares a mapping ancestor.
|
||||
3. Test effective-path secret predicates, field tags and recorded dependencies,
|
||||
superseded classified values, safe effective output/history/explanation, and
|
||||
bilateral diff redaction using disposable canaries. Compare mounted versus
|
||||
explicitly wrapped loads for equal effective values and no differences.
|
||||
4. Verify defaults, decoding, resolution, secret lookup, and validation execute
|
||||
once on the final shape; failures return no usable result. Reuse existing
|
||||
ordinary-load lifetime/ownership coverage and add mounted protection where
|
||||
placement creates a distinct risk.
|
||||
## Stage 9 — Reconcile documentation and audit the complete feature
|
||||
|
||||
Validate: destination/inheritance/secret/sensitivity/explain/diff/lifecycle tests
|
||||
and everyday check. Validated with
|
||||
`go test ./internal/engine -run 'Destination|Inheritance|Secret|Sensitivity|Explain|Diff|Load|Version|Grouped' -count=1`,
|
||||
`go test -race ./internal/engine`, and `./scripts/check.sh` (go1.26.8
|
||||
linux/amd64); all passed.
|
||||
Status: planned. Scope: final consistency and evidence; no publication work.
|
||||
|
||||
`TestLayeredDestinationInheritanceUsesFinalSiblingScopes` verifies parent and
|
||||
child contributions from separate peers, a higher-tier parent update, nested
|
||||
destination-local siblings, and cancellation. `TestLayeredDestinationInheritanceDoesNotSearchOtherCollections`
|
||||
keeps sibling lookup local. `TestLayeredMountedVersionProtectionCoversInheritanceAndUpperTiers`
|
||||
protects inherited values, scalar/null ancestors, consumed directives, selected
|
||||
overlays, and CLI overrides at mounted paths while allowing nonclaiming mapping
|
||||
ancestors and unrelated inheritance. The coverage exposed an ancestor gap in
|
||||
the existing inheritance-version check; it now applies the shared fragment claim
|
||||
logic to the transferred parent subtree.
|
||||
|
||||
`TestLayeredDestinationLifecycleAndSensitiveInspectionUseFinalShape` checks one
|
||||
defaults/resolution/secret-lookup/validation lifecycle, final mounted decoding,
|
||||
field tags and effective-path predicates, superseded history, and safe effective
|
||||
output/explanation against canaries; it compares mounted and explicitly wrapped
|
||||
loads for equal configuration and no diff. `TestLayeredDestinationDiffUsesBilateralSensitivity`
|
||||
checks redaction from either side and recorded dependencies, and
|
||||
`TestLayeredDestinationDecodeFailureReturnsNoResultOrLaterCallbacks` checks a
|
||||
mounted decode failure returns no result. Stage 8's
|
||||
`TestLayeredImportedInheritedValuesRetainResourceContexts` continues to verify
|
||||
the declaring context for inherited relative resources. Done: approved engine
|
||||
semantics integrate without per-fragment loading or a post-return processing
|
||||
pass.
|
||||
|
||||
## Stage 10 — Expose the root-owned facade and public acceptance tests
|
||||
|
||||
Status: complete. Scope: the two public fields and complete consumer behavior.
|
||||
|
||||
1. Add `Input.Destination Path` and `SourceInfo.Destination Path` to root types.
|
||||
Extend `toEngineInput`, `fromEngineSourceInfo`, `toEngineSourceInfo`, and all
|
||||
source publication paths with owned conversion. Run existing public/import
|
||||
boundary tests; expose no engine nodes, aliases, or bridge methods.
|
||||
2. Document zero/root behavior, mapping-only paths, main/underlay parity,
|
||||
inherited import placement, source-coordinate fallback, and source ownership
|
||||
beside declarations. Update the configuration contract for implemented input
|
||||
destinations, preserving canonical ownership of shared semantics.
|
||||
3. Add external-package public-load coverage for equivalent host file, native
|
||||
fs.FS file, byte, reader, and Mapping sources. Cover default/root destinations,
|
||||
literal escaped/numeric keys, empty mapping, NoSource, and invalid declarations.
|
||||
Include one public mounted main case, not just underlays.
|
||||
4. Add representative public tests tying final configuration to metadata,
|
||||
source placement, history, resources, callbacks, and safe diffs. Mutate returned
|
||||
record copies and repeat queries/loads to confirm detachment. Reuse engine
|
||||
matrices; public tests demonstrate supported integration rather than every
|
||||
private branch. Confirm failed loads expose detached source destinations.
|
||||
|
||||
Validated with `go test . -run 'Destination|FacadeLayered|PublicFacadeBoundary|DependencyImportBoundary' -count=1`,
|
||||
`go test -race ./...`, and `./scripts/check.sh` (go1.26.8 linux/amd64); all
|
||||
passed.
|
||||
|
||||
`TestFacadeInputDestinationsAcrossSourceKinds` exercises host, native
|
||||
filesystem, bytes, reader, and mapping inputs with literal escaped and
|
||||
numeric-looking mapping keys. `TestFacadeDestinationRootEmptyMappingNoSourceAndInvalidPaths`
|
||||
covers omitted/empty root placement, empty mapping presence, absent `NoSource`,
|
||||
invalid index/reserved destinations, and reader preflight. `TestFacadeImportedSourcesRetainInputDestination`
|
||||
checks public transitive import placement. `TestFacadeMountedMainAndUnderlayInspectionResourcesAndDiff`
|
||||
ties mounted main/underlay values to metadata, both source destinations, callback
|
||||
source context, relative-resource access during and after loading, history, safe
|
||||
effective/explanation rendering, and bilateral diff redaction; it also mutates
|
||||
returned records and confirms later queries and comparisons remain unchanged.
|
||||
`TestFacadeFailedLoadExposesDetachedSourceDestination` verifies failure records,
|
||||
and `TestSourceInfoDestinationConversionsAndCopies` covers root/engine source
|
||||
record conversion. Existing public-boundary tests pass with the new root-owned
|
||||
fields. Done: destination selection and inspection are available through the
|
||||
supported ConfigKit import path.
|
||||
|
||||
## Stage 11 — Add maintained simple and collection-style consumer examples
|
||||
|
||||
Status: complete. Scope: executable adoption examples with consumer-owned types.
|
||||
|
||||
1. Add a minimal mounted-fragment example using `Input.Destination` in an
|
||||
ordinary layered load. Show literal keys and root-default compatibility
|
||||
without introducing consumer parsing or generic merge helpers.
|
||||
2. Add one representative collection assembly under `examples/consumers`: peer
|
||||
prompt/profile fragments, collection metadata with ordinary `version`, a
|
||||
source-root import, local sibling inheritance, and an intentional higher-tier
|
||||
version-only override retaining the body. Keep the application VersionRule
|
||||
main-owned. Use a controlled native filesystem or temporary files.
|
||||
3. Demonstrate effective-path inspection plus source-relative resource lookup
|
||||
during resolution and from the result, including an inherited/surviving field.
|
||||
Application code owns opening/interpreting the resource and any qualified IDs.
|
||||
4. Add tests for final values, presence, actual source placement/coordinates,
|
||||
resource context, and expected conflict behavior. Link maintained examples
|
||||
from the consumer guide; add a small executable root example if useful for
|
||||
discovery without duplicating the complete scenario.
|
||||
|
||||
Validated with `go test ./examples/consumers -count=1`,
|
||||
`go test . -run '^Example' -count=1`, and `./scripts/check.sh` (go1.26.8
|
||||
linux/amd64); all passed, including local documentation links.
|
||||
|
||||
`Example_inputDestination` demonstrates a literal mounted mapping path and an
|
||||
ordinary root input without consumer-side parsing or merging.
|
||||
`LoadCollectionBundle` and `TestCollectionBundleAssemblesMountedPeersAndResources`
|
||||
exercise prompt/profile peer sources, imported collection metadata with an
|
||||
ordinary version label, main-owned schema-version checking, local sibling
|
||||
inheritance, and a higher-tier prompt version-only change that retains the rest
|
||||
of its body. The resolver and `ReadCollectionPromptContent` follow direct and
|
||||
inherited `content_file` provenance to the declaring native-filesystem context.
|
||||
The test checks final values, explicit presence, source destinations and authored
|
||||
coordinates, relative resources, and the inherited field's origin.
|
||||
`TestCollectionPeerPromptConflictsRemainStrict` preserves expected conflict
|
||||
behavior. The examples are linked from the consumer adoption guide. Done: simple
|
||||
and representative consumers substantiate the same model without a compensating
|
||||
structural pass.
|
||||
|
||||
## Stage 12 — Reconcile documentation and audit the complete implementation
|
||||
|
||||
Status: complete. Scope: final integration audit and evidence, not release work.
|
||||
|
||||
1. Update README navigation, consumer guidance, the component overview, and
|
||||
development reading/test maps. Add ADR 0011 to navigation. Update architecture
|
||||
policy only as needed to recognize placement within existing assembly and
|
||||
source ownership, linking precise behavior to the configuration contract.
|
||||
Do not change unrelated policies, deferred boundaries, or published notes.
|
||||
2. Audit every resolved decision, roadmap behavior, and request acceptance row
|
||||
against implementation and tests. Record the corresponding test names here;
|
||||
for reused coverage explain the behavior it proves. Do not mark complete
|
||||
based on green tests that do not exercise mounting.
|
||||
3. Review the complete baseline-to-candidate diff for accidental strengthening:
|
||||
extra naming rules, namespace uniqueness, main-only restrictions, changed
|
||||
merge/version semantics, invented source-read ordering guarantees, new limits,
|
||||
or expanded secret policies. Remove temporary helpers/unsupported branches
|
||||
left by staged integration. Confirm original source coordinates remain real.
|
||||
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 ./...`. Review source-kind and
|
||||
placement ownership coverage, error disclosure, complete-on-return handling,
|
||||
and root/private boundaries. Record commit, Go version, results, and any
|
||||
limitations. No release command, CI waiting, benchmark, or downstream upgrade.
|
||||
5. Mark this plan and the roadmap implemented only when code, public examples,
|
||||
and owning contracts agree. Retain completed planning evidence until separately
|
||||
authorized release preparation.
|
||||
`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.
|
||||
|
||||
Audit evidence for the approved decisions and request acceptance surface:
|
||||
|
||||
| Behavior reviewed | Evidence and what it proves |
|
||||
| --- | --- |
|
||||
| Root-owned `Input.Destination` and `SourceInfo.Destination`; detached conversions and publication | `TestSourceInfoDestinationConversionsAndCopies`, `TestFacadeFailedLoadExposesDetachedSourceDestination`, and `TestFacadeMountedMainAndUnderlayInspectionResourcesAndDiff` verify root/engine conversion, error records, and returned record detachment. `TestPublicFacadeBoundary` and `TestDependencyImportBoundary` verify no engine types cross the facade. |
|
||||
| Literal mapping keys, parsed numeric keys, reserved structural tokens, and invalid-path preflight | `TestNormalizeDestinationUsesLiteralMappingKeys`, `TestNormalizeDestinationRejectsIndicesAndReservedKeys`, and `TestLayeredLoadPreflightsDestinationsBeforeReadingSources` cover mapping-only normalization and rejection before reader consumption; `TestFacadeDestinationRootEmptyMappingNoSourceAndInvalidPaths` verifies the public error boundary. |
|
||||
| Placement of acquired bodies, empty mappings versus absence, imports, all source kinds, physical identity, and authored coordinates | `TestFacadeInputDestinationsAcrossSourceKinds` covers host/native/bytes/reader/mapping sources; `TestFacadeSameFragmentMountsAtSeparateCollectionDestinations` proves independent public collections can retain the same local key. `TestLayeredImportOnlyInputMaterializesDestination`, `TestLayeredHostImportsInheritInputDestinationTransitively`, `TestLayeredNativeFilesystemImportsInheritInputDestination`, and `TestLayeredDestinationsDoNotChangeRepeatedSourceIdentity` cover inherited import placement and unchanged identity. `TestPlaceDocumentWrapsEmptyMappingAndPreservesSourceCoordinates`, `TestPlaceDocumentPreservesAuthoredEntryCoordinates`, and `TestLayeredDestinationDiagnosticsUseEffectivePathsAndAuthoredLocations` distinguish fallback wrapper locations from authored coordinates. |
|
||||
| Strict composition, explicit-wrapper equivalence, precedence, empty values, and domain `version` overrides | `TestLayeredDestinationStrictCompositionBoundaries`, `TestLayeredDestinationMatchesExplicitlyWrappedInput`, `TestEmptyMountedMappingRetainsLowerChildren`, and `TestLayeredDestinationOverlayRetainsOrdinaryValueSemantics` prove existing group and overlay semantics are retained; the latter includes ordinary field-only updates rather than whole-record replacement. |
|
||||
| Main-owned version checks and imported, underlay, inheritance, overlay, CLI, and ancestor protection | `TestLayeredDestinationChecksVersionOnceOnComposedMain`, `TestLayeredDestinationVersionClaimsUsePlacedApplicationPaths`, `TestLayeredImportedVersionClaimsUseEffectiveDestination`, and `TestLayeredMountedVersionProtectionCoversInheritanceAndUpperTiers` cover effective paths, one main check, protected-path claims/ancestors, and nonclaiming mapping ancestors. `TestLoadVersionDestinationTypesKeepOrdinaryDecoding` preserves exact configured-path conversion and ordinary nested decoding. |
|
||||
| Final-shape sibling inheritance, no cross-collection lookup, one lifecycle, and failure without a usable partial result | `TestLayeredDestinationInheritanceUsesFinalSiblingScopes`, `TestLayeredDestinationInheritanceDoesNotSearchOtherCollections`, `TestLayeredDestinationLifecycleAndSensitiveInspectionUseFinalShape`, and `TestLayeredDestinationDecodeFailureReturnsNoResultOrLaterCallbacks` exercise these behaviors. Reused inheritance, lifecycle, and callback tests cover generic behavior that destination placement does not alter. |
|
||||
| Effective paths, presence, provenance/history, safe rendering, sensitivity, bilateral diff, and source-relative resources | `TestLayeredDestinationsRetainOriginsHistoryAndDetachedRecords`, `TestLayeredDestinationLifecycleAndSensitiveInspectionUseFinalShape`, `TestLayeredDestinationDiffUsesBilateralSensitivity`, `TestLayeredImportedInheritedValuesRetainResourceContexts`, and `TestFacadeMountedMainAndUnderlayInspectionResourcesAndDiff` connect mounted values to inspection. The imported-inheritance test specifically proves the inherited value keeps the declaring source's passive resource context. |
|
||||
| Shared depth/node limits and unchanged root/absence accounting | `TestPlaceDocumentRootAndBounds`, `TestDestinationPlacementCountsAgainstSharedNodeBudget`, `TestMultipleMountedInputsSharePlacementCharges`, `TestImportedEmptyBodiesChargeEachDestinationWrapper`, `TestSelectedOverlayAndCLIUsePlacementNodeCharges`, and `TestNoSourceAndRootPlacementAddNoWrapperCharges` cover per-document and aggregate limits without adding a new limit class. |
|
||||
| Maintained consumer usage and strict peer behavior | `Example_inputDestination`, `TestCollectionBundleAssemblesMountedPeersAndResources`, and `TestCollectionPeerPromptConflictsRemainStrict` verify the simple and representative collection examples against actual values, resources, source records, and conflict behavior. |
|
||||
|
||||
The wider baseline-to-candidate review covered all 38 changed files (`6353598..2d8df22`): production changes are limited to the root facade fields/conversions, private input/import assembly and accounting, source record ownership, and the inheritance version-claim correction described above. The contract and tests do not impose identifier grammar, namespace uniqueness, main-only placement, source-read ordering, new budgets, nested version conversion, or expanded secret policy. The implementation wraps only acquired application bodies after processing source-root directives; placement does not change physical source identity, authored node locations, filesystem resolution, or later-tier semantics. Stage evidence above reuses existing general composition, resource, inheritance, version, lifecycle, sensitivity, and boundary tests where those behaviors are unchanged; mounted-specific cases are named separately.
|
||||
|
||||
Completion record: audited source candidate `2d8df22dd1cb9fde8e60853da3e2260731acf2bb`. On `go1.26.8 linux/amd64`, `./scripts/check.sh` passed, including formatting, whitespace, documentation links, tests, vet, and build. `GOTOOLCHAIN=local GOPROXY=off go test -race ./...` also passed with dependency downloads disabled. No remaining implementation limitations were found; release preparation, CI, benchmark campaigns, and downstream upgrades remain separately scoped.
|
||||
|
||||
Done: one complete layered load supports input destinations with coherent values,
|
||||
diagnostics, inspection, limits, and source ownership across the approved surface.
|
||||
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.
|
||||
|
||||
## Implementation owner map
|
||||
|
||||
Use graph tools to locate these symbols rather than assume line numbers:
|
||||
Use graph discovery to confirm current symbols and locations before editing:
|
||||
|
||||
- Public input forwarding: `layered.go`, `records.go`, `conversion.go`
|
||||
(source conversions), and existing facade tests.
|
||||
- Private request and lifecycle: `internal/engine/layered.go`, `load_request.go`
|
||||
(`loadInput`, `acquireUnderlayGroup`, `assembleLayeredInput`), `load.go`
|
||||
(`executeLoadRequest`), and `load_input.go` (`assembleBaseInputTracked`).
|
||||
- Directives and imports: `directives.go` (`splitImportDirectives`,
|
||||
`fragmentVersionClaim`), and `imports.go` (`visitPath`).
|
||||
- Shared document semantics: `compose.go`, `document_walk.go`
|
||||
(`countInputNodes`), `path.go`, `parse.go`, and `value_operation.go` limits.
|
||||
- Inspection: `metadata.go`, `history.go`, `explain.go`, `resource_context.go`,
|
||||
`inheritance_origin.go`, `render.go`, and `diff.go`; source copies live in
|
||||
engine `records.go`. Confirm current filenames through the component overview.
|
||||
- `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`; root `facade_destination_test.go`; and
|
||||
maintained consumer fixtures/tests. Reuse owners rather than duplicate suites.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None required for implementation. The four policy choices are approved; this
|
||||
plan selects API spelling, validation timing/error category, coordinate handling,
|
||||
and accounting within them. Surface a newly discovered incompatibility or scope
|
||||
change with evidence rather than resolving it by silently narrowing the feature
|
||||
or strengthening an unrelated contract.
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user