@@ -109,6 +109,28 @@ prose below).
109109 against the real canon tree, not only a synthetic fixture: a fixture keeps proving the
110110 whitelist mechanism works while the live path silently drops out from under it (see the
111111 paired tests in ` vendoring/compute-vendor-set.test.mjs ` ).
112+ - ** A check that selects its inputs by path pattern can reach zero files and still pass — assert
113+ the live in-scope count.** When skills moved inside their owning pack (#385 ),
114+ ` skill-no-enforcement-narration ` kept scanning the root-level ` skills/<name>/SKILL.md ` layout: it
115+ matched nothing in any tree, read as live, and caught nothing until a human noticed the prose it
116+ should have flagged (#560 — 21 skills in scope once repointed). Its fixtures are why it hid so
117+ well; they spelled the same dead layout, so five green tests proved the * matching* and never the
118+ * selection* . A scan-based check therefore needs one assertion over the ** real** tree that its
119+ scope is non-empty. Other half of the same class: agent-facing text pointing where the code isn't
120+ — the same PR fixed a rule whose ` why ` , fix text and ` doc ` all named ` engine/checks_helpers ` or
121+ ` checks/lib ` , neither of which ever existed. Nothing catches that on its own —
122+ ` reference-integrity ` is work-scoped and flags only paths the branch itself deletes — so grep the
123+ tree for any directory you name in a finding, a remedy, or a doc pointer before shipping it.
124+ - ** A scheduled task's precondition gates on movement in the window, never on standing state.** "An
125+ open PR exists" is true forever once it is true once, so the task wakes every night, spends an
126+ agent, and re-derives yesterday's verdict over an unchanged set (three of tidy-repo's tasks
127+ shipped that way; fixed in #554 ). Gate on the objects' own movement — a ` touched ` list or a
128+ tip-commit date, which the signal collector has to actually carry (` branches ` carried names only,
129+ so "is any of this new" had no answer at all). A signal that is true most days on an active repo
130+ — a substantive ` main ` move — may only ** widen** an already-triggered run, never wake one. And the
131+ gate is not the scope: where a verdict is relative to the rest of the set (superseded-by,
132+ already-in-` main ` ), newness gates and the full set stays the scope. (Portable — a promote
133+ candidate for ` basics/scheduled-tasks.md ` , which states the precondition contract but not this.)
112134- ** You cannot force a due slot by running the scheduler workflow by hand.** Dueness is
113135 stateless — a slot is due iff its time falls in ` (last successful run, now] ` — so a
114136 ` workflow_dispatch ` run outside the slot's window succeeds, prints ` - no tasks due ` , and
0 commit comments