Skip to content

Every runtime loads every module, so planning can call file and platform immediately #563

Open

Description

@David-Noble-at-work

Epic: #530

2.4-hermeticity-guarantees.md opens with the guarantee:

Graph planning must be hermetic: given the same inputs, it produces the same graph, on any machine, every
time.

Planning does not currently have that property, and the mechanism intended to give it is present but defeated
at every call site.

Every runtime is handed the whole registry

RuntimeEnvironmentSpec.WithModules selects which providers a starlarkbridge.Runtime exposes as immediate
Starlark globals. Its own doc comment (pkg/op/runtime_environment.go:843) shows the intended shape -- a
curated subset:

WithModules(op.ReceiverRegistry().ModuleByName("file"), op.ReceiverRegistry().ModuleByName("json")).

All three callers pass everything instead:

cmd/lore/lore/builder.go:111                WithModules(op.ReceiverRegistry().Modules()...)
cmd/devlore-test/devloretest/runner.go:266  WithModules(receiverRegistry.Modules()...)
cmd/star/star/application.go:80             WithModules(registry.Modules()...)

builder.go:111 is the planning environment -- the one whose own comment reads "One shared
[op.RuntimeEnvironment] backs the whole build".

What that exposes at plan time

Modules() returns only RoleModule providers, so the planned-only set (shell, git, pkg, encryption,
archive, service, appnet, elevator, flow, function, powershell) is genuinely absent from immediate scope. That
part works.

What every runtime does receive is {file, json, platform, regex, template, yaml, plan, ui}. Two of those are
machine-dependent:

  • file -- 2.4 names it directly: "Planning currently reads secondary artifacts through ambient filesystem
    access (RootReader delegates to live os.*). This violates hermeticity in two ways."
  • platform -- reading the host at plan time makes the graph depend on the machine that planned it, which
    is the property 2.4 exists to guarantee against.

So the violation is reachable from the authoring surface today, not pending.

The annotation cannot express the rule

+devlore:access=[planned|immediate|both] is a property of the provider. Hermeticity is a property of the
evaluation:

Provider In star While planning
file correct -- the utility should read files hermeticity violation
platform correct -- the utility should report the host hermeticity violation

One provider, two verdicts, decided by which runtime is asking. No per-provider annotation can say that, which
is why disciplined annotation use cannot deliver the guarantee -- and why adding a fourth annotation value would
repeat the mistake by encoding a context property on the provider.

Per-runtime module selection is the only mechanism that can state the rule, and it already exists. It is
simply never used: WithModules(registry.Modules()...) reads like a default and functions as an opt-out.

What a fix has to decide

  1. Which subset is hermetic. json, regex and template are pure. plan is the planning surface itself.
    file and platform are the violations. ui is the interesting one -- it prompts a human, so a plan
    that branches on an answer is machine- and moment-dependent in a different way, and whether that is permitted
    at plan time is a real question rather than an oversight.
  2. How the subset is expressed. A hand-maintained list in the planning path, or a derived property. Note
    that "derived from a new annotation" recreates the problem above.
  3. Whether star changes at all. It should not -- it is a utility, hermeticity is not its guarantee, and
    its call is correct as written. Only the planning path is wrong.
  4. What devlore-test's runner should do. It executes fixtures rather than planning packages, so it likely
    follows star rather than the planning path -- but that is a decision, since some fixtures build graphs.

How this was found

While asking why shell is annotated access=planned. The annotation turns out to be correct and deliberate --
it keeps a machine-dependent provider out of planning -- but tracing it surfaced that the providers which are
immediate reach the planning runtime unfiltered.

Related: test_imm_shell.star asserts immediate shell execution, contradicts both the annotation and 2.4, and
is executed by no test. test_imm_file.star and test_imm_file_join_variadic_error.star are orphans too.
Filed separately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Epic:ExecutionGraphThe execution graph epicPriority:P1This cycleSeverity:HighA supported path is broken with no workaroundbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions