diff --git a/docs/roadmap/imports.md b/docs/roadmap/imports.md index 139a5aa..8d618e9 100644 --- a/docs/roadmap/imports.md +++ b/docs/roadmap/imports.md @@ -123,7 +123,7 @@ interfaces, without adopting all their spellings, defaults, or matching modes. OD-1 (recursion default), OD-2 (matching and selector expressiveness), OD-3 (directive validation), OD-4 (discovery boundaries and cycles), OD-5 (policy -precedence), and OD-6 (absent-import evidence) are settled in the sections below. +precedence), and OD-6 (no-selection evidence) are settled in the sections below. Supplying `depth` requires effective recursion to be enabled, including when enabled through an application default. This supersedes the earlier direction to accept but ignore depth when recursion is disabled. @@ -263,6 +263,12 @@ preserve each resolver's domain-specific admissibility and combination rules. Recursion changes which directories are visited; it does not change what `*` means. A nonrecursive search considers only files directly inside `dir`. +Filename filters use the candidate name supplied by the declaration or +encountered during discovery, not the canonical symlink target's basename. +For example, a symlink named `welcome.draft.yaml` matches +`exclude: '*.draft.yaml'` even if its target is named `welcome.yaml`. This +selection rule does not change canonical source identity or containment checks. + **OD-2: settled.** Use the existing case-sensitive Go `path.Match` wildcard grammar for filename filters. When neither the declaration nor the application supplies `pattern`, select all filenames, with no implicit extension restriction. @@ -305,6 +311,14 @@ existing repeated-source and alias checks still apply to distinct inclusion routes. In particular, it does not authorize silently merging separate alias paths to an imported source. +For declaration-local deduplication, identify a candidate by its normalized path +within its source namespace, before resolving symlinks. Compare paths relative +to the same namespace rather than relative to each search root. Overlapping +searches that encounter `prompts/welcome.yaml` therefore select it once, while +distinct symlink paths remain distinct candidates subject to the existing +canonical-source repeat checks. This candidate identity is separate from the +canonical identity used when accepting sources. + For `path`, `required: true` requires every listed file to be present. For `dir`, it requires at least one selected file across the complete union after exclusions; it does not require a match per directory, pattern, or pair. A @@ -333,6 +347,29 @@ Excluding a candidate is not permission to suppress discovery, containment, or resource-limit errors. Exclusions are local to the declaration; they do not prohibit another declaration from explicitly selecting the same filename. +### Resource Accounting + +Retain the existing resource limits, with an explicit adjustment to candidate +accounting for the new selection operations: + +- Every examined directory entry consumes the discovery visit budget, including + nonmatches and excluded entries. A small selected set does not authorize an + unbounded scan. +- Check distinct selected candidates against the remaining source allowance + after declaration-local deduplication and exclusions. Overlapping patterns + and search roots do not charge the same selected candidate more than once + within a declaration; excluded candidates do not consume source allowance. +- Excluded files are not read for content and consume no content-reading + allowance. Existing byte limits continue to govern selected sources. + +The current glob implementation checks candidate counts against the remaining +source allowance during expansion. Update that accounting to use the filtered, +deduplicated selection; do not reject an otherwise valid search solely because +its positive matches exceed that allowance before exclusions are applied. +Discovery limits still apply throughout the search. This is not global source +deduplication and does not suppress repeated-source errors across declarations +or distinct aliases. + ### Recursive Discovery And Depth Limits Enable recursion explicitly or through an application default for recursive @@ -368,12 +405,10 @@ default enables recursion, but invalid with the library default. Explicit supplied depth invalid. Depth must also have the valid type and range defined under directive validation; enabling recursion does not excuse malformed depth. -Recursive discovery must fit the existing filesystem containment, -repeated-source, and load-budget -contracts rather than silently changing them. In particular, examined entries, -including nonmatches, still consume the visit budget; a small number of matches -does not authorize an unbounded filesystem scan. This is an existing ConfigKit -constraint, not a new Ansible-derived decision. +Recursive discovery must retain the existing filesystem containment and +repeated-source contracts and follow the resource accounting defined above. +The discovery visit budget remains separate from the caller-selected depth +bound and still applies to unlimited-depth searches. ### Symlinks And Hidden Entries @@ -589,18 +624,29 @@ add options that override explicit declarations as part of this work without a separate concrete requirement and scope decision. The fields' applicability to each selector is defined under directive validation. -## Evidence For Absent Optional Imports +## Evidence For Optional Declarations With No Selection **OD-6: settled.** Record minimal structured inspection evidence when an optional declaration selects nothing: its declaring source/location, selector, -and absent outcome. Emit no warning by default and do not fabricate a +and no-selection outcome. Emit no warning by default and do not fabricate a loaded-source record. This keeps optional contributions quiet during ordinary use while allowing applications to explain omissions during troubleshooting. +No selection does not necessarily mean a source was missing. It may result from +missing sources or no positive matches, an explicit empty list, or exclusions +removing every candidate. The inspection record must not describe deliberate +exclusion or an empty list as missing files. + +This evidence is scoped to the whole declaration. An optional `path` list with +one selected file and one missing file does not produce this no-selection +record. Per-entry evidence for partial omissions is outside this feature's +scope; no additional exclusion audit is required. + Decide the exact inspection record shape during implementation planning, reusing existing structures where appropriate and retaining existing inspection contracts. Include ownership tests for the new evidence. This addition does -not require applications to reconstruct absent-import provenance themselves. +not require applications to reconstruct declaration-level no-selection evidence +themselves. ## Release Boundary