Planning bug: a row inventory over a prettier-wrapped HTML design asset was taken with a line-oriented grep, so MOTIR-4248's evidence table under-read one asset by two rows
Opened by Zhu Yue ·
Found by motir run MOTIR-4248 (2026-09-03), while building the asset that card commissioned. The card's conclusion was correct and its file COUNT was correct; one cell of its evidence table was not, and the cause is mechanical and repeatable.
What the card said
|
design/platform-admin/console.mock.htmlPanel 1 | identity block · Account settings · Platform admin | the staff-only door into/admin|
and, in prose, that "one omits Platform admin, the other omits Workspace settings and Sign out".
What that asset actually draws, at origin/main ee8dd322d
an Account head label +
ops@moooon.net· Account settings (i-settings) · Your organizations (i-users) · separator · Platform admin (hint +Staff only) · separator · Sign out (i-logout)
Three corrections, not one: it does draw Sign out; it draws a row — Your organizations — that UserMenu.tsx has never rendered; and it gives Account settings the settings glyph, which is Workspace settings's.
The cause — mechanical, not carelessness
The inventory was taken with a line-oriented pattern:
git grep -o -E '>(Account settings|Workspace settings|Platform admin|Sign out)<' <asset>
prettier wraps these assets, so a row's label and its closing tag land on different lines:
<span class="mrow"
><svg class="ic" viewBox="0 0 24 24"><use href="#i-settings" /></svg>Workspace
settings</span
>
git grep and grep match within a line and cannot see that. The command returns a clean, plausible, SHORT answer with no error — which is the whole hazard: an under-count from a line-oriented match is indistinguishable from a correct count.
The same defect is present in the card's own headline command (git grep -l 'Account settings' origin/main -- 'design/'). There it happened to be harmless — the file count is twelve either way, verified — because every one of those twelve names the string somewhere unwrapped. That is luck, not soundness.
Why it is filed here and not on MOTIR-4248
The plan defect is the METHOD, not this asset. MOTIR-4248 is amended on the record and its deliverable ships with the corrected measurement (design/shell/design-notes.md § The account menu, § Corrections), so nothing about that card is outstanding. What is outstanding is that the same command shape will be typed again by the next card that inventories a design asset's rows.
The fix
Add to the rule that governs a card COUNTING or ENUMERATING a population (plan-rules/phase-deepen.md's ENUMERATION limb, which already requires the ref and forbids find / ls / a bare grep -r) the sibling constraint this run paid for: over a FORMATTED source — HTML, JSON, a .pen, anything a formatter re-wraps — the enumeration is taken over file CONTENT, not over lines. The ref makes the number checkable; it does not make a line-oriented pattern able to see a wrapped match.
A worked form, which returned the same twelve and is what the notes now document:
git ls-tree -r --name-only origin/main design/ \
| xargs -I{} sh -c 'git show origin/main:{} | tr "\n" " " \
| grep -q "Account *settings" && echo {}'
The existing limb's counter-examples are all about the REF (a working tree vs. origin/main). This one is about the PREDICATE's ability to match at all, which no amount of ref discipline fixes — and it fails in the direction that looks like a finding.
Acceptance criteria
motir-meta/prompts/plan-rules/phase-deepen.md's ENUMERATION limb gains the formatted-source constraint, stated as an ADDITION beside the existing ref requirement — not a re-wording of it.- It names the tell (a formatter wraps a label away from its tag, so
>Label<matches nothing and returns a short count with no error) and gives one worked content-oriented form. - It says explicitly that the ref and the predicate are two separate checks, and that securing the ref does not secure the predicate.
- The MOTIR-4248 occurrence is cited as the fixture, with both numbers: the file count that HELD at twelve and the row inventory that was short by two.
Context refs
- MOTIR-4248 — the card whose table this corrects; amended on the record, and its § Corrections in
design/shell/design-notes.mdcarries the same finding for a design reader - motir-core#2544 — the pull request that ships the corrected measurement
motir-meta/prompts/plan-rules/phase-deepen.md— the ENUMERATION limb this amendsmotir-meta/prompts/run.md§ A bug card's FIRST deliverable is the REPRODUCTION step 3 — the run-time half, which already says to re-measure on a REF and is the rule that caught this </descriptionMd>
Advisory dispositions
-
reference·likely-missing-edgenaming MOTIR-4248 (in_review), raised byvalidate_work_itemon this card. Noblocked_byis owed, and this is a deliberate exclusion stated rather than a silence. Two independent reasons:- The two are in different containers. This card hangs under
MOTIR-1465(the planner-bug home); MOTIR-4248 hangs underMOTIR-653. A leaf-to-leafblocked_byacross containers is what gate 7 forbids — the edge would belong between the containers, and there is no dependency between them to record. - Nothing here CONSUMES that card's substrate. The fix is a rule addition in
motir-meta/prompts/plan-rules/phase-deepen.md. The occurrence it cites — the corrected inventory, the twelve that held, the two rows that were missed — is already readable in MOTIR-4248's own amended description and in motir-core#2544's body, neither of which needs a merge. This card can be written and shipped with #2544 still open, or closed, or merged.
A planning bug is telemetry about the planner: the correction it records was applied before it was filed, nobody scheduled it, and it holds nothing up. That is the whole reason
MOTIR-1465exists as a home rather than the bug being parented where it was found. - The two are in different containers. This card hangs under
Discussion
No comments yet.
Adding to this discussion signs you in on app.motir.co and brings you back to this request.