RunnerProvider
Methods
Section titled “Methods”collect()
Section titled “collect()”collect(
ctx,facts):Promise<ProviderResult>
Find the runner and enumerate its tasks.
Returns status: "absent" when the runner is not present — that is a
value, not an error, and not a separate lifecycle phase. Providers are
expected to bail cheaply: check the marker file first, before any real
work.
facts is the AspectFacts catalog collect() (collect.ts) computes
for this provider — manifest presence and content, already parsed, and
scoped to the one manifest kind this provider’s own id names (so its
cache fingerprint stays exact, see collect.ts’s own
ASPECT_FACTS_CONSUMERS). A provider whose job is manifest
presence/content (cargo, node-scripts, just, mise, make) reads it
instead of calling ctx.files()/ctx.readJson() itself; one that needs
neither (an exec provider answering from a live tool query, e.g. moon)
can ignore the parameter entirely — TypeScript accepts a collect(ctx)
implementation here since every caller still supplies both arguments.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
ctx | ProviderContext |
facts | AspectCatalog |
Returns
Section titled “Returns”Promise<ProviderResult>
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
binary? | string | The binary this runner’s tasks execute through, e.g. "moon", "just". A static declaration, like brand — the provider only NAMES it; it never reports presence itself. collect() fills RunnerReport.tool by running ctx.which() on this name, so a provider cannot lie about whether its tool is installed. Omitted by a provider whose binary is resolved per-directory rather than fixed (node-scripts, python) — a single static name would be wrong for those. |
brand? | RunnerBrand | Visual identity, copied onto the RunnerReport. Optional and stays that way: a provider is complete without one, and no consumer may require it — the value is polish for UIs, not part of the detection contract. |
chain | ChainSegment[] | What each position of this runner’s Task.path means. |
id | string | Stable id; becomes Task.runner and path[0]. |
kind | ProviderKind | - |
watch? | string[] | Basenames whose contents decide whether a cached result is still good. Only needed when the tool merges files this provider never reads. A parse provider needs none: every read it makes goes through ctx, so recording what it touched already covers exactly what it read. An exec provider does need them, because it reads only its markers while its TOOL merges files it never opens — moon’s per-project moon.yml, mise’s nested mise.toml, a newly added *.sbt. Basenames only, in the same pattern language ctx.files() speaks: an exact basename, or *suffix matched against the basename. Not a path glob. One pattern language shared with discovery is worth more than exact invalidation for a rare edit, and the cost is stated rather than hidden — a directory whose contents matter but whose filenames are not distinctive is simply not covered. Deliberately the ONLY cache-related field on this contract. There is no slow: slowness is MEASURED per repository, and a static default would only ever apply on the very first run, when there is no cached answer to be stale about. No TTL or invalidation knob either — kind already separates the exec providers, whose fingerprint cannot see their tool’s merge inputs and which therefore need the max-age backstop, from the parse providers, whose fingerprint is exact. |