`npm run docs:accept -- --identical`: the moon lives only on the "Follow the
Sun" background at night and General settings are not in the documentation
set, so every frame matched the committed one; only the fingerprint moves.
12 reviewed frames from the golden-images artifact of Validate run
36696388011 (c8c470ed), 178 kept byte-for-byte:
- 2 new scenes (#661 AC7): day-cycle-night-moon-gibbous-dark (Moscow,
2026-10-21 18:00Z, k 0.79) and day-cycle-dusk-moon-crescent-south-dark
(Sydney, 2026-10-14 09:00Z, k 0.14) — the moon top-left behind the plan,
lit on the left, the plan covering part of the disc.
- settings-help-zoom-200-en-light and -ru-dark: the General settings card
title «Sun» became «Sun and Moon»; nothing else in the frame moved by
more than antialiasing.
- 8 isometric frames (stage6 ×5, stage3-overlays ×2, large-warm-remount):
badged device icons keep their state-free place — #711's intended
shift, merged into dev without accepting them; named here explicitly.
Release: v1.79.0-beta.1
Baseline-Reviewed: https://github.com/Matysh/houseplan-card/actions/runs/36696388011
Issue: #661
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
At dawn, dusk and night the environment shows the moon in the top-left
corner of the scene, behind the plan: computed in the card from the home
coordinates and the browser clock (short Meeus series + topocentric
parallax, within 1.4° / 1.8 pp of JPL Horizons), one designer image under
a continuous phase mask with the lit side always on the left (owner
2026-09-29), a feathered terminator, 3°/3 % thresholds and the 2 s fade of
the window rays. Everything but a small gate lives in the lazy
moon-runtime chunk, with its own 30 s ticker. General settings: "Sun"
becomes "Sun and Moon" with one switch, on for new installations
(DEFAULT_CONFIG), off for existing ones.
The initial View graph sat 728 B under its budget: the gate is paid for by
moving fifteen dialog-only strings of General settings into the lazy
settings dictionary (#459) and by one build fingerprint literal instead of
three, so the graph ends 4 B above dev. Golden: two new moon scenes, and
the two General settings help frames show «Sun and Moon»; the WSL artifact
test fixture now models scenes whose first capture awaits acceptance.
Issue: #661
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
Owner's decision in #694: icons must not change position with state.
Since #651 the rigid overlay layout sized a device by its value text and
badges, which change with HA state: a light toggling on changed its width
from 37.2 to 26.7 CSS px and re-laid out all 62 overlays of the dense
scene (~385 of 495 ms of stateUpdate; v1.77.0 had 208 ms).
- iso-scene-render.ts: the layout sees the state-free tile (icon at its
configured size, no value text, badge or supplemental metrics). An
HA-only change keeps the layout and refreshes only the visual extent
that scene bounds read, without a collision search.
- iso-overlays.ts: the rigid-group search skips candidates that already
lose to the fallback on room, then wall violations (lexicographic
bound). The result is unchanged — identical placement hash on the dense
scene — at about 35 % less work.
- docs/ISOMETRIC.md, changelogs; test #711; mutant
iso-device-layout-follows-state-again (written, not run — #709).
Local isometric-stage3-dense-v1, 3 samples: stateUpdate 522 → 89 ms
(v1.77.0: 208), modelReady 3665 → 3129, switchCycle 5544 → 4700.
Issue: #711
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
The full workflow's 7-sample median of firstStableRenderMs for
large-house-interaction-v1 was about 2790 ms across the 1.77 line and
about 2920 ms at v1.78.0 (7d4d75bd: 2925.0; the neighbouring run of the
same SHA read 3144.8). The 3000 ms ceiling sat 2.7 % above the level and
failed on runner noise; #689's 3-sample smoke read 3002.4.
- hardMaxMs 3000 → 3400 in the full profile and its smoke twin (one
number, #473 AC4): +16 % over the 1.78 level, +8 % over the worst run.
The base-relative ratio and noise allowance are unchanged.
- README: the series and the reasoning; the test pins the number and the
series points.
Issue: #692
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
CODE-REVIEW-709-r1 M1: the "Локальный набор перед пушем" section still
showed `--no-mutants`/`--max-mutants` and listed diff mutants among what
the manual pre-push-gate runs, right after the paragraph saying it runs
none. The examples and the list now match the code; the flags are named
as accepted no-ops. The `--changed` tool description is marked as a
nightly-failure diagnostic, not a task gate.
Issue: #709
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
Owner's decision 2026-09-29: mutants check the tests, not the product.
During development they are not run at all — not locally, not in CI,
not by the reviewer. The whole registry is the nightly run
(mutation-gate.yml, #513); a survivor files an issue (#472). The #693
post-mortem: 36 of 57 minutes of a one-line fix went to optional work.
- process-track.mjs: `mutants` is always false (no track, no label).
- classify-changes.mjs: Validate requests no diff mutants on any event;
the `mutants` input stays so old `-f mutants=…` calls do not fail.
- _process.yml: the default for the gate and the merge is false.
- pre-push-gate.mjs: the manual run no longer runs mutants.
- Canon: PROCESS §2.7 (a mutant is written, not run; `--check` keeps the
anchors), §5.1 (`ci:mutants` retired), §8 (ship/show: nothing beyond
gate:small and the spec — one proof per item, no `--smokes` on ship,
a stray flake is an issue, not an investigation), §10.4; AUTHOR,
REVIEWER, AGENTS, TESTING.
- Registry: four mutants of the old request rules replaced by
dev-mutants-requested-again and track-pays-for-mutants-again.
Issue: #709
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
The Plan editor rule `.hp-stair.input-enabled .hp-stair-hit { cursor: move }`
also matched the View layer, which sets input-enabled only to receive
clicks. The hit area sits over the outline, so the link's pointer on the
group was never visible and every stair in View showed a drag it cannot do.
- src/stairs-view.ts: View stairs carry `hp-stair-view`.
- plan.styles.ts: `move` applies only without it; in View the hit area
keeps the group's cursor — pointer on a link, the stage's otherwise.
- demo/smoke_stairs.mjs: computed cursors in View (link, no target) and
in the Plan editor; the two View checks are red on the old code.
- test/stairs.test.mjs: the cascade without Chromium; mutant
view-stair-cursor-move-again.
- docs/STAIRS.md, changelogs.
Issue: #693
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
The two remaining owner decisions of #690 and the legacy trivial text.
- scripts/smoke-select.mjs: VISUAL_MINIMUM, eight smokes of modes,
layers and rendering (under a minute locally). An executable diff
with no proven link now returns and prints it instead of only "the
reviewer decides"; #687 missed smoke_modes that way (item 1').
- scripts/gate-small.mjs: `--smokes` runs the minimum with the
selection.
- PROCESS §7.1 and AUTHOR.md: a raster, sharpness or compositing defect
needs a witness red on the old code for the owner's symptom and the
owner's confirmation in a real GPU browser (item 4).
- PROCESS §8, TESTING.md: the minimum in the smoke-select rule.
- scripts/task-packet.mjs: legacy `trivial` is product flow read as
track:show (§5.1), not a short track without a spec.
- Tests; mutants visual-minimum-silent-again,
visual-minimum-on-proven-link, gate-small-skips-visual-minimum;
task-packet-trivial-is-product-flow retargeted.
Issue: #690
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
The label step after integration ran one gh call
`--add-label "$TO" --remove-label "$FROM"`. For the rereview outcome
TO == FROM == S7-code-review, and gh added and removed the same label:
#699 was left without a status and no new round started (run
36491087708).
- scripts/status-label.mjs: the same label is removed and set again
through relabel from process-reconcile (#555), so the labeled event
starts the next round and a failed restore fails the step; a
different label is still one call.
- _process.yml: the step calls the script.
- PROCESS.md: the exact-candidate rule names the relabel.
- test/status-label.test.mjs; mutants rereview-relabel-in-one-call and
process-label-step-combined-again.
Issue: #706
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
CODE-REVIEW-699-r1 M1: `node scripts/ratchets.mjs tighten` was named only
by the warning `release:prerelease` prints at publication, when the
candidate commit is already made. The candidate checklist in
docs/DEVELOPMENT.md now runs it after `npm run bundle:release`, so the
caps come from the fresh dist/ and land in the candidate commit.
- test/ratchets.test.mjs pins the step and its order.
- Mutant release-runbook-forgets-tighten.
Issue: #699
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
Validate on 3dd032d7 (run 36480911145): the mutant
initial-view-ceiling-unplugged survived. With the band over the ceiling,
ceiling + band (303 000) lies above the absolute INITIAL_VIEW_GZIP_BUDGET
(301 066), so every value the CLI test could feed went red on the budget
first and the ceiling check became unobservable.
- bundle-budget.mjs CLI: the initial View ceiling is judged before
assertBundleBudget, so a growth over the band names the ratchet that
caught it; the budget still stops anything the band lets through.
- The CLI test feeds ceiling + band + 1 and expects the band message.
- The mutant's anchor follows the moved lines.
Issue: #699
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
Two-sided ratchets with zero slack made parallel tasks conflict on shared
numbers, recompute them after every rebase and hit a ceiling because a
neighbour merged first (#689 after #691).
- Core lines (test/core-file-budget.test.mjs): a branch may grow up to
CORE_BAND = 50 lines over the beta ceiling; shrinking no longer fails it.
- Bundle graphs (bundle-budget.mjs): initial View and lazy graphs fail only
above ceiling + 2 000 B; below the ceiling is not a branch finding. The
absolute INITIAL_VIEW_GZIP_BUDGET stays the wall.
- Monolith numbers (monolith-metrics.mjs, unused-locals-gate.mjs):
METRIC_BANDS — 5 for delegates, port members and privates, 25 for host.
refs, 2 000 B for dist/; a lower number is reported, not failed.
- Browser mutation guards: 200 is a guideline — mutation-gate --check warns
above it instead of failing; every guard still needs its reason line.
- scripts/ratchets.mjs: `report [--warn]` and `tighten` — on the beta
candidate the release manager sets every ceiling to the fact in one
commit; release:prerelease prints loose ceilings as a warning.
Canon: PROCESS.md §3 (browser guards, monolith numbers) and §8 «Храповики»;
docs/TESTING.md.
Issue: #699
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
CODE-REVIEW-700-r1 Medium: `gh issue list … || true` turned a failed read
into an empty answer, and the step went on to gh issue create — a second
[workflow-sync] issue next to the open one on every network or rate-limit
failure. A failed read now warns and exits 0; creating stays reserved for
«read succeeded, nothing open».
Mutant workflow-sync-issue-duplicated-on-read-failure.
Issue: #700
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
11 of 85 returns in #600–#691 were the thin-workflow mirror check, and any
push could turn red because a foreign site behind a docs link was down.
- validate.yml preflight: on refs/heads/issue/* the workflow_sync mismatch
is a warning in the summary, not a failed verdict; push to dev, the beta
candidate and the release keep it red.
- On push to dev a mismatch opens one owner issue titled [workflow-sync]
(or comments on the open one), like the nightly mutation gate (#472);
preflight gets issues: write for that.
- check-docs --external=warn: external link failures become warnings; the
docs step passes it on task branches only.
Canon: PROCESS.md §10.4 («Workflow из ветки по умолчанию»).
Issue: #700
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
Сверка PROCESS.md, ролевых выжимок, AGENTS.md, TESTING.md, CONTRIBUTING.md
и скриптов по 26 найденным расхождениям (D1–D26): трейлеры по классам
изменений, gate:small как единственный источник состава, пороги ревью,
путь реестра мутантов, golden по ci:golden, порядок чтения промпта ревью.
- scripts/change-classes.mjs: классы A/B/C/D — один модуль для
process-gate и проверки трейлеров.
- commit-msg: коммит только с файлами класса C (документация) трейлеров
не требует; указанные трейлеры по-прежнему проверяются.
- Маршрут автора без docs/STATUS.md: 5345 → 4703 слова.
- Промпт ревью читает SCOPE → AGENTS → REVIEWER, как ROUTES.reviewer.
Issue: #701
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
370 merged issue/* branches sat on origin; the branch list stopped meaning
anything and an agent looking a branch up by number could take a stale one.
- merge-candidate.mjs: after a successful push to dev the task branch is
deleted with --force-with-lease on the tip the merge saw last — the
candidate published into the branch, or the material on fast-forward
(the index commit lives only in dev). A commit that landed after the
merge keeps the branch, and the merge comment says so; a failed delete
never undoes the merge. Failed, stale and conflicting merges keep it.
- The one-time cleanup of the already merged branches is not in this
commit: the list goes to the owner first.
Canon: PROCESS.md §10.4 (exact-candidate merge).
Issue: #702
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
CODE-REVIEW-698-r1 Medium: the canon said the merged monolith numbers are
judged «by the band test (#699)», but #699 is not merged — today
compareWithBaseline judges five numbers exactly and only dist/ bytes with
a band. The paragraph now says so: dev's side of the baseline turns the
candidate's Validate red when the task itself changed those numbers — the
same return to the author as before, after Validate instead of before the
review; the band for all six numbers is #699. The comment on UPSTREAM_WINS
says the same.
Issue: #698
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
14 of 48 returns in #600–#691 were rebase or merge conflicts on shared
files where the two edits do not contradict each other.
- .gitattributes: docs/CHANGELOG.md and docs/CHANGELOG.ru.md use the
built-in merge=union driver — both tasks' lines in ## Unreleased survive
a rebase, a merge and git merge-tree (#696's clean-merge test) without a
stop.
- rebase-generated.mjs: UPSTREAM_WINS — on a conflict in
scripts/monolith-baseline.json the rebase takes dev's side; the band test
on the candidate's Validate judges the merged tree (#699). Any other
conflicting path aborts exactly as before, with the full list.
- merge-candidate.mjs: the candidate's patch-id excludes the changelogs and
the monolith baseline next to docs/reviews, so a neighbour's line next to
the task entry does not re-send a green task to review.
- screenshots.json needs nothing: after #697 task branches do not commit it.
Canon: PROCESS.md, the rebase paragraph of the review index (#643).
Issue: #698
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
The screenshot fingerprint and golden baselines stop being a tax on every
task branch:
- Task branches no longer commit docs/images/** or golden baselines. On a
branch the screenshot freshness stays a preflight warning; the review
prompt, REVIEWER.md and AUTHOR.md drop check-docs as a per-task gate.
- beta-derived.yml refreshes them on dev in one bot commit before the beta
candidate: canonical docs capture + docs:accept --reviewed, golden from
the golden-images artifact of a completed Validate on dev +
golden:accept --reviewed. A changed frame or scene is accepted only when
named in the inputs; undeclared differences refuse. Baseline commits carry
Release: and Baseline-Reviewed:; the subject is not a candidate subject.
- classify-changes: the Release: trailer on an issue/* branch no longer
switches on the heavy set. ci:full / ci:golden do: process-track emits
full=true, the review gate dispatches Validate with full=true and does not
accept a light proof.
Canon: PROCESS.md §3 п.13, §5.1, §8, §11.4; CONTRIBUTING.md.
Issue: #697
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd