00b-h β Invariant harvest (WORKING LIST, unclassified)¶
Generated by
python scripts/invariant_census.py --seed <this file>and then edited by hand. The STATUS column is the whole point and no regeneration can recompute it.
Every entry in 00b arrived from the audit corpus β a filed defect, grouped into a repair family, promoted. This is the other route: rules written down in comments by whoever learned them, and never registered.
Classify against 00b's own discriminator: an invariant states a rule AND its
consequence. No consequence β it is a CONVENTION and should stay one; promoting
it manufactures the unfalsifiable claim the registry exists to remove.
β STALE WAS WRONG ON ALL FIVE ROWS THAT CARRIED IT (corrected 2026-08-21, by ablation).
Two are defended by existing tests, one is the undefended sibling of a defended rule, and two
are real constraints the suite CANNOT observe. Two parentheticals were added because the
original vocabulary had no way to say them:
INVARIANT (UNDEFENDED)β ablation-proven real, and nothing goes red. A gap, not a demotion.INVARIANT (not test-enforceable)β real, but ablation is STRUCTURALLY BLIND to it. Two known classes: rules asserting an absence (nothing exists to break), and rules governing build-time artifacts (the suite never runs them). Both ablate to "nothing red" and would be falsely demoted to CONVENTION. Their enforcement is code review; the input that makes them red is a future commit. Any future ablation sweep must carry this third verdict or it will quietly demote exactly the rules most worth writing down.
STATUS: unclassified Β· INVARIANT Β· CONVENTION Β· PN (binding but no
code site) Β· STALE (asserts something no longer true).
INVARIANT (cite INβ¦β¦) means it RESTATES an existing registry entry β the action
is a citation, not a new token. Bare INVARIANT means no entry covers it and a
ruling is still owed. CONTESTED means two independent reads reached opposite
verdicts and it needs a human call.
Evidence for every
.pyverdict below lives in.claude/notes/LEDGER-defects-code-vs-doc.md(batches 2β6, 2026-08-20), including the enforcement site, whether a test can make it red, and whether one exists. Classifying here is NOT minting: the order stays human ruling β mint β declare β cite.
Ranking is not a ruling. A candidate here is a lead. The order stays human ruling β mint β declare β cite.
236 lines state a rule AND a consequence in a file with no IN anchor, across 119 files.
Two populations, and they need different work¶
A 14-row sample on 2026-08-19 split roughly 4:10, and the split matters because one half is nearly free:
Places an EXISTING invariant binds and is not cited. services/stall_capture.py::_set_stall_capture says
"Never mint a record for a vacuum this install does not manage" β that is [[INKV8ZQD]], in a
file carrying no anchor. room_entities.py::EufyVacuumRoomEntity states [[IN4CW5Y9]]. bindings/room-editor.js::_alertRoomProfileResult
states [[INNPA4ZV]]. cards/dashboard-card.js::_handleStart states [[ENFV9F37]]. The rule already
exists; only the citation is missing, so closing these is a reference, not a ruling. This is
the same gap the 2026-08-18 tagging pass closed from the corpus side β found here from the
prose side, which reaches files no finding ever named.
Rules never registered at all. "NEVER int() on a float β int(3.7) is 3, a real Eufy
code", "an unrecognised fault must not be subtracted, because that is the failure",
"proof, never assumption" for font support. These need the full order: read the code, rule,
mint, declare, cite.
Why a comment is good evidence, and why it rots anyway¶
A code comment is normally written live β at the moment of the change, by the person who had just worked out what was true. That is the whole reason this repo trusts prose at the site over a document: nobody was reconstructing it weeks later from memory.
But the property that makes it accurate at birth is the property that lets it drift. A comment is protected from casual rewriting β nobody edits one for fun β and that same inertia means nothing forces it to change when the code around it does. High accuracy when written, no maintenance pressure afterwards.
So it decays silently, and worse, it decays while still reading as authoritative, because sitting beside the code is exactly why you believed it. A stale document is suspected on sight; a stale comment is trusted. That asymmetry makes comment rot the more dangerous of the two, not the safer one.
This is not theoretical here, and the evidence is from this repo in one week:
- 35 of 60
(closed RP-x)claims written into source name a packet whose commits never touched the file. Two were read; both were still live. mapping/mapping_services.pysaid re-analysis preserves the user's room links because they are "independent of the image-derived segments". They are keyed BY those segments β the comment asserted the exact inverse, and read as a decision.queue/queue_engine.py's TypedDicts opened "Canonical shape forβ¦" while a NOTE forty lines above said they describe a shape the module has never emitted.themes/manager.pydocumented "write-time normalizationβ¦ without touching storage on every read" in a function whose own body normalizes on every read.- The replica harvest needed a
STALEstatus added by the walk itself, for a notice naming a real mechanism at a path it no longer occupies.
What that means for every row below. A candidate is evidence that someone once knew a
rule. It is not evidence the rule still binds, that the code still enforces it, or that the
sentence was ever right. STALE is not an edge case here β it is an expected outcome, and a
row that turns out stale is a more valuable find than one that turns out registerable, because
it was actively misleading whoever read it next.
What the count is not¶
236 is a count of leads, not of invariants. Three things will thin it, and each is a verdict a human has to make:
- Test prose. Several candidates are docstrings in
*.test.mjsstating a rule the TEST checks. The rule belongs to the code under test; the test is a citation site at best. - Local contracts. "Returns a def or null; never throws" is an API contract for one
function, not a system invariant.
CONVENTION. - Stale assertions. This repo has already found comments asserting a closure that never happened, and prose at a site reads as authority whether or not it earned that. A candidate is not evidence its own claim is still true.
| STATUS | File | Notice |
|---|---|---|
| CONVENTION | custom_components/eufy_vacuum/adapters/eufy/const.py:44 |
derived from DOMAIN so that framework namespace changes never silently |
| INVARIANT (cite IN11T0FS) | custom_components/eufy_vacuum/adapters/eufy/room_profiles.py:115 |
The non-carpet rows are a PREFERENCE applied to users who never asked for it: floor_type |
| INVARIANT (defended) | custom_components/eufy_vacuum/adapters/eufy/vocabulary.py:250 |
fault that never stopped the robot cleaning silently zeroes a productive run. Observed β΅ RE-CLASSIFIED 2026-08-21, was STALE. Not stale β live, and defended by tests/adapters/eufy/test_error_source.py, which imports both code sets and eufy_error_invalidates_cleaning and asserts they are disjoint and correctly sized. EVIDENCE GRADE: by inspection, NOT ablated. Its consequence is dated and real: alfred job_2026-08-01T23-23-35 cleaned 4 mΒ² in 360 s and recorded cleaning_time_seconds 0. |
| INVARIANT | custom_components/eufy_vacuum/adapters/eufy/vocabulary.py:274 |
BOTH SETS ARE DECLARED. A code in neither resolves to UNKNOWN, and unknown NEVER |
| INVARIANT | custom_components/eufy_vacuum/adapters/eufy/vocabulary.py:275 |
invalidates -- an unrecognised fault must not be subtracted, because that is the failure |
| INVARIANT | custom_components/eufy_vacuum/adapters/eufy/vocabulary.py:564 |
"""Coerce to an error code, or None. NEVER int(): int(3.7) is 3, a real code (SIDE |
| INVARIANT (cite IN40W49E) | custom_components/eufy_vacuum/adapters/roborock/adapter.py:344 |
mode-specific. Without this, _detect_cancel_likely_run never fires |
| INVARIANT (defended) | custom_components/eufy_vacuum/adapters/roborock/vocabulary.py:47 |
Card-facing dropdown option lists (the framework never reads these). β΅ RE-CLASSIFIED 2026-08-21, was STALE. ABLATION-PROVEN: swapping the two weakest entries so the list is no longer ascending-suction turned tests/adapters/roborock/test_adapter.py::test_vocabulary red (1 failed / 4471 passed). Restored byte-exact. |
| INVARIANT (cite IN11T0FS) | custom_components/eufy_vacuum/adapters/roborock/vocabulary.py:195 |
The non-carpet rows are a PREFERENCE applied to users who never asked for it: floor_type |
| INVARIANT | custom_components/eufy_vacuum/adapters/roborock/vocabulary.py:353 |
follows the rule the Eufy table already states: never invent a label for a code whose |
| INVARIANT (cite IN3ASEP8) | custom_components/eufy_vacuum/battery/manager.py:800 |
excluded from the delta/rate/drain accounting above, but must not |
| INVARIANT (cite INNJ6SGC) | custom_components/eufy_vacuum/battery/manager.py:866 |
is already True so this branch never fires, and tracking goes dark |
| INVARIANT | custom_components/eufy_vacuum/battery/manager.py:1231 |
live:BATT-CV-1 β the ratio is unbounded by construction, so plausibility is |
| INVARIANT (cite IN5ATBW9) | custom_components/eufy_vacuum/battery/manager.py:1285 |
that means it must be cleared here too, or the very next |
| INVARIANT (cite IN5ATBW9) | custom_components/eufy_vacuum/button.py:103 |
writing state onto the STALE existing object would never |
| CONVENTION | custom_components/eufy_vacuum/button.py:325 |
start_run_profile is a COROUTINE β it MUST be awaited or its body never runs: |
| CONVENTION | custom_components/eufy_vacuum/button.py:326 |
the press silently no-ops with only a "coroutine was never awaited" warning, |
| CONVENTION | custom_components/eufy_vacuum/config_flow.py:63 |
must NOT also reload. Single-instance anyway, so this just aborts. |
| INVARIANT (cite INYA5T84) | custom_components/eufy_vacuum/const.py:43 |
: MUST NOT be stored as an adapter config. Stored configs load first and are |
| INVARIANT (not test-enforceable) | custom_components/eufy_vacuum/const.py:190 |
live_map_rotation and surfaced in the dashboard snapshot. Display only β never β΅ RE-CLASSIFIED 2026-08-21, was STALE. β NOT ABLATABLE β the claim asserts an ABSENCE ("display only β never affects dispatch") and the forbidden coupling does not exist (grep: zero dispatch-side references). To violate it you must ADD a dependency, and no test defends against a coupling never built. Its enforcement is CODE REVIEW; the input that makes it red is a future commit, not a test case. Ablating it would report "nothing red" and FALSELY demote it to CONVENTION. |
| INVARIANT | custom_components/eufy_vacuum/core/capabilities.py:70 |
: pinning a dead id, but a user choice that has quietly stopped working must be |
| INVARIANT | custom_components/eufy_vacuum/core/capabilities.py:764 |
each must be DECISIVE (exactly one survivor) or the next is tried: |
| INVARIANT | custom_components/eufy_vacuum/core/capabilities.py:896 |
live:ENT-7 β an override that did not win must SAY so. It is first in |
| INVARIANT | custom_components/eufy_vacuum/core/error_tracker.py:285 |
NEVER int() on a float β int(3.7) is 3, a real Eufy code (SIDE BRUSH |
| INVARIANT (UNDEFENDED) | custom_components/eufy_vacuum/core/error_tracker.py:311 |
"""Exact integers only. NEVER int(): int(3.7) is 3, which is a real Eufy code (SIDE β΅ CORRECTED TWICE 2026-08-21. Final: DEAD CODE, now DELETED (ledger C18). First read STALE, then re-classified INVARIANT (UNDEFENDED) on an ablation that showed int(3.7) resolving to code 3 (SIDE BRUSH STUCK) with 4,472 tests passing. That second verdict was ALSO wrong, and the error is the more instructive one: _exact_int's only live reference was inside _int_set, and _int_set had NO callers anywhere β the pair was UNREACHABLE, superseded by _code_key/_code_set under live:RB-ERR-1 so core could carry enum-string codes. β ABLATION CANNOT TELL "unguarded" FROM "unreachable": both read as nothing-red. Nor can it tell "defended" from "dead but tested" β the Eufy-side twin _exact_error_code turns THREE tests red and also has no production caller (ledger C20). Ablation proves a TEST observes the code; it says nothing about whether PRODUCTION does. A reachability check is a separate step. Both int guards this documented survive verbatim in _code_key's docstring, so the deletion lost nothing. ORIGINAL ABLATION NOTE: int(3.7) made to resolve to code 3 (SIDE BRUSH STUCK) and 4,472 tests passed. β ONE RULE, THREE COPIES β the adapter copy (adapters/eufy/vocabulary.py::_exact_error_code, owed ruling #2) IS defended by 3 tests parametrised on 3.7/2112.9; this core copy and the string variant at error_tracker.py::_code_key (owed ruling #9) are not. Same rule, filed here THREE times under TWO verdicts. Ruling should cover the SET, not the site. See LEDGER "THE NEVER int() RULE". |
| INVARIANT (cite IN40W49E) | custom_components/eufy_vacuum/core/error_tracker.py:655 |
declare it β it was simply never read, so a brand whose firmware says |
| INVARIANT | custom_components/eufy_vacuum/counter_segmentation.py:507 |
live:RECHARGE-ATTR-1 β drop never-boundary kinds BEFORE every mode, including |
| INVARIANT | custom_components/eufy_vacuum/learning/room_attribution_engines.py:223 |
"cleaned" on it directly. The winding short-circuit must NOT pre-empt it: |
| CONTESTED | custom_components/eufy_vacuum/learning/stats_rebuilder.py:996 |
flag (missing key -> coerced False here) is never mislabeled "Sanity |
| CONVENTION | custom_components/eufy_vacuum/listeners/stall_capture.py:60 |
: Fired after a capture lands. Carries the path so an automation never has to |
| INVARIANT | custom_components/eufy_vacuum/listeners/stall_capture.py:65 |
: images of someone's home must be opted into, never inherited by an upgrade. |
| CONVENTION | custom_components/eufy_vacuum/live_refresh/manager.py:172 |
RP-039/RF-33: a subclass of HomeAssistantError, so it MUST be caught |
| CONVENTION | custom_components/eufy_vacuum/mapping/stall_capture_render.py:162 |
"""Chevrons along pts, pointing the way the robot travelled. Never raises. |
| INVARIANT | custom_components/eufy_vacuum/mapping/stall_capture_render.py:426 |
normalize_rendered. They are never offset by (ro_dx, ro_dy) and never flipped; |
| INVARIANT | custom_components/eufy_vacuum/mapping/stall_capture_render.py:496 |
capture is correct and unrecognisable β the room is a shape the user has never seen |
| INVARIANT (cite INMKEHPQ) | custom_components/eufy_vacuum/onboarding/manager.py:237 |
never saw it. The damage is silent and card-reachable: reconcile_room's |
| INVARIANT | custom_components/eufy_vacuum/receipts/__init__.py:57 |
: D is the one Β§4 never stated. Β§4 says success may not be silent; a legitimate |
| INVARIANT | custom_components/eufy_vacuum/receipts/__init__.py:103 |
: DECLARED, NEVER DERIVED from __name__. Deriving would make a file move silently change a |
| INVARIANT | custom_components/eufy_vacuum/receipts/__init__.py:104 |
: station identity, and Β§18 says a semantic id never silently changes meaning. Declared + |
| INVARIANT (cite IN4CW5Y9) | custom_components/eufy_vacuum/room_entities.py:63 |
RP-009 (REVIEW D2): ownership is answered by ATTRIBUTES, never by parsing |
| CONVENTION | custom_components/eufy_vacuum/room_entities.py:145 |
managed subset above, so anything else must still reach the generic |
| INVARIANT (cite IN40W49E) | custom_components/eufy_vacuum/rooms/vocabulary_migration.py:70 |
: must agree on which axes a brand has, or the repair undoes itself one room at a time. |
| INVARIANT (cite INKR1TW7) | custom_components/eufy_vacuum/rooms/vocabulary_migration.py:274 |
The rule is EVERY target, not "any adapter answered". With two vacuums, one |
| INVARIANT (cite INKR1TW7) | custom_components/eufy_vacuum/rooms/vocabulary_migration.py:275 |
provider being ready must not burn the opportunity for a provider that starts |
| INVARIANT (cite INKV8ZQD) | custom_components/eufy_vacuum/services/stall_capture.py:84 |
Never mint a record for a vacuum this install does not manage β that is the |
| CONVENTION | custom_components/eufy_vacuum/services/stall_capture.py:118 |
renderer. The instrument must not hand anyone that. |
| CONVENTION | custom_components/eufy_vacuum/setup/protection.py:38 |
DR-SETUP-4: a malformed bucket/room record must degrade like drift.py's |
| INVARIANT (cite IN6VSBJ1) | custom_components/eufy_vacuum/step_types.py:11 |
different matter and must NOT be merged; read the block. |
| CONVENTION | custom_components/eufy_vacuum/user_fonts.py:165 |
explicitly (manifest does). This is "cannot verify", never "covers |
| CONVENTION | custom_components/eufy_vacuum/user_fonts.py:166 |
nothing": the two verdicts must not be conflated. |
harness/dist/mount.js:78 |
raw code, in parens, so a refusal is never blank and never silently renders as success. --- | |
harness/dist/mount.js:1534 |
emits {code, params} (params never pre-joined) and the card resolves them via | |
harness/dist/mount.js:2264 |
Secondary caption under a renamed room's NEW name in the reconciliation banner's "Renamed" group; {name}=the room's previous name (escaped by the call | |
harness/dist/mount.js:39959 |
omitted so the now-relative "Due in N days" projection never fires. | |
harness/dist/mount.js:44492 |
Keys MUST match resolveFloorType()'s output β e.g. granite resolves to "granite_light", | |
harness/dist/mount.js:49364 |
without this the call silently no-ops, file never gets written. | |
harness/dist/mount.js:49866 |
and must receive display-ready text. Falls back to the key: a visible miss, never | |
harness/dist/mount.js:49867 |
a throw and never a silent drop. | |
harness/dist/mount.js:50881 |
server read must never clobber a choice the user just made. Fails soft to | |
harness/dist/mount.js:50902 |
verified locales β the card never render-verifies; the font file was the | |
harness/dist/mount.js:53414 |
Rooms belong to a specific map; a vacuum can have several. The room list must show | |
harness/dist/mount.js:54586 |
MUST match custom_components/eufy_vacuum/frontend/animal-svg/animals/index.json. | |
harness/fixtures/gallery.js:507 |
omitted so the now-relative "Due in N days" projection never fires. | |
harness/lib/gallery-html.mjs:80 |
is the published store and never calls out a merged theme's failure; the "why | |
harness/lib/mount-page.mjs:19 |
no such route, so the request 404s, the face never loads, and everything | |
harness/lib/mount-page.mjs:58 |
has never once fired for a mountHarness spec. That is why the OpenDyslexic | |
harness/lib/mount-page.mjs:131 |
UA paints in its own popup layer and never inline. A | |
harness/lib/pseudo-locale.mjs:13 |
({one,other,...}); transform each FORM string, never the object, or the | |
harness/lib/site-nav.mjs:29 |
fall back to "./" so the href is never empty or a "..//" double-slash. | |
harness/mount-entry.js:78 |
MUST match custom_components/eufy_vacuum/frontend/animal-svg/animals/index.json. | |
harness/mount-entry.js:297 |
never the font itself β exactly the gap applyDir was added to close for | |
harness/mount-entry.js:501 |
- drop non-primitive values; never eval. | |
harness/shoot-gallery.mjs:17 |
run never overwrites the plain baseline shots) | |
harness/tests/gallery-completeness.spec.mjs:36 |
coverage that never renders in CI β the same "declaration reads as coverage" trap | |
harness/tests/i18n-layout.spec.mjs:2 |
I18N LAYOUT GATE β a translated locale must not break the layout. | |
harness/tests/i18n-layout.spec.mjs:178 |
Hiding text must not strip the name β that would trade a layout fix for | |
harness/tests/i18n-layout.spec.mjs:305 |
catalogue that registers but never reaches the renderer (a resolve/pin | |
harness/tests/i18n-rtl.spec.mjs:18 |
gate can never pass by silently rendering an LTR layout. | |
harness/tests/i18n-rtl.spec.mjs:30 |
this spec never imports en.js/flatten.js (Playwright's loader treats a | |
harness/tests/i18n-rtl.spec.mjs:67 |
Fidelity guard: the host must actually be RTL, or the gate is vacuous. | |
harness/tests/smoke.spec.mjs:32 |
It must have rendered real content into the active view-root, | |
scripts/animal-descriptor.mjs:13 |
_render), is EXECUTABLE JS with raw SVG markup. We never accept JS. |
|
scripts/animal-descriptor.mjs:28 |
intake β the SUSPENDERS. Defence in depth; never rely on one alone. | |
scripts/animal-descriptor.mjs:415 |
no SVG/string content can break out into executable code. Submitters never | |
scripts/animal-descriptor.test.mjs:217 |
so the generated source can never break out into executable code. | |
scripts/check-i18n.mjs:14 |
The adversarial case is explicit: a locale value carrying <script> must |
|
scripts/check-i18n.mjs:17 |
catalog renders byte-identical; it never sees a foreign locale or a | |
scripts/check-i18n.mjs:21 |
every literal t("β¦") / tRaw("β¦") key used in src/ MUST exist in |
|
scripts/check-i18n.mjs:23 |
and every en.js key MUST be reachable from source β proven three ways | |
scripts/check-i18n.mjs:25 |
from the code), never a hand-maintained allowlist. A key reachable by | |
scripts/check-i18n.mjs:413 |
picker. A missing index resolves soft (ok:false), never throws. | |
scripts/check-i18n.mjs:532 |
never silently exempt the whole catalog. | |
scripts/check-styles.mjs:4 |
template literal must be whole. A stray backtick INSIDE one (e.g. .is-open |
|
| CONVENTION | scripts/check_doc_citations.py:74 |
The :: branch MUST come first and MUST be spelled with two colons. The original |
| CONVENTION | scripts/check_doc_citations.py:75 |
pattern had one, so it matched file.py:symbol and never file.py::symbol β the |
| CONVENTION | scripts/check_doc_citations.py:77 |
skipped silently, which meant NO-SYMBOL reported zero findings because it had never |
| CONVENTION | scripts/check_receipts.py:81 |
dimensionless, but it must be SAID, for the same reason provenance states |
| CONVENTION | scripts/check_receipts.py:166 |
and a reader trusting the catalog would wait for a signal that never comes. |
scripts/gen-theme-token-docs.mjs:103 |
produced spurious churn, and CI could never agree with a local run. | |
scripts/gen-theme-token-docs.mjs:248 |
Split the count so a dynamic family can never be mistaken for a dead one. | |
| CONVENTION | scripts/gen_event_docs.py:387 |
they went stale on commits that never touched an event. Parent links are |
| INVARIANT (not test-enforceable) | scripts/gen_floor_masks.py:59 |
calibrated for that canvas, so every mask must match or the shift misaligns. β΅ RE-CLASSIFIED 2026-08-21, was STALE. Ablated SIZE = 2048 β 1024: 4,472 passed, nothing red. But this is a BUILD-TIME generator under scripts/, which the suite never exercises β violating it produces wrong masks only when someone REGENERATES. Same blind spot class as the absence-rule above: real, consequential, and structurally invisible to ablation. Do not read "nothing red" here as CONVENTION. |
scripts/sanitize-animal-svg.mjs:20 |
- href / xlink:href must be an internal #fragment (drops external refs). | |
src/actions/core.js:167 |
never break the call it's reporting on β same defensive pattern as the | |
src/actions/fetch-failure-tristate.test.mjs:151 |
FE-ERR-4: a failed saved-zones fetch must not overwrite the library with []. | |
src/actions/fetch-failure-tristate.test.mjs:163 |
FE-ERR-6: the trouble-rooms LATCH must be conditional. Unconditional, one failed | |
src/actions/index.js:56 |
and must receive display-ready text. Falls back to the key: a visible miss, never | |
src/actions/index.js:57 |
a throw and never a silent drop. | |
src/actions/map.js:242 |
without this the call silently no-ops, file never gets written. | |
src/actions/map.js:249 |
backend means we must opt into returnResponse or the call silently | |
src/actions/review-snapshot-origin.test.mjs:1 |
Regression: getLearningHistorySnapshot must FORWARD every filter param to the service. | |
src/actions/rooms-clear-applied.test.mjs:1 |
Regression tests for Defect #8 β post-apply room mutations must DROP the pending applied | |
src/actions/rooms.js:366 |
A zone has no editable value here, but its ids must survive a wholesale resend | |
src/actions/rooms.js:387 |
WHY: an explicit save is a strong user action; chips must not show stale data after it. | |
src/actions/rooms.js:505 |
source of truth for this room's color, so a reset must persist as an explicit clear. The | |
src/actions/rooms.js:506 |
backend only writes color when the key is present, so this never clobbers other callers. | |
src/actions/saved-zones.js:18 |
so a background refresh can never clobber the map's optimistic overlays (mirrors | |
src/actions/theme-refusal-toast.test.mjs:11 |
generic {success:false} check in actions/core.js's callService never | |
src/actions/theme-refusal-toast.test.mjs:12 |
fires for a theme call β theme refusals never carry a success field). |
|
src/actions/theme.js:22 |
that generic check never fires for a theme call. Centralizing the {ok: | |
src/bindings/map-segments-staleness.test.mjs:1 |
Regression tests β the map-segments slice must follow the ACTIVE MAP, not be fetched | |
src/bindings/map.js:30 |
Keys MUST match resolveFloorType()'s output β e.g. granite resolves to "granite_light", | |
src/bindings/map.js:492 |
map β the ft-name list alone never changed on a recolour, leaving the floor image stale. | |
src/bindings/map.js:1441 |
silently saving room links onto segments that never persisted. | |
src/bindings/map.js:2178 |
An ABORTED gesture (scroll/gesture takeover, focus loss) is NOT a tap β never | |
src/bindings/map.js:2785 |
panning. This MUST live inside this one handler β _on() is idempotent per | |
src/bindings/map.js:3166 |
2) Too big. CV variants must never be silently downscaled. | |
src/bindings/room-editor.js:106 |
Prefer a human-readable backend message; NEVER surface the raw reason CODE | |
src/bindings/room-editor.js:429 |
path added anywhere joins this set β it is not optional plumbing, it is the | |
src/bindings/room-rules-payload.test.mjs:89 |
is_on/is_off/exists/missing are in NO_VALUE_OPERATORS -> value never set. | |
src/bindings/setup-reconciliation.test.mjs:16 |
error, and NEVER auto-confirms the refreshed plan. | |
src/bindings/setup-reconciliation.test.mjs:191 |
clearing of a PRIOR note) β what must never happen is it being set true, | |
src/bindings/setup.js:208 |
configures rooms immediately β ghost rooms are never saved otherwise. | |
src/bindings/setup.js:632 |
NEVER auto-confirms the refreshed plan; only re-renders State B for the | |
src/bindings/theme-import-rejected.test.mjs:6 |
result?.ok === false (inline error) but never looked at | |
src/bindings/theme-overwrite-confirm.test.mjs:21 |
so this.t()/this.esc() are actually evaluated and must resolve. | |
src/bindings/theme-preset-confirm.test.mjs:44 |
undefined: if (!proceed) return fired, setActiveTheme was never reached, and |
|
src/bindings/theme-preset-confirm.test.mjs:115 |
passed while the handler was never reaching setActiveTheme for the wrong | |
src/bindings/theme.js:162 |
silently filtered out and never made it into the new library theme). A | |
src/bindings/theme.js:1424 |
Trigger download via temp anchor. Anchor must live on the | |
src/cards/card-suggestions.test.mjs:44 |
Never suggest for an unmanaged vacuum or a non-vacuum entity. | |
src/cards/dashboard-card.js:212 |
Never rebuild the DOM mid-draw β it would wipe the in-progress zone box. | |
src/cards/dashboard-card.js:278 |
Rooms belong to a specific map; a vacuum can have several. The room list must show | |
src/cards/dashboard-card.js:750 |
stale scene must never fire select_option (selecting IS the run). | |
src/cards/dashboard-dispatch.js:6 |
module produces β it never builds service calls itself. | |
src/cards/map-room-color.js:39 |
never be themed; remove one and the editor offers a swatch for a token nothing | |
src/cards/profile-card.js:476 |
never appeared under "By entity" for a managed vacuum. | |
src/i18n/card4-untranslated-strings.test.mjs:3 |
are defined in the English base (src/i18n/en.js:35,371,338) but were never | |
src/i18n/en.js:70 |
raw code, in parens, so a refusal is never blank and never silently renders as success. --- | |
src/i18n/en.js:1130 |
emits {code, params} (params never pre-joined) and the card resolves them via | |
src/i18n/flatten.js:11 |
organizational/dedup benefits live in the FILE, never on the render hot path. | |
src/i18n/font-store.js:17 |
chrome. Not against "languages that look Latin": proof, never assumption. | |
src/i18n/font-store.js:75 |
are never touched β a drop-in cannot widen a shipped font's verified set. | |
src/i18n/index.js:54 |
native-reviewed β it must NOT auto-activate from the HA system language (it can | |
src/i18n/index.js:109 |
An unreviewed locale that must NOT auto-activate from the system language β a | |
src/i18n/index.js:151 |
catalog is the one translate() uses, so the label must agree (never show a | |
src/i18n/index.js:250 |
value carrying markup must never reach the innerHTML sink raw. options.raw |
|
src/i18n/index.js:435 |
- catalog must be a plain object (else everything is dropped). | |
src/i18n/index.js:444 |
is stripped at build, so a key that merely READS as plural must still | |
src/i18n/lang-store.js:23 |
pin / system language exactly as before. A language toggle must never be able | |
src/i18n/lang-store.js:89 |
object so it never clobbers other keys stored under USER_DATA_KEY. Never | |
src/main.js:634 |
If the user already picked this session, their choice wins β never let | |
src/main.js:650 |
server read must never clobber a choice the user just made. Fails soft to | |
src/main.js:674 |
verified locales β the card never render-verifies; the font file was the | |
src/main.js:973 |
Never switch to a capability-gated tab the adapter doesn't show β closes | |
src/main.js:1550 |
element's transform INLINE and must not be interrupted by a re-render: the live-map | |
src/main.js:2131 |
applied and silently overwrote it β mobile_shell has therefore never worked | |
src/renderers/job-summary.test.mjs:13 |
[JS-6] per-room battery is never surfaced | |
src/renderers/job-summary.test.mjs:14 |
[JS-7] an unrecovered fault never claims it stopped the run | |
src/renderers/learning-charge-status.test.mjs:1 |
Render-path tests for the live charge status (slice c / b fix). The banner must render | |
src/renderers/maintenance-census6.test.mjs:47 |
Forward-compat: a backend that adds a status this release has not keyed must | |
src/renderers/maintenance-derive.test.mjs:347 |
the harness hass null-object is truthy, so || never fires, String() gives |
|
src/renderers/maintenance-derive.test.mjs:349 |
maintenance render for the default locale. Defaulting must happen AFTER | |
src/renderers/maintenance.js:785 |
safety net for a payload that carries a percentage but no status; it must | |
src/renderers/maintenance.js:849 |
- reset_at, used_since_reset_hours, remaining_hours must be present | |
src/renderers/maintenance.js:1004 |
to "", so || never fires and toLocaleUpperCase("") throws RangeError β |
|
src/renderers/map.js:421 |
When a compose shape is selected for placement, the full-frame art must be | |
src/renderers/map.js:1198 |
--fill backdrop must NOT rotate (its polygons would drift, same rule as | |
src/renderers/pause-timeout.js:6 |
without a settable dock never rendered it β and a pause timeout is not a dock | |
src/renderers/pause-timeout.js:22 |
interface could produce silently, via a service call, but never display or | |
src/renderers/review.js:510 |
or learning verdict, so it never reads as "Sanity Failed" (backend also forces | |
src/renderers/review.js:537 |
Only sources with seconds are named, so a purely robot-side run never | |
src/renderers/review.js:577 |
room for a segment β flagged for review, never auto-overridden (see reconcile_dispatched_identity). | |
src/renderers/review.js:601 |
English β never a raw key. tVocabRaw (not tVocab) because the note is sunk | |
src/renderers/review.js:603 |
join β never zip codes[] with the index-filtered *_texts[] arrays, which can | |
src/renderers/room-estimate-allocated.test.mjs:28 |
"default" note must keep firing, so a fix that touches this file can't | |
src/renderers/run-profiles-unsupported-position.test.mjs:12 |
required_behavior text says must never happen: "a legacy profile carrying one | |
src/renderers/run-profiles-unsupported-position.test.mjs:14 |
position)' ... never a silently-shown step that won't run." | |
src/renderers/run-profiles.js:234 |
never actually run. Flag it struck-through with an explanatory note rather than | |
src/renderers/setup-reconciliation.test.mjs:106 |
(never concatenated into one sentence with the room name). | |
src/renderers/setup-reconciliation.test.mjs:178 |
reports has_changes:false. The stale manual re-discover prompt must not | |
src/renderers/setup-reconciliation.test.mjs:250 |
resolvedToken is for a DIFFERENT (older) plan β must not suppress the fresh review. | |
src/renderers/setup.js:409 |
changes" read is authoritative and must win β otherwise the manual | |
src/renderers/setup.js:922 |
was never contested β NOT that nothing decided it β so it must not | |
src/renderers/setup.js:926 |
specific rung fired -- for a role whose source was never recorded. On a | |
src/state/access-graph-model.js:171 |
Excludes self, and rooms claimed by ANOTHER room β but never a room this one | |
src/state/access-graph-model.test.mjs:14 |
[AGM-11] validateEdit does NOT enforce completeness (a graph must be | |
src/state/coded-label.js:17 |
never heard of from rendering blank β a newer backend can add a reason | |
src/state/coded-label.js:104 |
that the raw code, which at least names the condition; never blank, and | |
src/state/coded-label.js:105 |
never a silent success. | |
src/state/core.js:142 |
I've never noticed it's missing"), which is what a silent upstream | |
src/state/dialog.js:8 |
the BROWSER's locale (so they can never follow the card's per-user | |
src/state/external-jobs.js:156 |
REV-2: same as openExternalWizard β suggest, never pre-select. A | |
src/state/learning.js:837 |
working branches behind it were unreachable and the warning could never render on | |
src/state/live-trail.js:15 |
order return docks WITHIN a clean and must not split the trace). The card fires | |
src/state/map.js:283 |
never on first load (oldMapId undefined) or a transient null-clear, which | |
src/state/map.js:353 |
not been uploaded yet must read as "missing" (-> upload prompt), never | |
src/state/map.js:358 |
the brand's live image as its backdrop β never an uploaded variant β so you | |
src/state/map.js:411 |
backdrop). The composer must then render the backdrop with object-fit:contain | |
src/state/metrics.js:159 |
(accumulated, never cleared), so a selected/filtered-down chip or card keeps | |
src/state/room-editor-matching.test.mjs:139 |
Roborock declares no clean_intensity axis at all. Absent must stay absent β | |
src/state/rooms-logic.test.mjs:375 |
prose and no reason must not go silent just because the card now leads | |
src/state/run-profiles-steps.test.mjs:56 |
live there), so a brand-new draft must still open it even with nothing to | |
src/state/run-profiles-steps.test.mjs:154 |
---- Defect #4f: pendingStepRunProfileId + has_stops must gate on SEQUENCED runs, | |
src/state/run-profiles-steps.test.mjs:155 |
not charge-only. A WAIT-only or multi-group profile is stepped and MUST route | |
src/state/run-profiles.js:327 |
Insert just before the last existing step, never at the very end -- a | |
src/state/run-profiles.js:333 |
so a brand-new draft must still open it even when it has nothing to | |
src/state/saved-zones.js:6 |
Isolated slot fed by refreshSavedZones -> getSavedZones. It NEVER mutates the shared | |
src/state/saved-zones.js:44 |
so "Clean N selected" never carries a stale id that the service would refuse. | |
src/state/steps-order.js:71 |
sequence -- it would be silently skipped, never run (CARD-6 clause (1), Q17). Refuse | |
src/state/steps-order.js:165 |
dispatch (the per-group overlay only overrides what is actually set) β never clobber a real | |
src/state/steps-order.test.mjs:80 |
skipped, never run -- refused as a no-op (mirrors LB-1's leading case). | |
src/state/steps-queue-order.js:13 |
(rooms) adapter, so this must be applied AFTER applyRoomsOrderState. | |
src/state/theme-resolve.test.mjs:154 |
combine must apply the draft alpha to the theme color, not keep a stale bake. | |
src/state/theme.js:382 |
and alpha multipliers (0β1 numbers) never overwrite each other during | |
src/state/viewport-landscape.test.mjs:73 |
Tests and SSR have no window; the predicate must not invent a height and | |
src/state/zone-draft.test.mjs:160 |
Roborock never enters custom/live-backdrop mode (segmentationMode stays 'cv'), | |
src/styles/animal-hsl.test.mjs:5 |
tokens must be BARE HSL COMPONENTS. The theme system stores colours as | |
src/styles/animal-hsl.test.mjs:22 |
Yellow at 88% β the value in the bug report. Must NOT drop the opacity: | |
src/styles/animal-hsl.test.mjs:46 |
triplet, or a var() reference, must pass through untouched rather than be | |
src/styles/fonts.js:59 |
stack MUST be a full fallback chain, and every inner var() MUST carry a |
|
src/styles/fonts.js:178 |
Validate + normalize one CATALOG entry. Returns a def or null; never | |
src/styles/fonts.js:245 |
bad entry) is a skip, never a throw β the shipped fonts must be untouched | |
src/styles/typeface-wiring.test.mjs:181 |
FONT_STACK_PRESETS appends FONT_DEFS automatically β a new card font must | |
src/styles/user-fonts.test.mjs:122 |
A drop-in can never widen a shipped font's HUMAN-verified set. | |
src/theme-tags/derive.mjs:8 |
are computed on the fly and never stored, so tweaking the taxonomy updates every |