- name
- blockwright
- description
- Постройка здания в Minecraft из любых входных данных — словесного описания, чертежей, векторного плана GeoJSON/SVG, 3D-модели, захвата Google Earth, фотографий, плоской карты. Используй, когда речь идёт о Blockwright, layout.png, model.obj, ge-export, схематике здания, derived.json, гейте или фото-ревью — а также когда просят «построить здание», «собрать схематику», «прогнать пайплайн», «замерить референсы».
# Blockwright: здание за пять этапов
Конвейер, который превращает то, что есть, в `.schem` с правильным пятном
застройки, правильным углом, правильными высотами и главными объёмами. Дальше
здание доводят люди. Это не генератор законченных зданий: это измерительно-
чертёжный набор, который снимает арифметику и оставляет решения.
Строит что угодно: реальный дом, здание из игры, объект по чертежу, объект по
описанию. Единственное, что меняется от задачи к задаче, — **чем измерено и чем
проверено**.
## Три правила, из которых следует всё остальное
**Один блок — один метр**, и один пиксель плоской карты — один метр. Никаких
масштабных коэффициентов нигде.
**Каждый вход решает только то, в чём он силён.** Шесть вопросов, у каждого один
ответчик — сильнейший из присутствующих:
| вход | что решает | чего не решает |
|---|---|---|
| словесное описание | что существует, материал, ритм; всё как объявления | ничего не измеряет |
| векторный план (GeoJSON/SVG) | посадку, контур и состав частей — точно | высоты: у полигона их нет |
| карта, 1 px = 1 м | посадка, размер, поворот, состав частей | высоты; отдельное ребро — рисовано от руки |
| чертёж с масштабом | план, высоты, ритм — объявлениями с именем листа | только ту проекцию, которую рисует |
| 3D-модель | план, высоты, **форма** | материал, если модель без текстур |
| захват Google Earth | объём и высоты | форму — это фотограмметрия |
| фотографии | материал, цвет, остекление, ритм, какие части существуют | **ни одного размера** |
Полная таблица авторитетности — `docs/sources.md`. Её стоит открыть в начале
каждой задачи: она за минуту говорит, что здесь измеримо, а что придётся
объявить.
**Постройка проверяется тем входом, которого ей не давали.** Сравнение результата
с картой, из которой он выведен, доказывает только, что растеризатор работает.
Меш читается ради чисел и никогда ради геометрии — поэтому он и может быть
свидетелем. Когда свидетеля нет, гейт печатает `ungraded`, а не `pass`, и это
честный исход, а не провал.
Эти три правила разрешают почти каждый спор, который возникает по ходу. Если
находка ревью говорит одно, а измеренное число другое — выигрывает число, и отказ
записывается вместе с числом, которое его отклонило.
## Этапы и ворота
Два слова, которые легко перепутать: **гейт** — проверяющий скрипт и его
строки (`[pass]`, `[FAIL]`, `[----]`); **ворота** — то, чем заканчивается
этап: строки гейта этого этапа, плюс агентский цикл ревью там, где есть
картинки, плюс — только в `--manual` — человеческий цикл после агентского.
| # | этап | артефакт | агент | человек |
|---|---|---|---|---|
| 1 | захват | орто участка сверху; что вошло, что отброшено как сосед | нет | нет |
| 2 | обмер | таблица покрытия; расхождения источников | нет | нет |
| 3 | манифест | список `Item` до того, как написан код | нет | нет |
| 4 | грейбокс | планы сверху, рендеры, лист «план \| карта \| орто» | да | да |
| 5 | постройка | гейт целиком, фото-ревью | да | да |
Цикл ревью есть на воротах 4 и 5: агентский, а в `--manual` — ещё
человеческий после него. Ворота 2 и 3 его не имеют по замыслу: их артефакт —
таблица и список, и всё, что человек мог бы там заметить, должно краснеть
само строкой гейта.
**У ворот 1 цикла пока нет.** Ревьюера захвата не написано, команды на эти
ворота нет, и ничто не пишет в журнал раздел `## Gate 1 -- capture`, поэтому
`--manual` на них не останавливается. Клип по-прежнему выбирает человек, глядя
на орто, — но это решение внутри этапа, а не ворота с записанным циклом.
Скилл `blockwright-capture` описывает, что именно смотреть.
Скиллы по этапам: 1 `blockwright-capture`, 2 `blockwright-measure`,
3 `blockwright-schedule`, 4 и 5 `blockwright-draw`, 5 ещё `blockwright-gate` и
`blockwright-review`. Скилла на этап 4 нет: как пишется `build.py`, говорит
`blockwright-draw`, а как проходятся ворота 4 — команда `/blockwright-greybox`.
Этап 1 нужен только для Google Earth. Этапы 2–5 идут по порядку, и каждый
отказывается работать без предыдущего. Это не формальность: `build.py` падает без
`derived.json`, гейт падает на схематике старше исходников, ревью падает на
схематике старше рецепта. Каждый такой отказ поставлен туда после конкретного
случая, когда без него отчёт печатал вчерашнюю правду сегодняшним числом.
## Раскладка проекта
Библиотека и инструменты лежат **в корне проекта**, а не в `.claude`: здания
импортируют `blockwright` абсолютно и запускаются модулями из корня.
```
blockwright/ библиотека: схематики, маски, рамы, меши, блоки,
sources.py (кто на какой вопрос отвечает),
survey.py и reviewing.py (аппаратура этапов 2-3 и 5)
tools/ отдельные CLI: конвертация Google Earth, рендеры Blender
buildings/_template/ скелет здания — из него заводят новые
buildings/<name>/ один пакет на здание
input/ brief.md, plan.geojson, layout.png, drawings/,
sketches/, model.obj, ge-export/, photos/ —
что есть, то и есть
probes/derive.py таблицы обмера; аппаратура — blockwright.survey
build.py рецепт: читает derived.json, пишет out/build.schem;
под --greybox — только объёмы, в out/greybox.schem
gate.py что считается правильным для этого здания
review.py камеры; аппаратура — blockwright.reviewing
paths.py где что лежит — и что читает survey()
findings.md журнал ревью: хроника раундов и блоки находок.
Над out/ нарочно — его ничто не пересобирает
out/ всё производное, удаляется и пересобирается целиком
docs/sources.md входы и их полномочия
docs/pipeline.md метод целиком, с обоснованием неочевидного
docs/data-contract.md что лежит в папке здания
```
Скрипты импортируют `blockwright` абсолютно и запускаются как модули из корня
проекта, поэтому от текущего каталога не зависит ничего, кроме импортов.
## Порядок запуска
```sh
python -m buildings.<name>.probes.derive # обмерить входы
python -m buildings.<name>.build --greybox # объёмы, ворота 4
python -m buildings.<name>.build # полная постройка
python -m buildings.<name>.gate # сверить с эталоном
python -m buildings.<name>.review --mesh # и посмотреть на это
```
Первое, на что смотреть в выводе `derive`, — таблица покрытия: что обмер
измерил, по его частям. Слово `none` в колонке высоты — у этой части обмера
высоты нет, и это решается до чертежа. Прочерк `-` там не печатается: он
значил бы, что словаря происхождения не было вовсе.
Часть, которую постройка положит сверх обмера, этой таблице невидима — её
ловит строка гейта `every part is measured by something` после чертежа.
Таблица свидетельств над ней говорит, кто на какой вопрос ответил и какого
веса числа под ней.
Команды: `/blockwright-new <имя>` (завести здание из `buildings/_template`),
`/blockwright-run <имя>` (обмер, чертёж, гейт), `/blockwright-greybox <имя>`
(ворота 4), `/blockwright-review <имя>` (рендеры и фото-ревью, ворота 5).
## Что читать, когда застрял
- `docs/sources.md` — что чем измеряется и что придётся объявить.
- `docs/pipeline.md` — метод целиком. Там же обоснования решений, которые
выглядят произвольными: почему минимальный прямоугольник, а не PCA; почему
разложение, а не пятно; почему заливка наружу, а не рамка; почему части модели
берутся со ступеней крыши.
- `docs/data-contract.md` — что лежит в `input/` и что появляется в `out/`.
## Чего не делать
**Не вписывать число, которое можно измерить.** Любая константа в `build.py` либо
приходит из `derived.json`, либо является осознанным чертёжным решением с
записанной причиной. Третьей категории нет, и «взял из README» — это первая
категория, которая протухла.
**Не объявлять размер по фотографии.** Фотография не даёт размеров. Число,
снятое с кадра, приезжает с угаданной камерой, угаданным объективом и угаданной
точкой съёмки, а рядом с ним стоит указанный источник — и это хуже, чем неверное
число без источника.
**Не подгонять допуск, чтобы гейт прошёл.** Если сечение не сходится, либо
постройка неправильная, либо окно обмера выбрано не там. Расширенный допуск — это
проверка, которая перестала быть проверкой.
**Не читать геометрию с захвата.** Высоту — да. Форму — нет, никогда. С
полноценной 3D-модели — можно и нужно: она для этого и есть.
**Не циклиться.** Если два прогона подряд не сдвинули отчёт, проблема не в том,
что ты правишь. Вернись на этап назад и проверь окно обмера.
View on GitHub