Adopt shared dependency-ready ordering for imports and inheritance
This commit is contained in:
@@ -46,9 +46,16 @@ Glob matching uses slash-based Go `path.Match` syntax. Recursive `**` syntax is
|
|||||||
not supported; authors can match particular depths with patterns such as
|
not supported; authors can match particular depths with patterns such as
|
||||||
`prompts/*.yaml` and `prompts/*/*.yaml`.
|
`prompts/*.yaml` and `prompts/*/*.yaml`.
|
||||||
|
|
||||||
The proposed changes concern naming, discovery, and absence handling. Import
|
Current imports expand depth-first in declaration order, with each ordinary
|
||||||
destinations, composition, precedence, and resource identity remain separate
|
source contributing its body before its imports. The existing
|
||||||
concerns.
|
[sibling inheritance resolver](../config.md#sibling-inheritance) instead follows
|
||||||
|
dependency chains before resolving dependents, using sorted sibling names and
|
||||||
|
an explicit stack. Neither implements the shared ordering selected below.
|
||||||
|
|
||||||
|
The proposed changes concern naming, discovery, absence handling, and uniform
|
||||||
|
dependency ordering for imports and `extends`. Import destinations, strict
|
||||||
|
composition, inheritance overlay semantics, tier precedence, and resource
|
||||||
|
identity retain their distinct roles.
|
||||||
|
|
||||||
## Proposed Import Vocabulary
|
## Proposed Import Vocabulary
|
||||||
|
|
||||||
@@ -107,6 +114,9 @@ interfaces, without adopting all their spellings, defaults, or matching modes.
|
|||||||
and filesystem contracts remain in force.
|
and filesystem contracts remain in force.
|
||||||
- **Include hidden entries by default, with an opt-out.** Provide `hidden: false`
|
- **Include hidden entries by default, with an opt-out.** Provide `hidden: false`
|
||||||
to exclude hidden files and prune hidden directories from discovery.
|
to exclude hidden files and prune hidden directories from discovery.
|
||||||
|
- **One dependency-ordering algorithm for imports and `extends`.** Both use the
|
||||||
|
shared dependency-ready scheduler defined below. This is settled independently
|
||||||
|
of the existing implementations and includes refactoring both resolvers.
|
||||||
|
|
||||||
The defaults and availability of these controls are settled. Their exact scope
|
The defaults and availability of these controls are settled. Their exact scope
|
||||||
at explicitly named roots, the definition of hidden names across filesystems,
|
at explicitly named roots, the definition of hidden names across filesystems,
|
||||||
@@ -158,6 +168,91 @@ The accepted `recursive` spelling is retained. The formerly tentative
|
|||||||
`max_depth` spelling becomes `depth`. Resource budgets remain separate from
|
`max_depth` spelling becomes `depth`. Resource budgets remain separate from
|
||||||
depth, and the current limits still apply to an unlimited-depth search.
|
depth, and the current limits still apply to an unlimited-depth search.
|
||||||
|
|
||||||
|
## Shared Dependency-Ready Ordering
|
||||||
|
|
||||||
|
**Status: settled for imports and `extends`; not yet implemented.** Use
|
||||||
|
deterministic dependency-ready ordering: Kahn's topological-sort algorithm with
|
||||||
|
a min-heap of eligible nodes. Both resolvers must use the same algorithm in the
|
||||||
|
same way, through one shared internal scheduling implementation, common
|
||||||
|
tie-breaking rules, and common cycle-path logic.
|
||||||
|
|
||||||
|
### Scheduling Rule
|
||||||
|
|
||||||
|
A dependency edge means that the dependent cannot complete until its dependency
|
||||||
|
has completed. For each dependency graph:
|
||||||
|
|
||||||
|
1. Count each node's outstanding dependencies and identify initially eligible
|
||||||
|
nodes: those with none.
|
||||||
|
2. Choose the eligible node with the smallest stable ordering key.
|
||||||
|
3. Append it to the schedule, decrement its dependents' outstanding counts, and
|
||||||
|
immediately make newly eligible nodes available for the next selection.
|
||||||
|
4. Continue until all nodes are scheduled. If unfinished nodes remain with no
|
||||||
|
eligible node, reject the graph and identify an actual dependency cycle.
|
||||||
|
|
||||||
|
Use stable source or definition identities to construct ordering keys, with
|
||||||
|
the same deterministic comparison rule in both resolvers. Map iteration order
|
||||||
|
and discovery-assigned source IDs must not supply the tie-breaker. Specify key
|
||||||
|
construction for source namespaces and logical definition paths during
|
||||||
|
implementation planning; it must distinguish nodes within each scheduled graph.
|
||||||
|
|
||||||
|
Construct and validate a complete schedule for the available graph before
|
||||||
|
applying its resolution operations. A blocked dependent is not necessarily a
|
||||||
|
cycle member: diagnostics should identify the actual cycle using shared,
|
||||||
|
deterministic cycle-path logic. Source discovery and parsing may already have
|
||||||
|
occurred; this rule is not a promise to avoid reading invalid configurations.
|
||||||
|
|
||||||
|
### Scope And Integration
|
||||||
|
|
||||||
|
Discovery and resolution are separate operations. An importing source must be
|
||||||
|
read to discover its imports, but its contribution need not be assembled first.
|
||||||
|
Discovery order is not a substitute for the selected resolution schedule.
|
||||||
|
|
||||||
|
Both resolvers construct dependency graphs and apply resolver-specific operations
|
||||||
|
through the shared scheduler. Imports retain strict composition; `extends`
|
||||||
|
retains inheritance overlay behavior. Scheduling does not authorize replacement
|
||||||
|
within a strict composition tier or change precedence between tiers. Shared
|
||||||
|
dependencies can be scheduled once where valid; this does not relax the existing
|
||||||
|
prohibition on repeated source inclusion for imports.
|
||||||
|
|
||||||
|
Preserve item-local helper scopes and enclosing-before-nested inheritance
|
||||||
|
requirements. An imported item completes its helper contributions before being
|
||||||
|
placed as an item. Enclosing inheritance establishes the context in which nested
|
||||||
|
relationships are discovered and resolved. Use the same scheduler at those
|
||||||
|
scope boundaries, with the actual prerequisites represented; do not flatten raw
|
||||||
|
files or mappings in a way that loses their scope. Inheritance still resolves
|
||||||
|
after source assembly and precedence have established the effective document.
|
||||||
|
|
||||||
|
The integration must account for resulting sequence positions, provenance,
|
||||||
|
history, and diagnostic ordering. It must distinguish source acquisition records
|
||||||
|
from assembly order rather than assuming they are the same. Review both
|
||||||
|
resolvers' contracts and behavioral tests when implementing the new schedule;
|
||||||
|
preserving the old traversal is not a design objective.
|
||||||
|
|
||||||
|
### Rationale And Validation
|
||||||
|
|
||||||
|
Dependency-ready ordering selects the smallest currently eligible node without
|
||||||
|
adding branch preference, batch barriers, or distance-from-root priority. With
|
||||||
|
a fixed total ordering key, it gives the lexicographically smallest valid
|
||||||
|
dependency-first schedule. It can interleave independent branches; branch
|
||||||
|
contiguity is not part of the chosen ordering contract.
|
||||||
|
|
||||||
|
The comparison considered deterministic depth-first postorder, dependency
|
||||||
|
rounds, and descending longest-path depth as well. All can satisfy dependency
|
||||||
|
correctness, but their additional ordering policies did not justify choosing
|
||||||
|
them over the uniform eligibility rule. This decision gives no preference to
|
||||||
|
the existing implementation or to minimizing pre-1.0 refactoring.
|
||||||
|
|
||||||
|
The scheduler requires O(E + V log V) time and O(V + E) memory for V nodes and
|
||||||
|
E dependency edges, assuming constant-time key comparisons. Source access,
|
||||||
|
parsing, merging, and provenance work are separate costs.
|
||||||
|
|
||||||
|
Validate independent branches, unequal chains, branches with multiple
|
||||||
|
dependencies, shared dependencies at equal and unequal depths, cycles with
|
||||||
|
blocked non-cycle dependents, and nested scopes. Equivalent valid graphs and
|
||||||
|
ordering keys must produce identical schedules through the import and
|
||||||
|
inheritance integrations. Verify independence from graph insertion order and
|
||||||
|
preserve each resolver's domain-specific admissibility and combination rules.
|
||||||
|
|
||||||
## Discovery Semantics
|
## Discovery Semantics
|
||||||
|
|
||||||
### Filename Matching
|
### Filename Matching
|
||||||
@@ -355,7 +450,8 @@ scaffolding. No promise is made to preserve every old declaration or use case.
|
|||||||
|
|
||||||
The recommendations below are not settled decisions. The new principles resolve
|
The recommendations below are not settled decisions. The new principles resolve
|
||||||
transition support, omitted filename filtering, and the defaults and opt-out
|
transition support, omitted filename filtering, and the defaults and opt-out
|
||||||
availability for symlinks and hidden entries. Seven decision areas remain;
|
availability for symlinks and hidden entries. Shared dependency-ready ordering
|
||||||
|
for imports and `extends` is also settled. Six decision areas remain;
|
||||||
closely related validation details are grouped together without treating them
|
closely related validation details are grouped together without treating them
|
||||||
as implicitly approved. Each has at least one viable alternative.
|
as implicitly approved. Each has at least one viable alternative.
|
||||||
|
|
||||||
@@ -426,8 +522,8 @@ That eases generated configuration but can turn an erroneous bound into a wider
|
|||||||
search or make a direct-file import appear recursive. These relaxations can be
|
search or make a direct-file import appear recursive. These relaxations can be
|
||||||
chosen independently; they do not require accepting ambiguous selectors.
|
chosen independently; they do not require accepting ambiguous selectors.
|
||||||
Another viable selector shape is to allow multiple selectors as an explicit
|
Another viable selector shape is to allow multiple selectors as an explicit
|
||||||
union, but it needs ordering and overlap semantics that one-selector declarations
|
union, but it needs rules for constructing the graph and handling overlaps that
|
||||||
avoid.
|
one-selector declarations avoid.
|
||||||
|
|
||||||
### 4. Discovery Control Boundaries And Cycles
|
### 4. Discovery Control Boundaries And Cycles
|
||||||
|
|
||||||
@@ -467,23 +563,7 @@ but can hide a layout mistake and needs clearly defined inspection evidence.
|
|||||||
It would not justify suppressing repeated-source errors for files actually
|
It would not justify suppressing repeated-source errors for files actually
|
||||||
selected through distinct routes.
|
selected through distinct routes.
|
||||||
|
|
||||||
### 5. Match Ordering
|
### 5. Application And Operator Policy Precedence
|
||||||
|
|
||||||
**Why still open:** Inclusion defaults do not determine order. `include_vars`
|
|
||||||
sorts directories and filenames; `win_find` documents path-sorted results;
|
|
||||||
POSIX `find` does not promise the same global ordering.
|
|
||||||
|
|
||||||
**Recommendation:** Sort selected slash-relative paths lexicographically within
|
|
||||||
each declaration, then use existing depth-first import expansion. This provides
|
|
||||||
one familiar order for discovery, sequence assembly, and diagnostics. It
|
|
||||||
requires collecting bounded candidates before expansion.
|
|
||||||
|
|
||||||
**Alternative:** Load direct files first, then visit sorted subdirectories
|
|
||||||
recursively. This offers directory-oriented traversal and can begin loading
|
|
||||||
sooner, but gives different sequence item positions. Neither choice grants
|
|
||||||
replacement precedence within strict composition.
|
|
||||||
|
|
||||||
### 6. Application And Operator Policy Precedence
|
|
||||||
|
|
||||||
**Why still open:** The library defaults and authored opt-outs are settled.
|
**Why still open:** The library defaults and authored opt-outs are settled.
|
||||||
Whether consumers can set different defaults or enforce restrictions over
|
Whether consumers can set different defaults or enforce restrictions over
|
||||||
@@ -505,7 +585,7 @@ needs clear conflict diagnostics and scope, particularly for explicit sources.
|
|||||||
A smaller alternative is declaration-level controls only initially: simpler
|
A smaller alternative is declaration-level controls only initially: simpler
|
||||||
API, but consumers cannot choose common defaults without changing declarations.
|
API, but consumers cannot choose common defaults without changing declarations.
|
||||||
|
|
||||||
### 7. Evidence For Absent Optional Imports
|
### 6. Evidence For Absent Optional Imports
|
||||||
|
|
||||||
**Why still open:** Permitting absence does not settle how it should be exposed
|
**Why still open:** Permitting absence does not settle how it should be exposed
|
||||||
for inspection. Ansible's file lookup, variable loader, and find modules return
|
for inspection. Ansible's file lookup, variable loader, and find modules return
|
||||||
|
|||||||
Reference in New Issue
Block a user