Update guidance for the cleaned public API

This commit is contained in:
2026-10-27 15:40:22 +00:00
parent c96197c417
commit 2ff588eb64
11 changed files with 127 additions and 66 deletions

View File

@@ -46,9 +46,9 @@ literal single filename components; it does not expand application-name
placeholders. An application slug is required only when a selected directory or
filename group uses it. Literal custom paths are not expanded for `~`, variables,
or wildcards; relative paths are resolved from the working directory at load time.
The zero `Search`, `Searches()`, `Paths()`, and an empty custom filename group
contribute no candidates. An explicitly supplied empty path or filename is
invalid. Slugs and custom filenames must be usable single host filename
The zero `Search`, `Searches()`, `SearchPaths()`, and an empty custom filename
group contribute no candidates. An explicitly supplied empty path or filename
is invalid. Slugs and custom filenames must be usable single host filename
components; ConfigKit preserves their case and spelling.
Search expansion is ordered concatenation. For each directory search, ConfigKit
@@ -290,7 +290,7 @@ the application root and are not moved beneath the main input's destination.
`SourceInfo.Destination` reports each acquired source's effective mapping or
sequence-container path, including imports. `PlacementMode` reports how that
source was placed; mapping is the zero value, and CLI/overlay sources report
mapping unless item placement was applied. `DestinationUnresolved` is true only
mapping unless item placement was applied. `DestinationIsFallback` is true only
when an enclosing item index needed to name the source's destination has not yet
been assigned. In that case `Destination` reports the nearest resolved enclosing
collection container and omits the unresolved local suffix. A source's own item
@@ -457,10 +457,10 @@ successful result. Callback panics remain programming failures.
`Options.SourceVersionMode` and `LayeredOptions.SourceVersionMode` select how
one `Definition.Version` policy applies across source documents. The zero value
`SourceVersionModeDefault` preserves the existing main-only check at its
effective path and existing protected-path behavior. `SourceVersionModeIfPresent`
checks each participating document that declares a version and permits absent
non-main declarations. `SourceVersionModeRequired` rejects a participating
`SourceVersionModeMainOnly` (the zero value) preserves the existing main-only
check at its effective path and existing protected-path behavior.
`SourceVersionModeIfPresent` checks each participating document that declares a
version and permits absent non-main declarations. `SourceVersionModeRequired` rejects a participating
document without a declaration. Enabled modes require a usable `VersionRule`
and checker; an unknown mode or unusable rule is an options error before source
access or callbacks.
@@ -497,7 +497,7 @@ declaration locations use source-local coordinates; ordinary payload
diagnostics continue to use effective paths. Default-mode diagnostics are
unchanged.
`SourceInfo.VersionCheck` is nil when enabled declaration processing did not
`SourceInfo.VersionEvidence` is nil when enabled declaration processing did not
occur. Otherwise it records a source-local `Path`, the observed `Version` state
(`Present`, `Null`, and, when disclosed, exact `Text`), an actual or nearest
available `Location`, and whether text was redacted. A non-nil record with
@@ -573,7 +573,7 @@ reports it absent. Queries return detached records.
### Secret classification and effective rendering
Secret classification combines `configkit:"secret"` field tags with the optional
pure `Definition.Secret(Path) bool` predicate. Tags on concrete structs inside
pure `Definition.Sensitive(Path) bool` predicate. Tags on concrete structs inside
supported dynamic values are retained in typed projections, including superseded
defaults and pre-resolution values. A tagged or predicate-classified
container makes all descendants sensitive. ConfigKit evaluates final and historical
@@ -636,7 +636,7 @@ writes remain visible. When structural replay differs from the pre-CLI typed inp
a `ChangeDecoding` event records retained defaults and canonical decoding. CLI
contributions then retain their raw input representation while effective and
resolution values use the typed projection. This built-in inspection operation is
not accepted by `Resolution.Record`.
not exposed as a manual recording method.
Base, overlay, and CLI history preserves the policy-validated input representation,
including a superseded value that could not have decoded into the final Go field.
@@ -671,11 +671,11 @@ unredacted mode.
Retained history consists of immutable source applications and audited subtree
deltas, rather than a full tree copy per field. Shared nodes count once toward a
4,000,000-node retained-history limit; exceeding it fails loading with
`explain.limit_exceeded`. Replaying one requested path is performed on demand, and
`history.limit_exceeded`. Replaying one requested path is performed on demand, and
the returned YAML strings and nested records cannot mutate later explanations.
Application commands should render the separate `SecretsReport` immediately after
an explicit `LoadSecretsDir` bootstrap, then use `WriteDiagnostics`,
an explicit `LoadSecretsIntoEnvironment` bootstrap, then use `WriteDiagnostics`,
`WriteEffective`, or `WriteExplanation` on the later load result as appropriate.
ConfigKit does not infer bootstrap outcomes from a secret reference and does not
bundle these independent reports into a command framework.
@@ -770,11 +770,12 @@ reference state without printing its value.
## Explicit secrets-directory bootstrap
`LoadSecretsDir(directory)` is a separate, opt-in startup operation. It is never
called by `Load`, is not a YAML option, and does not participate in configuration
validation. Applications choose the native directory path and should invoke the
operation once before starting concurrent work. The selected path may itself be a
symlink; ConfigKit resolves it to an existing canonical directory before examining
`LoadSecretsIntoEnvironment(directory)` is a separate, opt-in startup operation.
It is never called by `Load`, is not a YAML option, and does not participate in
configuration validation. Applications choose the native directory path and
should invoke the operation once before starting concurrent work. The selected
path may itself be a symlink; ConfigKit resolves it to an existing canonical
directory before examining
its immediate entries.
The bootstrap enumerates at most 1,024 entries, including dot-prefixed entries.
@@ -814,7 +815,7 @@ per-load `Resolution` context. The context's
`IsExplicit` query uses surviving input presence, so explicit false, zero, empty, and
null are never confused with absence or static defaults.
`Resolution.InputInfo(path)` returns detached effective metadata from the fixed
`Resolution.EntryInfo(path)` returns detached effective metadata from the fixed
post-decode entry state, including explicit CLI overrides, before application
resolution runs. It includes retained static defaults, preserves explicit null, and
uses the same exact semantic path matching as `Metadata.Lookup`; missing,
@@ -837,18 +838,20 @@ exit; changing them cannot affect later queries, results, or another load.
`Default` assigns and records a derived value only when its path is not explicit.
`Normalize` always assigns and records. For transformations performed directly by
application code, `Resolution.Record` declares a derived-default or normalization
operation; a recorded container covers changes to its descendants. Records require
a schema-valid path, valid kind, safe nonempty reason, and schema-valid dependency
paths. Repeated records at one path are coalesced: reasons and dependencies retain
their first occurrence, the last helper value is authoritative, and any normalization
makes the combined operation a normalization.
application code, `Resolution.RecordDerivedDefault` and
`Resolution.RecordNormalization` declare the operation already performed; a
recorded container covers changes to its descendants. These methods do not assign
values, and a derived-default record does not suppress work for explicit input.
Records require a schema-valid path, safe nonempty reason, and schema-valid
dependency paths. Repeated records at one path are coalesced: reasons and
dependencies retain their first occurrence, the last helper value is authoritative,
and any normalization makes the combined operation a normalization.
ConfigKit projects the configuration before and after the callback. Every net change
must have an exact or ancestor record. Helper-assigned values must agree with the
final value at their declared path, which supports ordinary map-entry copy/writeback
while detecting forgotten writeback or unrelated targets. Invalid paths, kinds,
values, records, helper targets, and unrecorded mutations fail the load. Equal-valued
while detecting forgotten writeback or unrelated targets. Invalid paths, values,
records, helper targets, and unrecorded mutations fail the load. Equal-valued
derived assignments may still record application intent even when there is no
structural change.
@@ -1226,6 +1229,8 @@ replaces rather than extends the default pattern. Nil `Pattern` leaves directory
filenames unrestricted; a non-nil empty slice selects none. Defaults do not make
a field applicable to selectors that do not support it, and load calls snapshot
the supplied pointers and slice before source acquisition.
The Go fields are named `FollowSymlinks` and `IncludeHidden`; the YAML keys
remain `follow` and `hidden`.
A source's `configkit.sequences` declarations apply independently of import
enablement; a `configkit.imports` declaration still requires `Options.Imports`.
@@ -1261,15 +1266,15 @@ or glob selection fail with `import.missing`; it also makes missing named paths
fail. Requiredness does not suppress invalid paths, containment failures,
directories selected as files, permissions, parse errors, or composition errors.
For inspection, `SourceInfo.ImportSelections` records one outcome for each
completed optional declaration whose entire selected set is empty. The record is
attached to its declaring source, keeps the declaration path local to that source,
identifies the declaration mapping (including its `SourceID`) and selector, and
uses outcome `none`. Records remain in declaration order and are available
through the existing result, load
error, and callback source snapshots. They do not enumerate candidates, explain
For inspection, `SourceInfo.EmptyImportSelections` records each completed optional
declaration whose entire selected set is empty. The record is attached to its
declaring source, keeps the declaration path local to that source, and identifies
the declaration mapping (including its `SourceID`) and selector. Records remain
in declaration order and are available
through the existing result, load-error, and callback source snapshots. They do
not enumerate candidates, explain
why a path was absent, or describe partial omissions. Empty `path: []` succeeds
regardless of requiredness: it produces a `none` record when effectively optional,
regardless of requiredness: it produces a record when effectively optional,
and no record when effectively required. Snapshots detach the record paths and
slices.

View File

@@ -99,15 +99,20 @@ records why discovery is explicitly selected.
`Options.ImportDefaults` and `LayeredOptions.ImportDefaults` apply one
load-wide policy to enabled main, underlay, and transitive imports. Each field
is resolved independently: a declaration's explicit value wins, then the
application default, then the library default. `Required`, `Follow`, `Hidden`,
and `Recursive` use nil pointers for unspecified values. `Pattern` applies to
application default, then the library default. `Required`, `FollowSymlinks`,
`IncludeHidden`, and `Recursive` use nil pointers for unspecified values.
`Pattern` applies to
directory searches: nil leaves filenames unrestricted, while a non-nil empty
slice selects no files. A declaration's own `pattern` replaces the application
default. The defaults do not enable imports or change selected-overlay behavior.
The Go fields `FollowSymlinks` and `IncludeHidden` correspond to the unchanged
YAML keys `follow` and `hidden`.
`Result.Sources`, `LoadError.Sources`, and `Resolution.Source` expose each
declaring source's `ImportSelections`. These records identify the source-local
declaration path, its authored location and selector, and the `none` outcome;
declaring source's `EmptyImportSelections`. `Result.Source(id)` and
`LoadError.Source(id)` retrieve one retained record directly when its load-local
ID is known. These records identify the source-local declaration path, its
authored location and selector;
they do not include candidate names or a guessed reason for absence. Returned
records are detached snapshots. The [configuration contract](../config.md#explicit-imports)
owns selector applicability and exact absence semantics.
@@ -117,7 +122,7 @@ owns selector applicability and exact absence semantics.
[`LoadVersionedService`](../../examples/consumers/source_version.go) demonstrates
if-present and required modes with one `Definition.Version` rule across a mounted
main input and an underlay. The example reads only sanitized
`SourceInfo.VersionCheck` fields; its executable test is in
`SourceInfo.VersionEvidence` fields; its executable test is in
[`layered_test.go`](../../examples/consumers/layered_test.go). The
[configuration contract](../config.md#shared-source-version-checks) defines
participation, source-local lookup and diagnostics, non-main header consumption,
@@ -264,7 +269,7 @@ conversion API.
## Source-aware application path policy
[`LoadNotariusPaths`](../../examples/consumers/consumers.go) is the maintained
path-bearing example. Its application resolver uses `Resolution.InputInfo` and
path-bearing example. Its application resolver uses `Resolution.EntryInfo` and
`Resolution.Source` before normalizing: relative CLI input uses an explicitly
supplied invocation directory, retained defaults use the canonical main source,
and a file-authored scalar uses its one declaring source. Absolute paths remain
@@ -301,10 +306,47 @@ The examples preserve domain meaning while adopting one configuration convention
parsers translate only explicitly set configuration flags into `Override` records.
Separate invocation state remains outside configuration.
- Credential fields migrate to environment-name `Secret` references. Applications
explicitly call `LoadSecretsDir` before `Load` when they choose file bootstrap;
explicitly call `LoadSecretsIntoEnvironment` before `Load` when they choose
file bootstrap;
blocked empty variables remain blocked, and ordinary `Load` never changes the
process environment.
### Pre-v1 public API cleanup
The pre-v1 API cleanup replaces these names outright; it does not retain
compatibility aliases:
| Previous API | Current API |
| --- | --- |
| `Resolution.InputInfo(path)` | `Resolution.EntryInfo(path)` |
| `Definition.Secret` | `Definition.Sensitive` |
| `SourceVersionModeDefault` | `SourceVersionModeMainOnly` |
| `SourceVersionCheck` | `SourceVersionEvidence` |
| `SourceInfo.VersionCheck` | `SourceInfo.VersionEvidence` |
| `ImportSelection` | `EmptyImportSelection` |
| `SourceInfo.ImportSelections` | `SourceInfo.EmptyImportSelections` |
| `SourceInfo.DestinationUnresolved` | `SourceInfo.DestinationIsFallback` |
| `ImportDefaults.Follow` / `.Hidden` | `FollowSymlinks` / `IncludeHidden` |
| `Paths(paths...)` | `SearchPaths(paths...)` |
| `LoadSecretsDir(directory)` | `LoadSecretsIntoEnvironment(directory)` |
| `LayerBase` | `LayerMain` |
| `CodeExplainLimitExceeded` | `CodeHistoryLimitExceeded` |
| `CodeResolveInvalidKind` / `CodeOptionsUnavailable` | Removed; no replacement |
| `ImportSelection.Outcome`, `ImportSelectionOutcome`, `ImportSelectionNone` | Removed; empty-selection records no longer carry an outcome |
| `Resolution.Record(path, ChangeDerivedDefault, reason, deps...)` | `Resolution.RecordDerivedDefault(path, reason, deps...)` |
| `Resolution.Record(path, ChangeNormalization, reason, deps...)` | `Resolution.RecordNormalization(path, reason, deps...)` |
| Enumerating `Result.Sources()` / `LoadError.Sources()` to find one ID | `Result.Source(id)` / `LoadError.Source(id)` |
| Provenance string `"base"` | `"main"` |
| History diagnostic string `"explain.limit_exceeded"` | `"history.limit_exceeded"` |
The YAML import keys `follow` and `hidden`, the `configkit:"secret"` tag, and
typed `Secret` references are unchanged. Consumers that compare literal strings
or keep serialized diagnostic/provenance expectations may need to update those
alongside Go references. This repository guidance does not claim that downstream
applications have migrated and does not select a release version for this
breaking pre-v1 change. `ChangeKind` and its inspection constants remain; use
`Default` and `Normalize` when the helper should both assign and record a value.
### Selected-overlay migration
To adopt the current selected-overlay API, rename `Options.Profile`,
@@ -330,7 +372,7 @@ focused behavioral owner:
| `Load`, `NoSource`, validation, versions, resolution, `SecretEnv`, overrides, and explanation | Executable examples in [`example_test.go`](../../example_test.go) |
| Source/import/selected-overlay pipeline rules and artifact defaults | Narratio-shaped executable example and fixture |
| Canonical module objects and dynamic option handling | WeatherReporter- and Notarius-shaped examples and migration tests |
| `LoadSecretsDir`, bootstrap reporting, typed lookup, CLI explanation | `Example_weatherStartup` |
| `LoadSecretsIntoEnvironment`, bootstrap reporting, typed lookup, CLI explanation | `Example_weatherStartup` |
| Native filesystem, grouped underlays, programmatic mapping, retained resource context | `Example_nativeFilesystem`, `Example_layeredCatalog`, and their focused consumer tests |
| Literal input destinations, root-default compatibility, and mounted peer collections | `Example_inputDestination`, `LoadCollectionBundle`, and `destinations_test.go` |
| Named sibling inheritance, presence, and derivation | `Example_inheritedPresets` and `TestPresetCatalogOneLoadAndDerivation` |

View File

@@ -1,6 +1,6 @@
# Pre-v1 Public API Cleanup Implementation Plan
Status: in progress; Stages 1–9 are complete and Stages 10–11 are pending.
Status: in progress; Stages 1–10 are complete and Stage 11 is pending.
Baseline: `07e4ae5d9236935389e81b207d4a8f00543fafce`.
Audience: a Luna coding agent executing the stages sequentially.
@@ -400,7 +400,9 @@ preserve success/failure evidence without new load activity.
## Stage 10 — Complete Guidance And Consumer Migration Information
Status: pending. Covers all accepted changes' documentation and maintained usage.
Status: complete. Consumer guidance, current contracts, declaration comments, and
maintained examples use the selected API; historical report references identify
their completed plan revision.
1. Review declaration comments and [config.md](../config.md)'s owning sections:
discovery, import defaults/evidence, source versions, layered metadata,
@@ -434,6 +436,8 @@ go test . -run '^Example|TestLocalDocumentationLinks' -count=1
git diff --check
```
Validation passed with the commands above.
Completion: current guidance/examples use the selected API, migration information
is complete, and historical evidence remains accurate.

View File

@@ -1,13 +1,14 @@
# Interface Contract Remediation Roadmap
Status: implemented. The shared history owner and all four audit corrections
are complete; validation is recorded in [implementation.md](implementation.md).
are complete; validation is recorded in the completed plan at
`07e4ae5:docs/roadmap/implementation.md`.
Planning baseline: `1f64673` (v0.10.2 implementation plus documentation changes).
This roadmap covers the four findings in the [interface audit](interfaces.md).
The audit owns reproductions, evidence, and finding numbers. This document owns
the combined target, required changes, and design intent. The
[implementation plan](implementation.md) owns concrete stages, private
the combined target, required changes, and design intent. The completed plan at
`07e4ae5:docs/roadmap/implementation.md` records concrete stages, private
implementation choices, validation commands, and progress.
## Purpose And Scope
@@ -196,8 +197,9 @@ by metadata.
#### Replace Existing Attribution Machinery
The common model must replace independent historical attribution, rather than
become another representation alongside it. The implementation plan should map
the following owners to their replacements:
become another representation alongside it. The completed plan at
`07e4ae5:docs/roadmap/implementation.md` mapped the following owners to their
replacements:
| Current owner | Required change |
| --- | --- |
@@ -330,5 +332,6 @@ The selected common underlying model addresses both concerns. This accepts a
larger internal refactor than a local shape-filtering fix.
No significant open decision remains at roadmap level. Private representation,
indexing, and helper choices are recorded in the completed implementation plan.
indexing, and helper choices are recorded in the completed plan at
`07e4ae5:docs/roadmap/implementation.md`.
This roadmap does not revise accepted ADRs.

View File

@@ -8,7 +8,8 @@ implementation plan; resolution evidence is recorded with each finding.
The [interface remediation roadmap](interface-remediation.md) describes the
settled target and its dependencies, including a shared internal history model
for metadata history and explanation. The completed implementation and
integrated validation are recorded in [implementation.md](implementation.md).
integrated validation are recorded at
`07e4ae5:docs/roadmap/implementation.md`.
This audit retains the findings and original reproduction evidence.
## Scope and evidence
@@ -39,7 +40,7 @@ existing contracts rather than introduce new API restrictions or guarantees.
Priority: P2. Status: resolved. Evidence: `TestFacadeResolutionPresenceUsesDynamicEntryShape`,
the engine resolution/provenance/default regressions, and the integrated checks
recorded in [implementation.md](implementation.md).
recorded at `07e4ae5:docs/roadmap/implementation.md`.
Relevant code:
@@ -86,8 +87,8 @@ documented treatment of invalid schema paths.
## 2. Resolution can transfer explicitness to a different semantic path
Priority: P2. Status: resolved. Evidence: the engine resolution/metadata/provenance
regressions, the full engine suite, and the integrated checks recorded in
[implementation.md](implementation.md).
regressions, the full engine suite, and the integrated checks recorded at
`07e4ae5:docs/roadmap/implementation.md`.
Relevant code: `applyResolutionMetadata`, `applyResolutionFieldOrigins`, and
`refreshResolutionFields` in
@@ -129,8 +130,8 @@ repair this publication path.
Priority: P2. Status: resolved. Evidence: `TestPublicHistoryUsesResolutionShapeAttribution`,
`TestPublicHistoricalPathsEnumerateContextualShapes`, shared history-selection
and explanation regressions, and the integrated checks recorded in
[implementation.md](implementation.md).
and explanation regressions, and the integrated checks recorded at
`07e4ae5:docs/roadmap/implementation.md`.
Relevant code:
@@ -172,8 +173,8 @@ and compare metadata history with explanation.
## 4. Diagnostic canonicalization breaks composition claimant ordering
Priority: P3. Status: resolved. Evidence: `TestFacadeCompositionConflictKeepsClaimantOrder`,
the engine diagnostic-order regression, and the integrated checks recorded in
[implementation.md](implementation.md).
the engine diagnostic-order regression, and the integrated checks recorded at
`07e4ae5:docs/roadmap/implementation.md`.
Relevant code: `compositionConflictDiagnostic` in
[compose.go](../../internal/engine/compose.go) and `canonicalDiagnostics` in

View File

@@ -5,7 +5,8 @@ Algorithmic follow-up: `91769e9` (unchanged production code).
Comparison baseline: `0dd16aa8a935645ae2847d32edd86461dc4618f0`
(the planning commit, before the implementation sprint).
Scope: the completed [implementation plan](implementation.md) and
Scope: the completed implementation plan at
`07e4ae5:docs/roadmap/implementation.md` and
[interface remediation roadmap](interface-remediation.md). This report records
remaining defects and newly introduced scalability problems; it does not change
the selected architecture or public contracts. All eight findings are complete;