Skip to main content

Module select

Module select 

Source
Expand description

Which of the repository’s objects a request reaches, and by which declared path.

§Nothing here discovers anything

Selection is a walk of two values the process already holds: the index, and the composed graph derived from it. The index was built once when the process loaded; the graph is crate::graph::COMPOSED, the repository’s own dependency graph, in which every typed reference the layer declares is already resolved to an edge. So there is no second relation table here, no glob, no read of a file and no walk of the working tree — which is what lets a request be answered inside a handler rather than at load time. The precedent and the reason are crate::plan’s: “App::load has a stated budget and 200 project records have no business inside it.”

§The traversal policy is the only thing this module decides

The graph says which things are related and how; it does not say which of those relations carry context. EDGES is that decision, and it is small on purpose: a weight per direction for each edge kind that carries context, and REFUSED for the kinds the compiler will not follow at all. is_a is refused because every object of a kind hangs off one node and following it would select the whole layer; composes and projects are refused because they describe this executable’s own wiring rather than the repository being worked on. policy projects the table so that a caller can read the decision instead of inferring it from the answer.

The two tables are complementary and not overlapping, and that is the invariant worth seeing: a refusal is an edge kind’s absence from EDGES, so edge_policy answering None is the refusal rather than a weight of zero standing for one. There is therefore no way to be in both tables, and no way to be followed at weight nothing.

use majordomus_cli::devcontext::edge_policy;
use majordomus_cli::devcontext::select::{EDGES, REFUSED};

// everything in the table is followed, in at least one direction, at a real weight
for e in EDGES {
    assert!(edge_policy(e.kind).is_some(), "{} is in the table", e.kind);
    assert!(e.forward > 0.0 || e.reverse > 0.0, "{} is followed at nothing", e.kind);
}

// and a refused kind is absent from it, with the reason the report prints
let refused: Vec<&str> = REFUSED.iter().map(|(kind, _)| *kind).collect();
assert_eq!(refused, ["is_a", "composes", "projects"]);
for (kind, why) in REFUSED {
    assert!(edge_policy(kind).is_none(), "{kind} is both followed and refused");
    assert!(!why.is_empty(), "{kind} is refused and does not say why");
}

Structs§

Candidate
One thing the compiler reached, before any budget was spent on it. The compiler folds every path that reached the same identifier into one of these, which is where deduplication happens: the Candidate is the unit, and discovered_by is the evidence of how many ways there were to find it.
EdgePolicy
Which way an edge is worth following, and what it means in each direction.
Request
What the walk was asked to start from and how far it may go.
Selection
The candidates a request reaches, and everything the walk learned on the way.

Constants§

EDGES
Which of the composed graph’s edges carry context, and how strongly.
REFUSED
The edges the compiler refuses to follow, and why. Read by devcontext.policy so that the refusal is inspectable state rather than an absence a reader has to notice.

Functions§

edge_policy
The policy for one edge kind, or None when the compiler refuses to follow it.
intent_terms
The words of a free-text intent, lowercased, three characters or more, deduplicated.
select
Reach every candidate the request implies: the seeds, the graph around them, the paths they declare, the governance the layer applies, the session that ran before, and — when the request gave an intent — what its words match.
tier_for_kind
Which tier an object of this kind is spent from, once it is not a seed.
version_of
The version or date an object states about itself, for the answer’s version field.