Implement canonical projection and detached copies

This commit is contained in:
2026-09-06 19:44:36 +00:00
parent 2b65876a7d
commit 15172294b5
8 changed files with 1059 additions and 23 deletions

View File

@@ -2,7 +2,7 @@
## Status and ownership
Status: implementation in progress; Stages 1–4 are complete and later stages are
Status: implementation in progress; Stages 1–5 are complete and later stages are
pending.
Audience: a `gpt-5.6-terra` coding agent implementing one stage per prompt, in
@@ -512,7 +512,30 @@ Acceptance:
## Stage 5 — Implement canonical projection and detached copies
Status: pending.
Status: complete.
Completion evidence (2026-09-06):
- Added descriptor-driven canonical typed projection and independently owned cloning
in [`projection.go`](../../projection.go), without YAML serialization or a second
binding model. Zero values, nil/empty distinctions, exact integers, destination-
precision finite floats, durations, text scalars, dynamic concrete values, and
recursive acyclic objects retain their configuration meaning.
- Added active-graph cycle detection, private depth/node enforcement, safe custom
codec and dynamic-type failures, zeroing of ignored state, reconstruction of text
scalars into fresh instances, and non-preservation of shared pointer identity.
- Added canonical-tree structural comparison with semantic mapping additions,
removals and replacements, cross-kind replacement, and whole-sequence atomicity.
The [current ownership contract](../config.md#typed-projection-and-ownership) and
component inventory now own the implemented behavior.
- Focused tests mutate every source alias after cloning, cover nil versus empty,
wide integers, duration/text canonicalization, recursive acyclic values and cycles,
unsupported dynamic types, non-finite floats, value-free codec failures, inline
physical members/conflicts, projection bounds, ignored state, and meaningful
comparison paths without index-wise sequence matching. Verified `go test ./...`,
`go vet ./...`, `go build ./...`, `go mod tidy -diff`, and `git diff --check` with
Go 1.26.7 on linux/amd64. No deviations were required; defaults and typed decoding
remain later work.
Read: feature [ownership](initial.md#recorded-resolution-and-validation) and
[type/projection contract](initial.md#supported-types-and-projection).

View File

@@ -645,6 +645,11 @@ subsequently mutate, not language-enforced immutability of exported Go values.
Callers should treat returned configuration as read-only; later caller mutations
are outside the captured metadata snapshot.
Canonical typed projection, detached cloning, and structural comparison are now
implemented as private foundations. The [current ownership contract](../config.md#typed-projection-and-ownership)
owns those mechanics; publishing independently captured results remains lifecycle
work.
Application semantic validation runs after successful resolution and collects
independent errors in a standard diagnostic form. Validators are read-only and
own domain requirements; checking live S3 buckets or starting runtime clients
@@ -1304,20 +1309,12 @@ sequence length. Ignored and unexported fields stay outside configuration projec
hooks must not use them to carry runtime resources or configuration needing
inspection. Non-configuration runtime state belongs in separate application types.
One field-binding model supplies defaults, decoding, path lookup, change auditing,
and rendering. `omitempty` never removes projected zero values. Preserve nil
versus empty maps/slices where represented by the type. Shared pointer identity
inside application values is not a configuration semantic; cyclic values are
unsupported and independent load/snapshot ownership must still hold.
`time.Duration` projects to a canonical duration string. A custom scalar's text
marshal method supplies its deterministic canonical string; unmarshalling must
accept that representation and preserve its configuration meaning. These methods
must be side-effect-free with respect to shared state. Custom scalars are atomic
for comparison/history; their internal fields are not traversed. Reject types
with only a text decoder and no supported inspection representation. Conversion
or projection failures produce safe diagnostics. This is a bounded scalar seam,
not a custom structural decoder or arbitrary reflection extension framework.
Canonical projection, detached copying, cycle and finite-value enforcement, custom
scalar reconstruction, and structural comparison are implemented and owned by the
[current ownership contract](../config.md#typed-projection-and-ownership). The same
field-binding model must still supply defaults, decoding, change auditing, and
rendering. Application text methods must remain side-effect-free with respect to
shared state; this is a bounded scalar seam, not a custom structural decoder.
## Internal organization