Commit Graph
188 Commits
Author SHA1 Message Date
Sergey Matyunin c8e9597228 fix: resolve chain segment thickness in one place
Issue: #234
User-Visible: yes
2026-08-21 19:42:42 +03:00
CodexandCodex edf1cca8e3 feat: hatch density is a distance, not a count of units (#230)
Одна и та же стена 15 см выглядела на планах с разным `cell_cm` по-разному:
шаг паттерна был константой в юнитах, а толщина стены переводится в юниты через
`cell_cm`, — значит число полос было пропорционально `1/cell_cm`. Разброс между
крайними масштабами достигал 25 раз, а при `cell_cm ≥ 10` в стену не попадало
и одной полосы: штриховка вырождалась в случайные штрихи или исчезала.

Шаг стал физической величиной: `wallHatchStepUnits(cellCm)` возвращает
`8 × (5 / cell_cm)` — это 9.6 см плана при любом масштабе сетки и ровно
исторические 8 юнитов при эталонном `cell_cm: 5`, так что старые планы не
двигаются. Толщина штриха следует за шагом, поэтому соотношение «штрих к
просвету» тоже перестало зависеть от масштаба.

Формула из описания issue (`cell_cm / 5`) не годилась: она увеличивает шаг там,
где стена и без того тонкая в юнитах, и разброс не исчезает, а растёт — 39
полос против 0.06 на краях диапазона. Множитель обратный; на эту ошибку
поставлен отдельный мутант `hatch-step-inverted`.

Зумовая компенсация `1/zoom` убрана по решению владельца (§4.2 ТЗ): стена,
которая меняет штриховку при зуме, — это тот же дефект, только по другой оси.
От каши на дальнем конце зума защищает второй порог `wallHatchNeedsSolid`
рядом с существующим `wallBodyNeedsSolid`; шаг клампится в [0.5, 80] юнитов,
чтобы патологический `cell_cm` не выродил паттерн.

Статический рендерер (`space-render.ts`) нёс собственную константу 8 и вообще
не знал про зум — то есть уже сегодня расходился с картой при любом зуме,
кроме единицы. Теперь оба читают шаг из одной функции; смок проверяет, что они
согласны между собой, а не только каждый сам с собой.

Два golden-эталона переснято осознанно (`golden:accept -- --reviewed`):
`large-house-zoom-040-dark` (шаг был 20 юнитов, стал 8) и
`large-house-zoom-250-dark` (был 3.2, стал 8). Расхождение осмотрено: меняется
только плотность штриховки тел стен, колонн и перегородок, геометрия и цвета
идентичны. Остальные 80 сцен не тронуты — `accept` переснимает весь набор, и
пять сцен, разошедшихся на шуме рендера, возвращены к прежним байтам вместе с
их хэшами в индексе.

Issue: #230
User-Visible: yes
2026-08-21 15:12:08 +03:00
Codex e6be43b90f feat: a straight wall is one record, not a row of seams (#229)
Рисование прямой стены в несколько кликов оставляло по записи на каждый
отрезок. Швы невидимы, пока их не тронешь: выделение хватает кусок,
перетаскивание ломает стену пополам, толщина задаётся пофрагментно. У стен
комнат этого давно нет — `normalizeWallIntervals` схлопывает каждый сплошной
участок одной толщины. Независимые перегородки жили по другому правилу.

Новый чистый модуль `src/wall-merge.ts` даёт им то же правило:

- `mergeCollinearPartitions` сращивает соседей одинаковой толщины и
  направления до неподвижной точки, но только там, где узел никому не нужен.
  Узел остаётся, если в него приходит третья перегородка, стена комнаты
  (стороной, а не только вершиной), колонна или конец сохранённого черновика.
- Направление выжившей записи канонизируется лексикографически: иначе одна и
  та же физическая стена выходила то a→b, то b→a в зависимости от порядка
  входа, и каждый host.t вдоль неё переворачивался вместе с ней.
- `applyOpeningMoves` переносит проёмы на выжившую запись: и авторитетный
  `host`, и legacy-проекцию `x/y/angle`, которую рисует старый читатель
  конфига (docs/CONFIG-COMPATIBILITY.md, #132). Проекция здесь не кэш —
  канонизация направления разворачивает угол на 180°.

Рисование сращивает только свою цепочку и то, чего она коснулась (§8.6 ТЗ):
молча править чужие швы в стороне оно не вправе — для этого есть
«Оптимизировать планы» с предпросмотром, отчётом и отменой. Оптимизация
проходит по всему пространству без seed-ограничения и отдельной строкой
сообщает, сколько записей исчезло.

Issue: #229
User-Visible: yes
2026-08-21 12:40:34 +03:00
Codex 8369c0e839 feat: reorder space tabs by dragging one to a new position
The order of config.spaces used to be whatever order the spaces were created
in, and there was no way back other than deleting a space and drawing it
again.

The gesture is deliberately narrow — mouse, editors only. The same tabs are
the primary way to switch spaces in View, where touch is first class, so a
drag there would compete with the tap that switches. Recorded in the spec as
"Touch editor: not exposed".

The part that needed care is not the drag. Position in the array feeds three
things: the marker placement fallback, the swipe neighbour and a positional
`floor`. So the write that stores the new order also writes down the
placement that used to depend on it: a marker with neither an explicit space
nor an area that names one gets the space it has right now. Both changes go in
one save; splitting them would leave a window in which markers move on their
own. The positional `floor` cannot be fixed from here, so the card says so
once.

Issue: #220
User-Visible: yes
2026-08-21 00:27:35 +03:00
Sergey Matyuninandclaude[bot] d486c64576 fix: canonicalize near-grid coordinates exactly
Issue: #223
User-Visible: yes
2026-08-20 19:32:16 +00:00
Codex 4a84734b18 fix: resolve internal content urls by path, not by string
A backup holding a PDF attachment could not be imported back: legacy links
carry a cache-buster (".../files/m1/doc.pdf?v=1783170649"), and the resolver
compared the raw tail with its sanitized form, so the query made the name
differ from itself. The reference then read as internal by prefix and
non-canonical by name, which is exactly the combination _content_state must
refuse — every such document failed with invalid_content.

Parse the url as a url: the path addresses the file, the query and the
fragment address the transfer. Path segments keep doing the guarding, so
dropping the query cannot widen what a segment is allowed to be.

Issue: #225
User-Visible: yes
2026-08-20 22:00:22 +03:00
Sergey Matyuninandclaude[bot] 442731e8eb fix: deduplicate entity markers from parent devices
Issue: #226
User-Visible: yes
2026-08-20 18:48:01 +00:00
Sergey Matyunin 3af04840a9 build: promote v1.66.0 after beta.1
Issue: #221
User-Visible: yes
2026-08-20 16:05:55 +03:00
Sergey Matyunin d55e0dd298 Release v1.66.0-beta.1 candidate
Issue: #217
Issue: #218
Issue: #219
User-Visible: yes
2026-08-20 15:18:43 +03:00
Sergey Matyunin bc75e00c2d fix: unify lock and orange icon colors
Issue: #219
User-Visible: yes
2026-08-20 14:56:21 +03:00
Sergey Matyunin 3d11758e2b fix: keep Glow visible with noisy floor geometry
Stabilize polygon-boolean inputs at render time and isolate residual
room failures without weakening fail-dark clipping.

Issue: #218
User-Visible: yes
2026-08-20 14:05:22 +03:00
Sergey Matyunin 39456dc44c fix: restore capsule outline for text markers
Issue: #217
User-Visible: yes
2026-08-20 13:21:40 +03:00
Sergey Matyunin ea33edebf9 build: promote v1.65.0 after beta.9
Issue: #215
User-Visible: yes
2026-08-20 11:55:46 +03:00
Sergey Matyunin adc1d15b98 Release v1.65.0-beta.9 candidate
Issue: #213
User-Visible: yes
2026-08-20 11:26:44 +03:00
Sergey Matyunin 0e5ee030fe fix: polish device marker geometry and input
Issue: #213
User-Visible: yes
2026-08-20 11:00:22 +03:00
Sergey Matyunin 1521d3716a Release v1.65.0-beta.8 candidate
Issue: #212
User-Visible: yes
2026-08-20 09:30:32 +03:00
Sergey Matyunin c5ba699cf1 fix: address device icon review findings
Issue: #212
User-Visible: yes
2026-08-20 09:14:27 +03:00
Sergey Matyunin 120d41317c fix: polish device icons and pointer feedback
Issue: #212
User-Visible: yes
2026-08-20 08:42:34 +03:00
Sergey Matyunin 9f5ebec6f2 Release v1.65.0-beta.7 candidate
Issue: #210
Issue: #211
User-Visible: yes
2026-08-20 01:57:19 +03:00
Sergey Matyunin 6063eead10 fix: pin card instances to configured spaces
Issue: #210
User-Visible: yes
2026-08-20 01:38:01 +03:00
Sergey Matyunin 4e82976b4a fix: match device icons to designer package
Issue: #211
User-Visible: yes
2026-08-20 00:44:11 +03:00
Sergey Matyunin c22b39e8fc Release v1.65.0-beta.6 candidate
Issue: #179
Issue: #198
Issue: #204
Issue: #205
User-Visible: yes
2026-08-19 23:17:01 +03:00
Sergey Matyunin 9daa2e91fd fix: align device compatibility guards and vacuum puck
Issue: #179
User-Visible: yes
2026-08-19 22:58:01 +03:00
Sergey Matyunin 48bcdafab9 feat: redesign device marker faces
Issue: #179
User-Visible: yes
2026-08-19 22:37:25 +03:00
Sergey Matyunin 9b05dd598d fix: clean isolated wall micro-intervals in Optimize
Issue: #198
User-Visible: yes
2026-08-19 21:10:18 +03:00
Sergey Matyunin 56e01148f8 fix: resume vacuum trails after short stops
Issue: #205
User-Visible: yes
2026-08-19 20:55:38 +03:00
Sergey Matyuninandclaude[bot] 6f89002e3a fix: show honest new-space display defaults
Issue: #204
User-Visible: yes
2026-08-19 17:44:48 +00:00
Sergey Matyunin e6016a966f Release v1.65.0-beta.5 candidate
Issue: #176
Issue: #186
Issue: #195
Issue: #200
Issue: #201
Issue: #203
User-Visible: yes
2026-08-19 19:31:44 +03:00
Sergey Matyunin 1290927f10 fix: hide disabled room names
Issue: #203
User-Visible: yes
2026-08-19 18:47:33 +03:00
Sergey Matyunin f7abf14abd fix: inherit parent thickness for atomic walls
Issue: #201
User-Visible: yes
2026-08-19 18:04:11 +03:00
Sergey Matyunin cd029a0415 fix: keep room labels aligned across modes
Issue: #200
User-Visible: yes
2026-08-19 17:12:02 +03:00
Sergey Matyunin 016c75f539 fix: enlarge editor close hit target
Issue: #195
User-Visible: yes
2026-08-19 16:38:43 +03:00
Sergey Matyunin 57ba75b9da fix: keep jamb margin on partition openings
Issue: #186
User-Visible: yes
2026-08-19 15:43:23 +03:00
Sergey Matyunin c9a83af50e Release v1.65.0-beta.4 candidate
Issue: #180
Issue: #192
Issue: #193
Issue: #196
Issue: #197
User-Visible: yes
2026-08-19 14:24:38 +03:00
Sergey Matyunin d01d0926be feat: show humidity in room tooltips
Issue: #196
User-Visible: yes
2026-08-19 13:28:09 +03:00
Sergey Matyunin db57180956 fix: isolate degenerate junction patches
Issue: #197
User-Visible: yes
2026-08-19 13:02:12 +03:00
Sergey Matyunin 9bde4b1a6d Prevent ripple color label overlap
Issue: #180
User-Visible: yes
2026-08-19 11:55:43 +03:00
Sergey Matyunin fcee724638 Unify all color picker call sites
Issue: #180
User-Visible: yes
2026-08-19 11:40:32 +03:00
Sergey Matyunin 9ec3636a42 Preview open passage placement
Issue: #193
User-Visible: yes
2026-08-19 10:51:07 +03:00
Sergey Matyuninandclaude[bot] 29ce5d9e65 Keep hue slider thumb visible
Issue: #192
User-Visible: yes
2026-08-19 07:28:37 +00:00
Sergey Matyuninandclaude[bot] a75c729d87 Show spectrum on hue slider
Issue: #192
User-Visible: yes
2026-08-19 07:28:37 +00:00
Sergey Matyunin a80fa1fa5e Release v1.65.0-beta.3 candidate
Issue: #57
Issue: #103
Issue: #113
Issue: #117
Issue: #132
Issue: #184
Issue: #187
Issue: #189
User-Visible: yes
2026-08-19 05:02:30 +03:00
Sergey Matyunin 89789d8fa6 fix: cut partition snap axes at hosted openings
Issue: #189
User-Visible: yes
2026-08-19 04:23:09 +03:00
Sergey Matyunin c8755b7c51 Fix Glow fail-dark source guard
Issue: #187
User-Visible: yes
2026-08-19 04:09:13 +03:00
Sergey Matyunin 299da593d5 Unify color and opacity picking
Issue: #57
User-Visible: yes
2026-08-19 03:46:38 +03:00
Sergey Matyunin 932773773f Show state in toggle confirmations
Issue: #103
User-Visible: yes
2026-08-19 03:23:58 +03:00
Sergey Matyunin 01fe48de00 fix: support registryless opening entities
Issue: #117
User-Visible: yes
2026-08-19 02:12:37 +03:00
Sergey Matyunin 3fe0f8c443 fix: address partition opening review regressions
Issue: #132
User-Visible: yes
2026-08-19 01:34:51 +03:00
Sergey Matyunin 9f77e3e932 feat: support openings in independent walls
Issue: #132
User-Visible: yes
2026-08-19 01:11:55 +03:00
Sergey Matyunin 57fc434d4f Release v1.65.0-beta.2 candidate
Issue: #150
Issue: #157
Issue: #170
Issue: #172
Issue: #173
Issue: #174
Issue: #178
User-Visible: yes
2026-08-18 22:11:05 +03:00