diff --git a/docs/roadmap/internal-boundaries.md b/docs/roadmap/internal-boundaries.md new file mode 100644 index 0000000..149e7d1 --- /dev/null +++ b/docs/roadmap/internal-boundaries.md @@ -0,0 +1,191 @@ +# Import Discovery And Facade Boundary Simplification + +Status: target defined; staged implementation planning pending. +Baseline: `80cf23e7102fca2c5d7c7621e75f930a1ef1ecad`. + +This roadmap brings together the two refactors deferred until after the audit +remediation sprint: glob entry preparation (**C03**) and facade-to-engine +transport simplification (**F07**). Their original motivation is retained in the +[glob](future.md#1-separate-glob-entry-preparation-from-traversal) and +[transport](future.md#2-simplify-redundant-facade-to-engine-transport) future-work +entries and the [consolidated audit](audit.md). + +The goal is clearer responsibility and ownership with fewer redundant internal +representations. Both changes preserve the public API and configuration model. +They are independent work areas within one maintenance effort, not a new loading +workflow. A subsequent implementation plan will own concrete edits, stages, +validation commands, and execution progress. + +## Baseline And Targeted End State + +The preceding sprint repaired directory-failure classification and shared link +dependency evaluation, clarified acquisition handoffs, and removed unused +placement bridges. Those changes provide the baseline; this work does not repeat +or redesign them. + +| Area | Current baseline | Target | +| --- | --- | --- | +| Glob discovery | `selectGlobImportCandidates` interleaves traversal and set operations with substantial per-entry preparation. | The selector coordinates discovery; a cohesive private operation prepares a wildcard-discovered entry. | +| Facade transport | Import defaults pass through root conversion, an exported engine transport record, an equivalent private engine record, and repeated snapshots. Placement construction also uses setter-style bridges. | Root-owned public records convert explicitly to one engine defaults representation, with straightforward engine option/input construction and identifiable ownership copies. | + +The [architecture policy](../policy/architecture.md), [configuration +contract](../config.md), and public declarations remain authoritative. [ADR +0006](../adr/0006-public-facade.md) continues to govern the facade boundary. These +refactors do not require a new architectural decision or changes to its accepted +decision. The [component overview](../internal/overview.md) and [import +internals](../internal/imports.md) own implemented structure. + +## Glob Entry Preparation + +### Target Responsibility Split + +In [glob.go](../../internal/engine/glob.go), the selector continues to own pattern +validation, component advancement, literal-segment handling, directory +enumeration and its accounting, candidate union and sorting, final target +validation, exclusions, and requiredness. + +A private glob-specific preparation operation owns the patterned branch's work +for one directory entry: matching and hidden-entry filtering, lexical/access path +construction, containment checks, target inspection and discovered-link policy, +intermediate-directory eligibility, host/native access-path selection, labels, +and candidate construction. Its result distinguishes a selected candidate, an +ordinary skip, and a diagnostic. It receives the facts needed for that entry +rather than mutating the selector's candidate set or surrounding traversal state. + +Use the existing filesystem access and link-resolution helpers. Directory +selection already has `prepareImportDirectoryEntry`; it remains a separate owner +because its recursion, matching, absence handling, and traversal state differ. +Share a smaller operation only where it actually expresses the same semantics +and reduces duplication. No common visitor or discovery strategy is needed for +this extraction. + +### Behavior To Preserve + +Preserve the current distinctions and processing order documented by +[explicit imports](../config.md#explicit-imports) and exercised by the selection +tests: + +- Literal components remain explicit selections; discovery filters apply at + their existing wildcard boundaries. Moving matching or hidden filtering after + filesystem inspection would change which errors are observable. +- Keep lexical candidate identity separate from resolved access identity. + Native source identity and relative imports retain namespace spelling; host + access retains its existing canonicalization and containment behavior. +- Keep discovered-link follow rules, intermediate-directory eligibility, + missing-target handling, and structured diagnostic sites/classifications. + Do not make glob and directory rules identical as a side effect of extraction. +- Preserve deterministic candidate and error order, union/deduplication, + directory-entry accounting, and the existing point of source admission. + Final selected-file validation remains before exclusions where it is today; + exclusions do not hide discovery or resource errors. +- Retain the preceding sprint's distinction between missing-on-open directories + and failures after opening, along with operation-local completed-link reuse. + +The intended benefit is that a maintainer can understand traversal separately +from entry eligibility and identity preparation. This is a readability change; +it does not select a different search algorithm or claim a speedup. + +## Facade-To-Engine Transport + +### Target Representations + +The root keeps its public `ImportDefaults`, `PlacementMode`, `Options`, `Input`, +and `LayeredOptions` types. Explicit conversions remain appropriate at this +boundary; consumers must not acquire engine type identity, fields, or methods. + +Inside the engine, consolidate the equivalent `ImportDefaults` transport and +private `importDefaults` records into one presence-aware input-defaults +representation. Carry that representation through the ordinary and layered +options, normalized request, and acquisition policy instead of translating the +same five fields between equivalent engine records. + +Keep `resolvedImportPolicy` distinct: it represents concrete per-declaration +choices, including selector-specific rules, rather than another copy of optional +load-wide input. Likewise, registration compilation and the normalized loading +request have real responsibilities and are not replacement targets. + +Make placement and defaults straightforward to construct on the existing engine +option/input records. Remove decorator-style bridges made unnecessary by that +construction surface. Exporting fields or types within `internal/engine` where +needed by the root converter does not make them part of ConfigKit's supported +public API. Keep explicit enum conversion and preserve unknown values until the +existing option validation can report them; conversion must not silently choose +a default or move validation into facade setters. + +### Ownership And Copying + +Make the actual mutable ownership boundaries identifiable. Public load calls +continue to snapshot pointed-to default booleans and the pattern slice before +source acquisition, as specified by the [public +declaration](../../lifecycle.go). Preserve omitted, explicit false, nil pattern, +and non-nil empty pattern as distinct inputs where they are distinct today. + +Review the entire handoff, not just the duplicate type definitions: root +conversion in [conversion.go](../../conversion.go), ordinary construction in +[lifecycle.go](../../lifecycle.go), layered construction in +[layered.go](../../layered.go), engine options and normalization, acquisition +policy construction, and declaration resolution in +[import_spec.go](../../internal/engine/import_spec.go). + +Remove snapshots that merely recopy already-owned read-only defaults as they +cross those private representations. Keep copies needed when establishing +independent mutable ownership, including any independently owned resolved +policy. The target is explainable ownership and less redundant work, not an exact +copy count or removal of copying throughout the library. Shared defaults within +one load can be read-only by implementation discipline; this creates no new +caller immutability or concurrency requirement. + +Preserve ordinary and layered option preflight before source reads and application +hooks, independent declaration overrides, transitive/underlay propagation, +selected-overlay behavior, destination normalization, and invalid-enum +diagnostics. Keep callback, source, path, secret, and returned-record conversions +whose ownership or domain meaning is not redundant transport. + +The intended benefit is fewer concepts, field mappings, and construction paths +to maintain. Reduced copying is useful but does not establish an end-to-end +performance guarantee. + +## Implementation And Documentation Work + +The later plan should identify the glob extraction boundary and map the defaults +and placement ownership handoffs against current callers before changing them. +The two refactors can be implemented and reviewed independently; neither needs +the other to land. Retire replaced private representations and helpers together +with their callers rather than adding a second production path. + +Update internal documentation when the resulting boundaries land. Public +declaration wording needs changes only if required to keep its existing +ownership description accurate; this effort does not select new public behavior. +Replace the corresponding C03/F07 candidate detail in `future.md` with a pointer +to the active work when the planning records are reorganized, avoiding parallel +target or progress inventories. Leave the unrelated future candidates alone. + +## Validation And Completion + +Follow the [testing policy](../policy/testing.md) and [development +guide](../development.md#baseline-validation). Reuse the existing glob selection, +directory/link failure, import-default, placement, public facade, and dependency +boundary coverage. Add a focused behavioral case only where a concrete +extraction or ownership risk lacks protection. + +For discovery, verify literal versus wildcard filters, host/native identity, +contained and escaping links, optional absence versus read/close failures, +ordering, exclusions, regular-file checks, and existing resource accounting. For +transport, verify nil/empty and explicit-false distinctions, mutation of caller +default storage after the load snapshot through a supported callback, invalid +options before input consumption, both loading APIs, and transitive/underlay +defaults. Existing conversion-focused tests may change with private construction; +preserve the useful ownership behavior rather than fossilizing a helper's shape. + +Completion requires an easier-to-follow selector, one engine input-defaults +representation, fewer redundant mapping/construction sites, justified remaining +copies, and preserved public behavior under the relevant checks. Review source +and ownership flow as well as passing tests; moving complexity into a helper or +renaming a duplicate record alone is insufficient. + +No benchmark campaign, complexity score, allocation threshold, exact filesystem +call trace, new resource limit, or additional release gate is required. This work +adds no dependencies, caches, background activity, or new consumer controls, and +does not reopen other audit findings or deferred performance experiments. Routine +helper signatures, names, and file placement belong to the implementation plan; +no significant product or architectural decision remains open for this scope.