@spec-box/sdd 0.6.4 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -1
- package/assets/ci/Dockerfile +2 -0
- package/assets/hosts/claude/agent.md +13 -0
- package/assets/project/testing.md +4 -0
- package/assets/roles/challenger.md +4 -0
- package/assets/roles/distiller.md +4 -0
- package/assets/roles/implementer.md +4 -0
- package/assets/roles/planner.md +4 -0
- package/assets/roles/researcher.md +8 -3
- package/assets/roles/reviewer.md +4 -0
- package/assets/roles/tester.md +5 -1
- package/assets/roles/verifier.md +5 -1
- package/assets/skills/sbox-approve.md +11 -0
- package/assets/skills/sbox-browser.md +31 -0
- package/assets/skills/sbox-run.md +24 -0
- package/bin/sbox-browser.js +5 -0
- package/dist/adapters/host/claude/index.js +27 -85
- package/dist/adapters/host/claude/index.js.map +1 -1
- package/dist/adapters/host/index.js +25 -0
- package/dist/adapters/host/index.js.map +1 -0
- package/dist/adapters/host/skills.js +27 -0
- package/dist/adapters/host/skills.js.map +1 -0
- package/dist/browser/cli.js +488 -0
- package/dist/browser/cli.js.map +1 -0
- package/dist/browser/client.js +182 -0
- package/dist/browser/client.js.map +1 -0
- package/dist/browser/commands.js +598 -0
- package/dist/browser/commands.js.map +1 -0
- package/dist/browser/daemon.js +315 -0
- package/dist/browser/daemon.js.map +1 -0
- package/dist/browser/executable.js +138 -0
- package/dist/browser/executable.js.map +1 -0
- package/dist/browser/install.js +49 -0
- package/dist/browser/install.js.map +1 -0
- package/dist/browser/keys.js +44 -0
- package/dist/browser/keys.js.map +1 -0
- package/dist/browser/paths.js +34 -0
- package/dist/browser/paths.js.map +1 -0
- package/dist/browser/protocol.js +34 -0
- package/dist/browser/protocol.js.map +1 -0
- package/dist/browser/selectors.js +53 -0
- package/dist/browser/selectors.js.map +1 -0
- package/dist/browser/session.js +128 -0
- package/dist/browser/session.js.map +1 -0
- package/dist/browser/settings.js +51 -0
- package/dist/browser/settings.js.map +1 -0
- package/dist/browser/snapshot.js +89 -0
- package/dist/browser/snapshot.js.map +1 -0
- package/dist/cli/args.js +9 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/commands/change.js +2 -1
- package/dist/cli/commands/change.js.map +1 -1
- package/dist/cli/commands/doctor.js +16 -0
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/host.js +4 -6
- package/dist/cli/commands/host.js.map +1 -1
- package/dist/cli/commands/init.js +9 -7
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/metrics.js +2 -1
- package/dist/cli/commands/metrics.js.map +1 -1
- package/dist/cli/commands/run.js +5 -4
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/main.js +2 -12
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/output.js +7 -3
- package/dist/cli/output.js.map +1 -1
- package/dist/core/archive.js +4 -0
- package/dist/core/archive.js.map +1 -1
- package/dist/core/async.js +15 -0
- package/dist/core/async.js.map +1 -0
- package/dist/core/change.js +2 -0
- package/dist/core/change.js.map +1 -1
- package/dist/core/config.js +16 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/deliver.js +3 -1
- package/dist/core/deliver.js.map +1 -1
- package/dist/core/lock.js +2 -1
- package/dist/core/lock.js.map +1 -1
- package/dist/core/metrics.js +28 -19
- package/dist/core/metrics.js.map +1 -1
- package/dist/core/packet.js +1 -0
- package/dist/core/packet.js.map +1 -1
- package/dist/core/paths.js +14 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/report.js +5 -1
- package/dist/core/report.js.map +1 -1
- package/dist/core/roles.js +16 -5
- package/dist/core/roles.js.map +1 -1
- package/dist/core/run.js +2 -3
- package/dist/core/run.js.map +1 -1
- package/dist/core/skills.js +60 -0
- package/dist/core/skills.js.map +1 -0
- package/docs/design.md +18 -4
- package/package.json +11 -5
package/docs/design.md
CHANGED
|
@@ -300,7 +300,7 @@ Delivery narrative. При вердикте `готово` ревьюер пиш
|
|
|
300
300
|
verify-1.md
|
|
301
301
|
changeset.json # запечатанный change-set после implement: пути и дайджест дифа
|
|
302
302
|
log.md # тегированный журнал: [CODE] [RULE] [TASK] [HUMAN]
|
|
303
|
-
runs/
|
|
303
|
+
runs/ # до архивации; в архив не переносится (archive.runs: true оставляет)
|
|
304
304
|
r7/
|
|
305
305
|
packet.json # пакет роли
|
|
306
306
|
result.md # ответ роли с блоком sbox-result
|
|
@@ -368,7 +368,7 @@ runs:
|
|
|
368
368
|
|
|
369
369
|
### Архивация до мержа
|
|
370
370
|
|
|
371
|
-
Архивация происходит на фазе deliver, внутри пул-реквеста. CLI применяет дельты к истине `specs`, переносит папку изменения в `changes/archive/` с датой и коммитит всё в ветку изменения. Шаг атомарный: все проверки (каталог архива, валидность дельт) выполняются до записи, затронутые файлы истины снимаются в снимок, после применения истина проверяется на дубликаты требований и сценариев, и любая ошибка откатывает файлы к снимку. Применение дельт идемпотентно (повтор `ADDED` с тем же содержимым пропускается, с другим содержимым это ошибка), поэтому повторный запуск после сбоя даёт тот же результат, что однократный успешный. Ревьюер пул-реквеста видит три дифа вместе: код, тесты и истину спецификаций.
|
|
371
|
+
Архивация происходит на фазе deliver, внутри пул-реквеста. CLI применяет дельты к истине `specs`, переносит папку изменения в `changes/archive/` с датой и коммитит всё в ветку изменения. Шаг атомарный: все проверки (каталог архива, валидность дельт) выполняются до записи, затронутые файлы истины снимаются в снимок, после применения истина проверяется на дубликаты требований и сценариев, и любая ошибка откатывает файлы к снимку. Применение дельт идемпотентно (повтор `ADDED` с тем же содержимым пропускается, с другим содержимым это ошибка), поэтому повторный запуск после сбоя даёт тот же результат, что однократный успешный. Ревьюер пул-реквеста видит три дифа вместе: код, тесты и истину спецификаций. Папка `runs/` в архив не переносится: ответы ролей и квитанции остаются в истории ветки изменения, а всё, что нужно после доставки, уже в `change.yaml` (список запусков со временем и стоимостью, `delivery_narrative` ревьюера). Опция `archive.runs: true` сохраняет папку в архиве.
|
|
372
372
|
|
|
373
373
|
Если ревью пул-реквеста требует правок, работают два пути. Правки только в коде идут через `sbox change resume`: папка остаётся в архиве, реализатор получает замечания, фазы verify и review повторяются. Правки в спецификациях идут через `sbox change reopen`: CLI восстанавливает затронутые файлы истины из базовой ветки, возвращает папку из архива и переводит изменение в фазу plan.
|
|
374
374
|
|
|
@@ -459,7 +459,7 @@ runs:
|
|
|
459
459
|
|
|
460
460
|
### Метрики решателя
|
|
461
461
|
|
|
462
|
-
Команда `sbox metrics` считает по `change.yaml` и receipt
|
|
462
|
+
Команда `sbox metrics` считает по `change.yaml` (список запусков с временем и стоимостью переживает архивацию) и по receipt запусков, пока папка `runs/` есть: время агентов по фазам, ожидание человека на гейтах, число запусков, стоимость (для headless-запусков), возвраты и отклонения отчётов, вмешательства (отклонённые гейты, `resume`, вопросы к человеку, отклонённые отчёты), признак автономного прохождения и оценку результата человеком (`sbox change rate`). Сводка по всем изменениям даёт долю автономных, медианы времени и запусков, среднюю оценку и число вмешательств на изменение. Ничего не хранится отдельно: метрики восстанавливаются из файлов изменения.
|
|
463
463
|
|
|
464
464
|
### Как контекст попадает к агенту
|
|
465
465
|
|
|
@@ -731,7 +731,7 @@ interface HostMaterials {
|
|
|
731
731
|
}
|
|
732
732
|
```
|
|
733
733
|
|
|
734
|
-
Команда `sbox host install --target claude`
|
|
734
|
+
Команда `sbox host install --target claude | codex` копирует скиллы из единого источника `assets/skills` (`sbox-run`, `sbox-approve`, `sbox-browser`) в раскладку хоста и генерирует агентов: для Claude Code `.claude/agents/sbox-<role>.md`, где скиллы из `metadata.roles` подключены полем `skills`, потому что субагенты не видят скиллы проекта сами; для Codex сейчас ставятся только скиллы без привязки к хосту (`sbox-approve`, `sbox-browser`) в `.agents/skills`, а `sbox-run` помечен `metadata.hosts: [claude]`, потому что его текст опирается на субагентов Claude Code; агенты ролей и раздел `AGENTS.md` для Codex появятся на этапе 4. Описания агентов берутся из фронтматтера `description` файлов ролей, каркас агента из `assets/hosts/claude/agent.md`, набор инструментов из `runner.claude.allowedTools` и `readOnlyTools` конфига, как в headless-режиме. Все сгенерированные файлы тонкие: они вызывают `sbox next` и `sbox report`, а определения ролей остаются в одном месте. Повторный запуск обновляет файлы, ручные правки в них не предполагаются.
|
|
735
735
|
|
|
736
736
|
### Отчёты тестов
|
|
737
737
|
|
|
@@ -743,6 +743,17 @@ interface TestReportAdapter {
|
|
|
743
743
|
|
|
744
744
|
Реализации: jest (он же vitest с репортёром json), playwright; testplane и storybook позже. Сопоставление сценариев с тестами по ключам (название capability, требования, сценария) повторяет алгоритм spec-box, поэтому состояние автоматизации совпадает с тем, что показывает бэкенд spec-box. В OpenSpec-проекте тот же алгоритм даёт покрытие сценариев без бэкенда.
|
|
745
745
|
|
|
746
|
+
### Браузер для проверки интерфейса
|
|
747
|
+
|
|
748
|
+
Сборка и статические проверки не доказывают, что изменение работает, а роли в headless-режиме лишены браузерных инструментов хоста. Поэтому пакет ставит второй бинарник `sbox-browser`: управляемый Chrome с командами для агентов и людей. Пакет не скачивает браузер при установке (`puppeteer-core`, а не `puppeteer`); установка отдельная и необязательная.
|
|
749
|
+
|
|
750
|
+
- **Браузер.** Порядок поиска исполняемого файла: флаг `--executable`, переменная `SBOX_BROWSER_EXECUTABLE`, `browser.executable` в конфиге, кэш инструмента `~/.sbox/browser/cache`, кэш puppeteer других проектов, системный Chrome по каналам, известные пути Chromium, Edge и Brave, имена в PATH. Явно заданный путь, которого нет, это ошибка, а не переход к поиску. `sbox-browser install [--browser chrome | chrome-headless-shell | chromium] [--build stable | beta | buildId] [--cache-dir <dir>]` скачивает сборку через `@puppeteer/browsers` в кэш инструмента, `installed` и `uninstall` управляют кэшем, `doctor` показывает выбор и кандидатов. `sbox doctor` проекта добавляет проверку браузера предупреждением. Настройки: секция `browser` конфига (`executable`, `headless`, `profile`, `baseUrl`, `cacheDir`, `viewport`, `timeoutMs`, `idleMinutes`), переменные `SBOX_BROWSER_HOME` (каталог инструмента), `SBOX_BROWSER_EXECUTABLE`, `SBOX_BROWSER_HEADLESS`, `SBOX_BROWSER_PROFILE`, `SBOX_BROWSER_BASE_URL`, `SBOX_BROWSER_CACHE_DIR`, глобальные флаги `--session`, `--profile`, `--timeout`, `--cwd`; порядок: флаги → окружение → конфиг → умолчания. Прерванная установка (папка без бинарника) переустанавливается.
|
|
751
|
+
- **Сессия.** Первая команда страницы поднимает демон: фоновый процесс с браузером и локальным сокетом (unix-сокет, на Windows именованный канал) в `~/.sbox/browser/sessions/<имя>`. Клиент отправляет одну команду в JSON-строке и получает ответ; демон исполняет команды последовательно. Между вызовами сохраняются вкладки, страница, куки, буферы консоли и сети. Демон завершается по `stop`, по простою между командами (`browser.idleMinutes`, по умолчанию 30; во время долгой команды таймер не срабатывает, значения больше 35791 минут отключают самозавершение) или при потере браузера. Имя сессии занимается атомарной блокировкой до запуска браузера, поэтому два одновременных автозапуска не поднимают два Chrome; `ping` и `stop` отвечают вне очереди команд, так что занятый демон не считается мёртвым, а `stop` прерывает долгое ожидание. Уход клиента (таймаут, Ctrl+C) отменяет его команду в очереди. След мёртвого процесса удаляется при следующем обращении, а `stop` посылает сигнал только процессу, чья командная строка это демон данной сессии. `--session <имя>` даёт независимые браузеры.
|
|
752
|
+
- **Вход человеком.** `sbox-browser login <url> --profile <имя>` открывает окно с постоянным профилем (user-data-dir в `~/.sbox/browser/profiles/<имя>`), человек входит и подтверждает Enter, либо `--until <селектор>` / `--until-url <шаблон>` завершают вход автоматически. Дальше та же сессия работает под входом, а после `stop` любая headless-сессия с этим профилем (флаг `--profile` или `browser.profile` в конфиге) получает те же куки. Перенос входа в CI или на другую машину: `state save <файл>` выгружает куки браузера и storage текущей страницы, `state load` восстанавливает; файл содержит секреты и не коммитится.
|
|
753
|
+
- **Команды для агента.** `goto`, `back`, `reload`, `snapshot` (дерево доступности с ролями, именами, состояниями и ссылками `[eN]` на интерактивные элементы), действия `click`, `fill`, `type`, `press`, `select`, `check`, `upload`, `hover`, `scroll`, ожидания `wait` (элемент, текст, адрес, условие, пауза), чтение `text`, `html`, `attr`, `value`, `count`, `exists`, `eval`, доказательства `screenshot`, `console --errors`, `requests` (ответы 4xx/5xx и неудачные запросы), окружение `cookies`, `viewport`, `dialog`, `auth`, `headers`, вкладки `pages` и `page new | switch | close`. Цель действия это ссылка из снимка либо селектор: CSS, `text=`, `aria=`, `xpath=`. Ссылки нумеруются при каждом снимке; исчезнувший элемент даёт ошибку `BROWSER_REF_STALE` с подсказкой сделать снимок заново, `exists` по ссылке проверяет живой элемент. Диалог `beforeunload` подтверждается всегда, иначе политика `dismiss` отменяла бы любую навигацию. `eval` сначала исполняет код как есть (выражение или список инструкций), а при синтаксической ошибке из-за `return` или `await` как тело async-функции. Все команды поддерживают `--json`, ошибки приходят в общем конверте диагностики с кодами `BROWSER_*`.
|
|
754
|
+
- **В процессе изменения.** Верификатор обязан проверить затронутую страницу через `sbox-browser`, если `testing.md` описывает запуск: ошибки консоли и ответы 4xx/5xx на ней это FAIL, скриншот прикладывается как доказательство; без профиля для страницы, требующей входа, это пробел с окружением «вход в приложение». Исследователь и тестировщик используют снимок, чтобы зафиксировать тексты, элементы и маршруты; автотесты пишутся на инструментах проекта. Пакет каждой роли содержит подсказку `commands.browser`. Категория `testing.md` получила раздел «Проверка интерфейса в браузере»: базовый URL, профиль входа, дымовые маршруты.
|
|
755
|
+
- **Безопасность.** Профили, файлы состояния, скриншоты и журналы демонов лежат в `~/.sbox/browser`, вне репозитория продукта; в репозиторий попадает только конфиг без секретов. Демон слушает локальный сокет, доступный только пользователю.
|
|
756
|
+
|
|
746
757
|
## 12. CLI и архитектура кода
|
|
747
758
|
|
|
748
759
|
### Команды
|
|
@@ -762,6 +773,7 @@ interface TestReportAdapter {
|
|
|
762
773
|
| Доставка | `deliver [--check] [--keep-draft]`, `gates poll` | Чеклист готовности и доставка: intent, архив, коммит с ключом, push, пул-реквест; опрос гейтов в комментариях пул-реквеста |
|
|
763
774
|
| Среда | `ci install --target github \| docker` | Шаблоны workflows GitHub Actions (запуск @spec-box/sdd и тесты с JSON-отчётом) и Dockerfile |
|
|
764
775
|
| Знания | `route`, `distill`, `wiki lint` | План чтения wiki, дистилляция журнала, проверка wiki |
|
|
776
|
+
| Браузер | `sbox-browser install \| installed \| uninstall \| doctor \| login \| start \| stop \| status \| state \| goto \| snapshot \| click …` | Отдельный бинарник: управляемый Chrome для проверки интерфейса агентами и людьми, см. раздел 11 |
|
|
765
777
|
|
|
766
778
|
Все команды поддерживают `--json` и выводят ровно один JSON-документ в stdout. Диагностика в едином конверте: `severity`, `code`, `message`, `target`, `fix`. Человекочитаемый вывод идёт в stderr. Контракт взят из OpenSpec, потому что агенты уже умеют с ним работать.
|
|
767
779
|
|
|
@@ -780,6 +792,7 @@ packages/
|
|
|
780
792
|
tests-jest/ tests-playwright/ tests-testplane/ tests-storybook/
|
|
781
793
|
roles/ определения ролей и схема артефактов по умолчанию
|
|
782
794
|
cli/ команды, вывод, конфиг
|
|
795
|
+
browser/ sbox-browser: демон, клиент, команды страницы, снимок, поиск и установка браузера
|
|
783
796
|
```
|
|
784
797
|
|
|
785
798
|
На первом этапе это один npm-пакет с такой раскладкой каталогов. Разделение на пакеты происходит, когда появляется второй потребитель ядра (например, GitHub Action или бот).
|
|
@@ -788,6 +801,7 @@ packages/
|
|
|
788
801
|
|
|
789
802
|
- Node.js 22 LTS, TypeScript в strict-режиме, ESM.
|
|
790
803
|
- Схема артефактов, роли и категории документации хранятся как данные (YAML и Markdown), а не как код, чтобы проект мог их переопределять без сборки.
|
|
804
|
+
- Скиллы хостов тоже данные: единый источник `assets/skills/<имя>.md` с фронтматтером `name`, `description` и `metadata.roles`. Адаптер хоста при `init --host` и `host install` копирует файл без изменений в раскладку хоста (Claude Code: `.claude/skills/<имя>/SKILL.md`, Codex: `.agents/skills/<имя>/SKILL.md`) и подключает скилл ролям из `metadata.roles` средствами хоста. Текст скилла в коде адаптера запрещён; новый хост это новая строка в таблице раскладок, а не новый текст. Проект заменяет или добавляет скилл файлом `.sbox/skills/<имя>.md`. Хосты равноправны: возможность, сделанная для одного хоста, либо покрывает остальные, либо явно записана в план.
|
|
791
805
|
- Парсер spec-box-YAML переиспользует модель из `@spec-box/sync`, парсер OpenSpec-Markdown свой, без зависимости от пакета `@fission-ai/openspec`: он меняет формат каждые несколько недель, а нам нужен стабильный внутренний контракт. Если `openspec` установлен в проекте, `sbox validate` дополнительно вызывает `openspec validate` и показывает его диагностику.
|
|
792
806
|
- Тесты ядра на фикстурах: репозиторий-образец в каждом формате спецификаций, прогон машины состояний с записанными ответами ролей. Адаптеры сред тестируются контрактными тестами с заглушками.
|
|
793
807
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spec-box/sdd",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "@spec-box/sdd: автономная реализация продуктовых фич ИИ-агентами",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"url": "https://github.com/spec-box/sdd/issues"
|
|
14
14
|
},
|
|
15
15
|
"bin": {
|
|
16
|
-
"sbox": "bin/sbox.js"
|
|
16
|
+
"sbox": "bin/sbox.js",
|
|
17
|
+
"sbox-browser": "bin/sbox-browser.js"
|
|
17
18
|
},
|
|
18
19
|
"files": [
|
|
19
20
|
"bin",
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
"docs/design.md"
|
|
24
25
|
],
|
|
25
26
|
"engines": {
|
|
26
|
-
"node": ">=22"
|
|
27
|
+
"node": ">=22.12"
|
|
27
28
|
},
|
|
28
29
|
"scripts": {
|
|
29
30
|
"build": "tsc -p tsconfig.json",
|
|
@@ -31,13 +32,16 @@
|
|
|
31
32
|
"dev": "tsx src/cli/main.ts",
|
|
32
33
|
"test": "vitest run",
|
|
33
34
|
"test:watch": "vitest",
|
|
34
|
-
"prepublishOnly": "tsc -p tsconfig.json && vitest run"
|
|
35
|
+
"prepublishOnly": "tsc -p tsconfig.json && vitest run",
|
|
36
|
+
"dev:browser": "tsx src/browser/cli.ts"
|
|
35
37
|
},
|
|
36
38
|
"dependencies": {
|
|
37
39
|
"@anthropic-ai/claude-agent-sdk": "^0.3.268",
|
|
40
|
+
"@puppeteer/browsers": "^3.2.3",
|
|
38
41
|
"commander": "^15.0.0",
|
|
39
42
|
"fast-glob": "^3.3.3",
|
|
40
43
|
"picomatch": "^4.0.7",
|
|
44
|
+
"puppeteer-core": "^25.12.0",
|
|
41
45
|
"yaml": "^2.9.0",
|
|
42
46
|
"zod": "^4.6.2"
|
|
43
47
|
},
|
|
@@ -56,7 +60,9 @@
|
|
|
56
60
|
"codex",
|
|
57
61
|
"autonomous-development",
|
|
58
62
|
"sdd",
|
|
59
|
-
"spec-driven-development"
|
|
63
|
+
"spec-driven-development",
|
|
64
|
+
"puppeteer",
|
|
65
|
+
"browser-automation"
|
|
60
66
|
],
|
|
61
67
|
"publishConfig": {
|
|
62
68
|
"access": "public",
|