# Pre-v1 Public API Cleanup Roadmap Status: target settled; implementation has not begun. Planning baseline: `7548fa1` (accepted decisions, with the v0.10.2 implementation and subsequent interface/history remediation already present). This roadmap owns the targeted end state, required changes, and completion criteria. The [implementation plan](implementation.md) owns concrete edits, sequential stages, validation commands, and progress tracking. The [preliminary review](review.md) retains the API catalog and original proposals; the [additional review](audit.md) retains its evidence and alternatives. Proposal IDs below provide traceability. ## Purpose And Scope Make the public API clearer before v1.0.0 through the accepted renames, narrower recording methods, redundant-state removal, and direct source lookups. Preserve existing configuration behavior except for the selected public replacements, removals, and observable string changes. The root package remains the supported facade; private engine structure can evolve within that boundary. This is a breaking pre-v1 cleanup, not a compatibility-shim rollout. The renamed or replaced public declarations give way to their selected forms. Existing Go declaration comments and the [configuration contract](../config.md) continue to own behavior that this roadmap does not change. No redesign of loading, composition, history ownership, or YAML syntax is selected. ## Current Baseline - [lifecycle.go](../../lifecycle.go), [records.go](../../records.go), [discovery.go](../../discovery.go), and [secrets.go](../../secrets.go) expose the old declarations listed below. There are corresponding engine declarations and facade conversions, including [conversion.go](../../conversion.go). - `Resolution.Record` accepts the inspection `ChangeKind` type, then rejects kinds other than derived-default and normalization during loading. The generic assignment helpers already select their own supported intent. - `ImportSelection` represents only empty selections, but still carries a single-valued outcome. Source records expose version and destination evidence through names that do not fully describe that evidence. - `Resolution.Source(id)` already performs passive, detached lookup during a callback. `Result` and `LoadError` expose ordered `Sources()` lists but no direct lookup. Failure records contain only the evidence available at failure. - The shared history implementation and its admission boundary are already in place. Provenance still uses `"base"`, and retained-history failures still use `"explain.limit_exceeded"`. - Current production-reference checks find only declarations for `CodeOptionsUnavailable`, and the kind guard in `resolutionState.addRecord` produces `CodeResolveInvalidKind`. Their removal requires the checks described below, rather than inventing a new supported use for either code. ## Targeted Public API The following table is the complete accepted change set. Unless stated otherwise, renames retain the existing signature/type and behavior. Internal names are not part of this public replacement list. | Review item | Decision | | --- | --- | | D1 | Rename `Resolution.InputInfo` to `EntryInfo`, describing the fixed resolution-entry metadata view, including retained defaults and CLI assignments. Preserve its return type and lookup behavior. | | D2 | Rename `Definition.Secret` to `Sensitive`. Preserve classification behavior, the `configkit:"secret"` tag, and typed `Secret` references. | | D3 | Rename `SourceVersionModeDefault` to `SourceVersionModeMainOnly`, `SourceVersionCheck` to `SourceVersionEvidence`, and `SourceInfo.VersionCheck` to `VersionEvidence`. Retain `SourceVersionModeIfPresent` and `SourceVersionModeRequired`. | | D4 | Rename `ImportSelection` to `EmptyImportSelection` and `SourceInfo.ImportSelections` to `EmptyImportSelections`. Retain path, location, and selector; remove `Outcome`, `ImportSelectionOutcome`, and `ImportSelectionNone`. | | D5 | Rename `SourceInfo.DestinationUnresolved` to `DestinationIsFallback`, preserving its existing meaning and destination coordinates. | | D6 (including N4) | Replace `Resolution.Record` with the two intent-specific methods below and remove `CodeResolveInvalidKind` once its public trigger is eliminated. Retain `ChangeKind` and its inspection constants. | | D7 | Rename `LoadSecretsDir` to `LoadSecretsIntoEnvironment`, making process-environment mutation explicit. Preserve its signature apart from the name, report-plus-error behavior, and existing bootstrap semantics. | | D8 | Remove `CodeOptionsUnavailable` after confirming there is no intentional supported role. Do not introduce a failure merely to give the code a producer; a concrete reason to retain it should be brought back for discussion. | | A1 (including N5) | Add `Result.Source(id)` and `LoadError.Source(id)` for direct lookup of source evidence on successful and failed loads, alongside their existing `Sources()` enumeration. Keep source evidence distinct from passive resource access through `SourceContext(id)`. | | N1 | Rename `Paths(paths ...string) Search` to `SearchPaths(paths ...string) Search`, replacing the old name outright. Preserve literal file candidates, ordering, deferred acquisition, and selection/failure behavior. Leave semantic `Path` APIs and `Searches` unchanged. | | N2 | Replace `LayerBase = "base"` with `LayerMain = "main"`, without a compatibility alias. Update Go references and affected string comparisons, serialization, and rendered labels. Preserve the existing main-tier category, imported contributions' owning tiers, precedence, and acquisition order. | | N3 | Replace `CodeExplainLimitExceeded = "explain.limit_exceeded"` with `CodeHistoryLimitExceeded = "history.limit_exceeded"`, without a compatibility alias. Update Go references and affected diagnostic-code consumers. Preserve the existing quota, retained-node accounting, failure conditions, diagnostic locations, and admission timing before effective secret lookup and application validation. | | N6 | Rename `ImportDefaults.Follow` to `FollowSymlinks` and `ImportDefaults.Hidden` to `IncludeHidden`, replacing the old fields outright. Preserve `*bool` types, nil defaulting, explicit true/false, declaration overrides, traversal behavior, and search scope. Keep YAML keys `follow` and `hidden`, and Go fields `Required`, `Recursive`, and `Pattern`, unchanged. | ### Recording Methods (D6) The selected signatures are: ```go func (r *Resolution) RecordDerivedDefault(path Path, reason string, dependencies ...Path) func (r *Resolution) RecordNormalization(path Path, reason string, dependencies ...Path) ``` Both record intent for work already performed by application code. They do not assign values; `RecordDerivedDefault` does not check absence or suppress work on explicit input. Keep `Default` and `Normalize` as the assignment-and-recording helpers. Preserve path/reason/dependency validation, container coverage, coalescing, net-change auditing, and callback lifetime. Replace the old `Record` method outright rather than retain parallel public recording interfaces. Include N4's diagnostic cleanup in this change: confirm that no supported public input can still produce `resolve.invalid_kind`, then remove `CodeResolveInvalidKind` without a replacement or compatibility alias. Preserve other recording diagnostics. Internal defensive checks remain an implementation choice. If another legitimate public trigger is found, bring it back for discussion rather than silently reclassifying the failure. ### Version Policy And Evidence (D3) `MainOnly` remains the zero mode and does not enable checking without a configured version rule. The broader modes retain their requirement for a usable rule. Document the modes together, preserving these distinctions: - `MainOnly` retains the existing main-version check at its effective path. Broader modes inspect each participating document in source-local coordinates before placement and composition. - `IfPresent` passes an absent main declaration to the application checker, while absent non-main declarations skip the checker. `Required` rejects missing declarations in participating documents. Existing `NoSource` behavior remains. - Version evidence describes observed declarations or absence, not checker invocation or acceptance. Preserve nil-versus-observed-absence meaning, explicit null, locations, consumption, and redaction. No acceptance flag is added. ### Direct Source Lookup (A1) ```go func (r *Result[T]) Source(id string) (SourceInfo, bool) func (e *LoadError) Source(id string) (SourceInfo, bool) ``` Look up an acquired source by its load-local ID, returning the same information represented in `Sources()` as a detached record. Empty or unknown IDs return false. The query performs no source acquisition, filesystem access, or credential lookup. Reuse existing source lookup and conversion machinery where practical; no public registry, indexing strategy, or constant-time guarantee is required. The failed-load lookup returns records from `LoadError.Sources()`'s partial inventory and returns false for nil or zero-valued errors as well. Preserve existing failed-load redaction and the evidence available at failure, including incomplete placement information. Lookup neither completes acquisition nor promises a record for every attempted source. This incorporates N5 into A1. ## Work Required From The Baseline ### Public Declarations And Facade Conversions Update the public declarations, comments, wrappers, and conversions as a coherent surface. Useful existing owners are: | Area | Baseline owners and required work | | --- | --- | | Entry metadata, sensitivity, version mode, and import defaults | [lifecycle.go](../../lifecycle.go), [layered.go](../../layered.go), and [conversion.go](../../conversion.go): update both ordinary and layered loading paths, callback wrappers, and definition/default conversions. | | Source evidence | [records.go](../../records.go) and [conversion.go](../../conversion.go): rename records/fields and remove the empty-selection outcome. Cover source records returned through results, callbacks, and load errors. | | Recording intents | [lifecycle.go](../../lifecycle.go) and [engine resolution](../../internal/engine/resolution.go): provide the two methods, route them to the existing recording/auditing machinery, and remove the public kind-selecting method. | | Discovery and bootstrap | [discovery.go](../../discovery.go) and [secrets.go](../../secrets.go): replace constructor/function names and migrate their callers without changing acquisition or environment mutation behavior. | | Provenance and diagnostic values | [records.go](../../records.go), [engine records](../../internal/engine/records.go), producers, conversions, and renderers: apply the selected labels and codes consistently. | | Direct lookup | [lifecycle.go](../../lifecycle.go), [diagnostic.go](../../diagnostic.go), and their engine collaborators: expose the existing retained source evidence through the new result/error methods. | Use explicit root/engine conversion as needed; no public aliases or engine types are needed to implement these replacements. Private naming and helper placement belong to implementation planning. Avoid unrelated internal renames merely to make every private identifier match the facade. Preserve distinctions that the new names clarify: - `EntryInfo` remains a fixed, detached entry-state lookup with its current unknown/invalid/shape-mismatch behavior. `IsExplicit` retains its own existing validation behavior; the rename does not unify those two query contracts. - `Sensitive` remains the classification predicate, separate from typed secret references. Existing tag/predicate/dependency classification and redaction still apply. - `DestinationIsFallback` still describes the nearest resolved enclosing container when the full destination is unavailable. It does not promise an item's exact coordinates or upgrade evidence retained at an earlier stage. - Empty-selection records keep their existing scope, order, and declaration-local coordinates. Removing `Outcome` does not create a complete import ledger. - `FollowSymlinks` and `IncludeHidden` retain pointer defaulting and load-preflight snapshot behavior. Do not mechanically rename YAML `follow` or `hidden` keys. ### Recording Entry Points And Obsolete Diagnostics Implement the two recording methods over the existing resolution lifecycle. Migrate manual-record callers according to the intent they currently supply; keep assignment helper calls as helpers. Tests of container coverage, overlapping records, dependencies, equal-valued intent, and net-change auditing continue to protect the same behavior through the new entry points. Complete the N4 check after replacing `Record`: trace supported recording routes, then remove the obsolete exported invalid-kind code if its public trigger is gone. Update tests of the removed input mechanism without weakening unrelated record validation. Do not introduce a different public diagnostic solely to represent an unreachable kind. For D8, confirm both producer references and any documented intentional role for `CodeOptionsUnavailable`, then remove the unused declaration and associated active documentation. A concrete supported role discovered during this check should be brought back for discussion. These are verification tasks for accepted removals, not permission to delete other diagnostics that happen to be uncommon. ### Direct Lookup And Source Evidence Implement the result and error methods against each receiver's retained source inventory. Reuse source-copying and facade-conversion helpers where practical so lookup and enumeration agree, including nested locations, version evidence, empty-selection evidence, and detached paths. Follow existing result-query nil/zero conventions; failed-load nil/zero behavior is specified above. Keep `Sources()` enumeration and `SourceContext(id)` responsibilities intact. Lookup must not repeat acquisition, finalize failure evidence, or change source IDs. A slice search or a suitable existing index can satisfy the contract; no new lookup complexity promise or shared lazy cache is selected. ### Observable Strings And Their Producers And Readers Replace the main-tier category's `"base"` spelling with `"main"` wherever that category crosses the public boundary or is rendered. Imported contributions keep their owning tier and ordinary source-location attribution. Other uses of the word "base", such as filesystem base directories, are unrelated. Change every retained-history-limit diagnostic producer and relevant reader to `"history.limit_exceeded"`, including inheritance and final load admission. Preserve the quota, accounting, and failure timing. This rename does not make history optional or add a new limit control. Review Go constant references and literal comparisons/expected output separately: compilation catches old symbols but not stale diagnostic or provenance strings. Other codes and layer values retain their existing meaning and spelling. ### Consumer Guidance And Migration Information Update declaration comments, applicable sections of [config.md](../config.md), the [consumer guide](../consumers/README.md), README examples, and maintained consumer code/fixtures under `examples/`. Use the new recording methods and source lookups in relevant existing examples without expanding unrelated workflows. Update internal documentation only where implemented ownership or terminology changes. Accepted ADR decisions do not need revision for this cleanup. Record the old-to-new Go names, removed outcome fields/codes, recording-call replacements, and the two observable string changes as migration information. Downstream applications may need to update literal comparisons and serialized expectations as well as Go references. Version-specific release notes and publication remain part of the normal [release process](../release.md); this roadmap does not select a release version or authorize publication. Keep revision-pinned review evidence and historical release records accurate for their original revisions. Old names in those records are not stale active API usage. Do not rewrite history or require external consumer migrations to claim the repository implementation is complete. ## Validation And Completion Follow the [testing policy](../policy/testing.md) and [development guide](../development.md#baseline-validation). Reuse existing behavioral tests for mechanical renames; new tests should protect the changed entry points and added lookups, rather than duplicate implementation details. - Check the root API exposes every selected replacement/addition and no obsolete public declarations from the accepted removals. Preserve root-owned type identity and the existing public/dependency boundary checks. Historical references and useful private implementation names do not invalidate this check. - Exercise both recording intents through the new public methods. Preserve helper assignment behavior, validation, recorded origins, and history under the existing resolution tests; update the old invalid-kind case when its input mechanism is removed. - Cover successful and failed source lookup against each receiver's enumeration, missing IDs, applicable nil/zero cases, detachment of nested evidence, and unchanged records after caller mutation. Reuse existing source/version/resource fixtures for redaction, partial failure evidence, and passive access behavior. Do not add source-completeness, performance, or concurrency guarantees. - Retain the existing entry-shape, sensitivity, version-mode, empty-selection, placement, import-default snapshot, discovery, and secrets-bootstrap coverage. In particular, Go field renames must leave YAML declarations and tri-state defaulting behavior intact. - Update relevant provenance and diagnostic assertions for the selected strings. Existing history-budget cases should continue to check rejection before secret lookup and application validation, using the new code and unchanged accounting. - Run the applicable focused checks during development and the everyday check for the integrated code changes. Apply existing race-check guidance if the implementation changes ownership/concurrency behavior. Validate documentation links and maintained examples. No benchmark campaign or additional release gate is introduced. Completion means all accepted proposals are implemented, the diagnostic-removal checks are resolved, maintained consumers and current documentation use the new surface, and applicable checks pass with behavior preserved except for the expressly selected changes. Update roadmap/review status with the actual evidence; passing the current baseline suite is not evidence of future implementation. No significant open design decision remains. D8's role check and D6/N4's public reachability check are implementation verification tasks; unexpected evidence of a legitimate public use should be discussed before changing that use. Private helper choices and lookup mechanics are selected in the implementation plan. Public path comparison (A2) remains deferred and outside this scope.