Add audited application resolution

This commit is contained in:
2026-09-06 20:14:55 +00:00
parent cc41653bfd
commit 0da4260ad6
16 changed files with 909 additions and 57 deletions

View File

@@ -2,7 +2,7 @@
## Status and ownership
Status: implementation in progress; Stages 1–7 are complete and later stages are
Status: implementation in progress; Stages 1–8 are complete and later stages are
pending.
Audience: a `gpt-5.6-terra` coding agent implementing one stage per prompt, in
@@ -684,7 +684,36 @@ Acceptance:
## Stage 8 — Implement recorded application resolution
Status: pending.
Status: complete.
Completion evidence (2026-09-06):
- Implemented per-load `Resolution`, `IsExplicit`, `Record`, `Default`, `Normalize`,
`Error`, and `Warning` in [`resolution.go`](../../resolution.go), and enabled the
resolver in `Load` after successful decode while leaving semantic validation gated.
- Added schema-aware path/kind/dependency checks, safe reason requirements, dynamic
and typed helper projection, final helper/path consistency checks, before/after
structural comparison, exact/ancestor record coverage, and distinct safe failures
for invalid values, targets, records, and unrecorded changes.
- Coalesced repeated path intent deterministically, retaining unique reasons and
dependencies, using the last helper value, and promoting mixed operations to
normalization. Equal-valued derived intent remains recorded; map copy/writeback,
container coverage, deletions, and new dynamic/map descendants are supported.
- Integrated resolution origins and history without changing surviving input
explicitness, retained private detached before/after snapshots, sorted records by
semantic path, and made retained callback-context use panic with fixed value-free
text. Resolver errors are suppressed unless explicitly reported through the
context; warnings remain on successful results. The
[current resolution contract](../config.md#recorded-application-resolution) owns
this behavior.
- Focused tests execute the timeout/artifact consumer shape, explicit null/zero and
absent-baseline behavior, normalization, map writeback, equal and repeated helper
intent, stable map-derived record order, subtree removal, snapshot detachment,
unrelated targets, invalid paths/kinds/values, unrecorded mutation, safe hook
failures, and closed resolution/version contexts. Verified `go test ./...`,
`go test -race ./...`, `go vet ./...`, `go build ./...`, `go mod tidy -diff`, and
`git diff --check` with Go 1.26.7 on linux/amd64. No deviations were required;
semantic validation remains later work.
Read: feature [resolution callbacks](initial.md#resolution-and-validation-callbacks).

View File

@@ -571,37 +571,16 @@ rendering remain target work below.
## Recorded resolution and validation
Application-owned resolution runs after decoding and may derive absent values
or normalize explicitly configured ones. Provide a narrow resolution context
that exposes metadata and records each changed semantic path, operation kind
(derived default or normalization), and a safe reason. Dependency paths may be
recorded when a value is derived from other fields.
Application-owned recorded resolution is implemented. The
[current resolution contract](../config.md#recorded-application-resolution) owns
explicitness queries, helpers and manual records, structural mutation auditing,
coalescing, diagnostics, origins, history, and snapshot ownership. Layered input
history, redacted explanation, and secret dependency propagation remain target work.
A resolver may mutate the typed configuration, but ConfigKit compares its
before/after configuration projection and requires records for changed paths.
Unrecorded changes are resolution errors. Container replacement records cover
changed descendants. Capture previous/final values internally from the actual
configuration rather than trusting separately supplied values. Application
resolvers own meaningful reasons; a diff alone cannot explain intent. Reasons
must not embed secrets. The proposed [resolution API](#resolution-and-validation-callbacks)
provides helpers to combine assignments and records. Snapshot comparison verifies
net changes during the hook; it does not reconstruct intermediate assignments.
A record describes the hook's before/final transition and declared intent, not an
automatically recovered event log. Equal-valued derived-default assignments may
still have a record identifying their intent. Multiple records at the same path
are coalesced for that hook, retaining declared reasons and dependencies.
The final configuration, effective output, presence queries, and explanation
records must agree. Do not render the pre-resolution YAML tree as the final
configuration. ConfigKit promises an independently owned snapshot it does not
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.
Canonical typed projection, detached cloning, structural comparison, and publishing
independently captured resolved results are implemented. The
[current ownership contract](../config.md#typed-projection-and-ownership) owns those
mechanics.
Application semantic validation runs after successful resolution and collects
independent errors in a standard diagnostic form. Validators are read-only and
@@ -613,7 +592,9 @@ is outside this lifecycle. Do not run later hooks on an invalid typed value.
Safe diagnostic/provenance value records, canonical diagnostic rendering, and
`LoadError` access are implemented. Their current contracts are owned by
[`records.go`](../../records.go) and [`diagnostic.go`](../../diagnostic.go).
Attaching those records to the loading lifecycle remains target work below.
Base/default and resolution records are attached to the current loading lifecycle.
Additional layers, safe historical values, redaction, and rendering remain target
work below.
Retain input sources, layer, line/column where available, import sites, effective
origins, overridden definition records, and resolution operations. Container
@@ -814,6 +795,10 @@ behavior. Layered callback history and safe historical values remain target beha
### Resolution and validation callbacks
The resolution declarations and behavior below are implemented; the
[current recorded-resolution contract](../config.md#recorded-application-resolution)
is authoritative. Semantic validation behavior in this section remains target work.
```go
func (r *Resolution) IsExplicit(path Path) bool
func (r *Resolution) Record(path Path, kind ChangeKind, reason string, dependencies ...Path)