Skip to content

B-WUV6-guard-moon-task-inputs

just ci runs moon run :check :test --affected. Moon selects a task only when a changed file matches one of that task’s DECLARED inputs. A task whose declared inputs omit its own source is therefore invisible to the gate: it never runs, and the gate reports “No tasks affected by changed files” rather than an error. The failure is silent and looks like success.

root:check and root:test had exactly this fault — they declared only the implicit .moon/*.yml glob, so every change confined to solutions/ontological/ or scripts/ was ungated locally. Fixed by declaring real inputs on both tasks.

That fix is a point repair. Nothing stops the next task from being added the same way, and nothing catches the adjacent failure modes a sweep of all 103 registered projects turned up:

  • sdlc (solutions/ontological, layer tool) declares exactly one task, doc-site. No check, no test. It has layer: tool, so it does not inherit check from .moon/tasks/ts-lib.yml, which is scoped to language: typescript AND layer: library AND stack: backend.
  • determined-root (solutions/determined, layer tool) likewise has no check and no test, while carrying real ungated TypeScript in its own scripts/ and tests/.
  • Seven registered projects have no moon.yml at all, so zero tasks of any kind: agent-call, manifest-graph, shell, test-vue-component, vault-graph-core, vault-path, vault-transform.
  • Six library projects have one of the pair but not the other: app-frame (test, no check); context, dashboard-client, graph-canvas, logging (check, no test); obsidian-editor has a well-scoped typecheck task that moon run :check never targets because of the name.

Common ancestor: .moon/tasks/rust.yml scopes on language: rust alone and so reaches every rust project regardless of layer. There is no equivalent inherited task file for layer: tool + language: typescript. All three TS tool-layer projects (root, sdlc, determined-root) are hand-rolled as a result, and all three were wrong.

Proposed: a repo-level guard, scripts/guard-moon-task-inputs.ts, wired into just ci-guards and the ci-guards job. For every registered project with projectLayer != application, assert it has a reachable check and a reachable test (own or inherited), and that each declares inputs that would actually match a change to a file inside that project’s own source. Read the task graph with moon query projects --json, which returns merged tasks with expanded inputs; state.emptyInputs and an inputs list naming only config files are the two shapes to reject. Carry an explicit allowlist for the projects that legitimately have neither, with a reason per entry, so the exceptions are stated rather than assumed.

This belongs in scripts/, not in solutions/ontological. It enforces THIS repo’s moon layout, which is a consumer-specific convention; per CLAUDE.md that keeps it out of the ontological gate service and the op registry.

The seven no-moon.yml projects and the two taskless tool projects should be separate follow-ups — the guard would fail on them from day one, so either they get fixed first or they enter the allowlist with a reason.


← Back to Backlog