@spec-box/sdd 0.8.1 → 0.9.0
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 +22 -0
- package/assets/project/wiki.README.md +30 -0
- package/assets/skills/sbox-wiki.md +21 -0
- package/bin/sbox-wiki.js +5 -0
- package/dist/adapters/host/index.js +1 -1
- package/dist/adapters/host/index.js.map +1 -1
- package/dist/core/packet.js +3 -0
- package/dist/core/packet.js.map +1 -1
- package/dist/core/wiki.js +10 -70
- package/dist/core/wiki.js.map +1 -1
- package/dist/wiki/cli.js +60 -0
- package/dist/wiki/cli.js.map +1 -0
- package/dist/wiki/markdown.js +41 -0
- package/dist/wiki/markdown.js.map +1 -0
- package/dist/wiki/store.js +268 -0
- package/dist/wiki/store.js.map +1 -0
- package/docs/design.md +24 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -40,6 +40,7 @@ src/adapters/ spec/spec-box, spec/openspec — истина и дельты
|
|
|
40
40
|
repo/github, repo/local — хостинг репозитория; host/skills — раскладки скиллов по хостам, host/claude — агенты Claude Code
|
|
41
41
|
src/cli/ команды commander: init, doctor, host, change, next, report, approve, reject,
|
|
42
42
|
status, instructions, validate, spec, archive, log
|
|
43
|
+
src/wiki/ sbox-wiki: индекс и кеш Markdown, поиск, страницы, ссылки и валидация
|
|
43
44
|
src/browser/ sbox-browser: демон с Chrome на сессию, клиент через локальный сокет, команды страницы,
|
|
44
45
|
снимок дерева доступности со ссылками, поиск и установка браузера, вход человеком, перенос состояния
|
|
45
46
|
assets/roles/ определения ролей (Markdown): researcher, planner, tester, implementer, reviewer, verifier…
|
|
@@ -95,6 +96,27 @@ sbox-browser stop
|
|
|
95
96
|
|
|
96
97
|
Существующий браузер вместо установки: флаг `--executable`, переменная `SBOX_BROWSER_EXECUTABLE` или `browser.executable` в `.sbox/config.yaml`; без них по порядку проверяются кэш инструмента, кэш puppeteer, системный Chrome, Chromium, Edge и Brave. Сессия это фоновый процесс с браузером: команды идут к нему через локальный сокет, поэтому страница, куки, консоль и сетевые ошибки сохраняются между вызовами; `--session <имя>` даёт несколько независимых браузеров, простой 30 минут завершает сессию. Настройки в секции `browser` конфига: `executable`, `headless`, `profile`, `baseUrl`, `cacheDir`, `viewport`, `timeoutMs`, `idleMinutes`; те же значения задаются переменными `SBOX_BROWSER_EXECUTABLE`, `SBOX_BROWSER_HEADLESS`, `SBOX_BROWSER_PROFILE`, `SBOX_BROWSER_BASE_URL`, `SBOX_BROWSER_CACHE_DIR` (каталог инструмента: `SBOX_BROWSER_HOME`) и глобальными флагами `--profile`, `--session`, `--timeout`, `--cwd`. Все команды поддерживают `--json`, ошибки разбора аргументов тоже приходят в JSON-конверте. Профили и файлы состояния содержат секреты входа и живут в `~/.sbox/browser`, вне репозитория. Скилл `sbox-browser` лежит в `assets/skills` и копируется в папку хоста командой `sbox host install --target claude | codex`; агентам researcher, tester и verifier он подключается по `metadata.roles` (в Claude Code полем `skills`).
|
|
97
98
|
|
|
99
|
+
## Wiki для агентов
|
|
100
|
+
|
|
101
|
+
`sbox-wiki` работает с `.sbox/wiki/` (или `project.wiki` из конфига). Для произвольной папки без SDD укажите `--dir ./knowledge`; без конфига и этого флага используется `wiki/`. `--cwd` задаёт каталог проекта.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
sbox-wiki index --json
|
|
105
|
+
sbox-wiki search "добавить экспорт" --path src/export --limit 5 --json
|
|
106
|
+
sbox-wiki get exports --json
|
|
107
|
+
sbox-wiki get exports --section добавление-формата
|
|
108
|
+
sbox-wiki backlinks exports --json
|
|
109
|
+
sbox-wiki put exports --file /tmp/exports.md --if-match <revision> --json
|
|
110
|
+
sbox-wiki put new-topic.md --file /tmp/new-topic.md --create --json
|
|
111
|
+
sbox-wiki validate --json
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Индекс содержит краткое содержание, ситуации применения и заголовки, без текста страниц. Поиск возвращает причины совпадения и фрагменты; это лексический поиск по тексту и метаданным с повышением веса страниц подходящей области кода. `summary` и `read_when` заполняет автор или агент. Страницы — обычный Markdown, кеш хранится вне репозитория во временной папке и обновляется для изменённых файлов; `index --rebuild` пересобирает его.
|
|
115
|
+
|
|
116
|
+
`get --json` возвращает полное содержимое с фронтматтером и `revision` для последующей записи. `put` отклоняет устаревшую ревизию и ошибки целостности wiki, в том числе удаление раздела, на который ссылается другая страница. `--file -` читает stdin. Для согласованной правки нескольких связанных страниц можно использовать редактор и затем `validate`.
|
|
117
|
+
|
|
118
|
+
Валидация проверяет типы метаданных, уникальность id, локальные ссылки и якоря заголовков; ссылки из блоков кода не учитываются. Внешние URL не проверяются, ссылки за пределы wiki запрещены; HTML-ссылки и пользовательские HTML-якоря не поддерживаются. Код выхода 1 означает ошибку; отсутствие summary/read_when — предупреждение. Скилл `sbox-wiki` устанавливается для Claude и Codex через `sbox host install`; `sbox doctor` использует ту же проверку wiki.
|
|
119
|
+
|
|
98
120
|
## Состояние
|
|
99
121
|
|
|
100
122
|
Готово (этапы 1 и 2): конфиг и раскладка `.sbox/`, жизненный цикл изменения с гейтами, возвратами и бюджетом (`parked`), ревизия и lock `change.yaml`, пакеты и receipt запусков, приём отчётов с проверками (артефакты, дельты, задачи, защищённые тесты, дрейф change-set, disposition и `delivery_narrative` ревьюера), запечатывание change-set после реализации, адаптер spec-box, категории документации и структурный `doctor`, материалы для Claude Code, адаптеры сред Claude и Codex с надзором и одним транспортным повтором, `run`/`stop`/`watch`, адаптер GitHub с идемпотентной доставкой и каналом гейтов через комментарии, отчёты тестов jest/vitest/playwright и покрытие, шаблоны CI и Dockerfile.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Wiki проекта для ролей @spec-box/sdd
|
|
2
|
+
|
|
3
|
+
Здесь лежат локальные знания об областях кода, которым не место в общей документации `.sbox/project/`:
|
|
4
|
+
как устроен конкретный модуль, какой образец повторять при добавлении похожей функциональности,
|
|
5
|
+
подводные камни области. Одна страница на область или тему. README.md не включается в пакет роли SDD; sbox-wiki индексирует его как обычную страницу.
|
|
6
|
+
|
|
7
|
+
Каждая страница начинается с фронтматтера:
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
---
|
|
11
|
+
id: wiki.exports # уникальный идентификатор
|
|
12
|
+
summary: Как устроены модули экспорта и какой образец повторять
|
|
13
|
+
read_when: # когда роль обязана прочитать страницу
|
|
14
|
+
- Добавляется или меняется экспорт данных
|
|
15
|
+
- Создаётся новый модуль в src/features
|
|
16
|
+
source_roots: # пути области; по ним страница попадает в пакет роли
|
|
17
|
+
- src/features/export
|
|
18
|
+
areas: [client]
|
|
19
|
+
updated: 2026-09-16
|
|
20
|
+
verification: needs-review # verified после проверки человеком
|
|
21
|
+
---
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Тело: факты с путями, образец для единообразия («новый модуль повторяет структуру `src/features/export`: …»),
|
|
25
|
+
подводные камни, что нельзя делать. Индекс всех страниц (summary и read_when) попадает в пакет каждой роли;
|
|
26
|
+
саму страницу роль читает, если read_when подходит к задаче.
|
|
27
|
+
|
|
28
|
+
Индекс и поиск: `sbox-wiki index --json`, `sbox-wiki search "задача" --json`.
|
|
29
|
+
Чтение: `sbox-wiki get <id> --json`. Сохранение полной страницы: `sbox-wiki put <id> --file <файл> --if-match <revision>`. Новая страница: `put <путь.md> --file <файл> --create`.
|
|
30
|
+
Ссылки: относительный Markdown-путь внутри wiki с необязательным якорем заголовка. `sbox-wiki backlinks <id>` показывает входящие ссылки; `sbox-wiki validate` проверяет их целостность. Обновляйте summary и read_when вместе с текстом.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sbox-wiki
|
|
3
|
+
description: Поиск и ведение локальной Markdown-wiki проекта через sbox-wiki. Используй для поиска знаний об области кода, чтения и обновления страниц wiki и проверки ссылок между ними.
|
|
4
|
+
metadata:
|
|
5
|
+
roles: [researcher, planner, tester, implementer, verifier, reviewer, challenger, distiller]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sbox-wiki
|
|
9
|
+
|
|
10
|
+
Работает с project.wiki из .sbox/config.yaml. Для отдельной папки без SDD укажи `--dir <папка>`; пути считаются от `--cwd`. Используй `--json` для структурированного ответа, кода ошибки и revision.
|
|
11
|
+
|
|
12
|
+
- `sbox-wiki index --json`: карточки страниц с summary, read_when, source_roots и заголовками. Содержимое страниц в индекс не включается. Для большого wiki начни с поиска.
|
|
13
|
+
- `sbox-wiki search "задача" --path src/module --limit 5 --json`: результаты с причинами совпадения и фрагментом. Поиск лексический, попробуй другие термины при пустом результате. --path повышает приоритет страниц области, не ограничивает выдачу.
|
|
14
|
+
- `sbox-wiki get <id|путь.md> --json`: полный Markdown и revision. `--section <якорь>` читает раздел; для редактирования получи полную страницу.
|
|
15
|
+
- `sbox-wiki backlinks <id|путь.md> --json`: страницы, на которые повлияет удаление раздела или перенос.
|
|
16
|
+
- `sbox-wiki put <id|путь.md> --file <файл> --if-match <revision> --json`: сохранить полную страницу. При WIKI_CONFLICT перечитай её и перенеси свою правку в новую версию. Для создания: `put область/page.md --file <файл> --create`.
|
|
17
|
+
- `sbox-wiki validate --json`: метаданные, дубликаты id, отсутствующие страницы и разделы. Ссылки за пределы wiki считаются ошибкой, внешние URL не проверяются. В примерах кода ссылки не проверяются.
|
|
18
|
+
|
|
19
|
+
Пиши summary как краткое описание конкретного знания, read_when как ситуации, в которых оно помогает. Обновляй их вместе с содержимым. Метаданные составляются автором или агентом, CLI не генерирует их. Отсутствие диагностик не подтверждает истинность текста.
|
|
20
|
+
|
|
21
|
+
Сохраняй знания только в рамках полномочий текущей роли: наличие команды put не расширяет их. Markdown — источник истины; файлы можно редактировать напрямую. Кеш обновляется при изменениях файлов; `index --rebuild` восстанавливает его. put проверяет всю wiki до записи, включая входящие ссылки на изменяемые якоря. Для согласованной правки нескольких взаимосвязанных страниц отредактируй файлы и затем выполни validate.
|
package/bin/sbox-wiki.js
ADDED
|
@@ -16,7 +16,7 @@ export function installHostMaterials(root, target, config) {
|
|
|
16
16
|
next = 'В Claude Code: `/sbox-run` после `sbox change new <id> --title "..." --request "..."`.';
|
|
17
17
|
break;
|
|
18
18
|
case 'codex':
|
|
19
|
-
notes.push('Для Codex установлены скиллы sbox-approve и sbox-
|
|
19
|
+
notes.push('Для Codex установлены скиллы sbox-approve, sbox-browser и sbox-wiki в .agents/skills; оркестратор sbox-run, агенты ролей и раздел AGENTS.md для Codex появятся на этапе 4 плана.');
|
|
20
20
|
next = 'В Codex: скиллы из .agents/skills доступны сразу; изменения пока ведутся из Claude Code или командами `sbox next` и `sbox report` вручную.';
|
|
21
21
|
break;
|
|
22
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/host/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAmB,MAAM,aAAa,CAAC;AAUzF,8GAA8G;AAC9G,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,MAAc,EAAE,MAAe;IAChF,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,cAAc,EAAE,oBAAoB,MAAM,cAAc,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpI,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAY,CAAC;IACjB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,KAAK,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YACzD,IAAI,GAAG,wFAAwF,CAAC;YAChG,MAAM;QACR,KAAK,OAAO;YACV,KAAK,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/host/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAmB,MAAM,aAAa,CAAC;AAUzF,8GAA8G;AAC9G,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,MAAc,EAAE,MAAe;IAChF,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,cAAc,EAAE,oBAAoB,MAAM,cAAc,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpI,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAY,CAAC;IACjB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,KAAK,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YACzD,IAAI,GAAG,wFAAwF,CAAC;YAChG,MAAM;QACR,KAAK,OAAO;YACV,KAAK,CAAC,IAAI,CAAC,kLAAkL,CAAC,CAAC;YAC/L,IAAI,GAAG,4IAA4I,CAAC;YACpJ,MAAM;IACV,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC"}
|
package/dist/core/packet.js
CHANGED
|
@@ -117,6 +117,9 @@ export function buildPacket(ctx) {
|
|
|
117
117
|
instructions: `sbox instructions <artifact> --change ${change.id} --json`,
|
|
118
118
|
validate: `sbox validate --change ${change.id} --json`,
|
|
119
119
|
specList: 'sbox spec list --json',
|
|
120
|
+
wikiIndex: 'sbox-wiki index --json',
|
|
121
|
+
wikiSearch: 'sbox-wiki search <query> --json',
|
|
122
|
+
wikiGet: 'sbox-wiki get <id> --json',
|
|
120
123
|
specShow: 'sbox spec show <capability-id> --json',
|
|
121
124
|
changeset: `sbox changeset show --change ${change.id} --json`,
|
|
122
125
|
log: `sbox log add --change ${change.id} --tag CODE "<факт с путём>"`,
|
package/dist/core/packet.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packet.js","sourceRoot":"","sources":["../../src/core/packet.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"packet.js","sourceRoot":"","sources":["../../src/core/packet.ts"],"names":[],"mappings":"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"}
|
package/dist/core/wiki.js
CHANGED
|
@@ -1,39 +1,14 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
1
|
import path from 'node:path';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import { parseDoc } from './project-docs.js';
|
|
6
|
-
import { exists, readText, toPosix } from './paths.js';
|
|
2
|
+
import { WikiStore } from '../wiki/store.js';
|
|
3
|
+
import { assetsDir, readText, toPosix } from './paths.js';
|
|
7
4
|
export function wikiDir(root, config) {
|
|
8
5
|
return path.join(root, config.project.wiki);
|
|
9
6
|
}
|
|
10
|
-
function asList(value) {
|
|
11
|
-
if (Array.isArray(value))
|
|
12
|
-
return value.map(String);
|
|
13
|
-
if (typeof value === 'string' && value.trim())
|
|
14
|
-
return [value];
|
|
15
|
-
return [];
|
|
16
|
-
}
|
|
17
7
|
export function loadWiki(root, config) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
.sync('**/*.md', { cwd: dir, onlyFiles: true, absolute: true })
|
|
23
|
-
.filter((f) => path.basename(f).toLowerCase() !== 'readme.md')
|
|
24
|
-
.sort()
|
|
25
|
-
.map((f) => {
|
|
26
|
-
const doc = parseDoc(readText(f));
|
|
27
|
-
const fm = doc.frontmatter;
|
|
28
|
-
return {
|
|
29
|
-
file: toPosix(path.relative(root, f)),
|
|
30
|
-
id: String(fm.id ?? path.basename(f, '.md')),
|
|
31
|
-
summary: String(fm.summary ?? ''),
|
|
32
|
-
read_when: asList(fm.read_when),
|
|
33
|
-
source_roots: asList(fm.source_roots),
|
|
34
|
-
areas: asList(fm.areas),
|
|
35
|
-
};
|
|
36
|
-
});
|
|
8
|
+
return new WikiStore(wikiDir(root, config), root).pages()
|
|
9
|
+
.filter(p => path.basename(p.file).toLowerCase() !== 'readme.md')
|
|
10
|
+
.map(p => ({ file: toPosix(path.relative(root, path.join(wikiDir(root, config), p.file))), id: p.id,
|
|
11
|
+
summary: p.summary, read_when: p.read_when, source_roots: p.source_roots, areas: p.areas }));
|
|
37
12
|
}
|
|
38
13
|
/** Страницы, чьи source_roots пересекаются с путями задачи; без путей возвращаются все. */
|
|
39
14
|
export function relevantWiki(pages, paths) {
|
|
@@ -43,44 +18,9 @@ export function relevantWiki(pages, paths) {
|
|
|
43
18
|
return hit.length > 0 ? hit : pages;
|
|
44
19
|
}
|
|
45
20
|
export function doctorWiki(root, config) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
out.push(diag('warning', 'WIKI_SUMMARY', 'У страницы нет summary во фронтматтере', page.file));
|
|
50
|
-
if (page.read_when.length === 0)
|
|
51
|
-
out.push(diag('warning', 'WIKI_READ_WHEN', 'У страницы нет read_when: роли не поймут, когда её читать', page.file));
|
|
52
|
-
for (const r of page.source_roots) {
|
|
53
|
-
if (!fs.existsSync(path.join(root, r)))
|
|
54
|
-
out.push(diag('warning', 'WIKI_SOURCE_ROOT', `source_roots указывает на несуществующий путь ${r}`, page.file));
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return out;
|
|
21
|
+
return new WikiStore(wikiDir(root, config), root).validate()
|
|
22
|
+
.filter(d => !(path.basename(d.target ?? '').toLowerCase() === 'readme.md' && ['WIKI_SUMMARY', 'WIKI_READ_WHEN'].includes(d.code)))
|
|
23
|
+
.map(d => ({ ...d, target: toPosix(path.relative(root, path.join(wikiDir(root, config), d.target))) }));
|
|
58
24
|
}
|
|
59
|
-
export const WIKI_README =
|
|
60
|
-
|
|
61
|
-
Здесь лежат локальные знания об областях кода, которым не место в общей документации \`.sbox/project/\`:
|
|
62
|
-
как устроен конкретный модуль, какой образец повторять при добавлении похожей функциональности,
|
|
63
|
-
подводные камни области. Одна страница на область или тему. Файл README.md страницей не считается.
|
|
64
|
-
|
|
65
|
-
Каждая страница начинается с фронтматтера:
|
|
66
|
-
|
|
67
|
-
\`\`\`yaml
|
|
68
|
-
---
|
|
69
|
-
id: wiki.exports # уникальный идентификатор
|
|
70
|
-
summary: Как устроены модули экспорта и какой образец повторять
|
|
71
|
-
read_when: # когда роль обязана прочитать страницу
|
|
72
|
-
- Добавляется или меняется экспорт данных
|
|
73
|
-
- Создаётся новый модуль в src/features
|
|
74
|
-
source_roots: # пути области; по ним страница попадает в пакет роли
|
|
75
|
-
- src/features/export
|
|
76
|
-
areas: [client]
|
|
77
|
-
updated: 2026-09-16
|
|
78
|
-
verification: needs-review # verified после проверки человеком
|
|
79
|
-
---
|
|
80
|
-
\`\`\`
|
|
81
|
-
|
|
82
|
-
Тело: факты с путями, образец для единообразия («новый модуль повторяет структуру \`src/features/export\`: …»),
|
|
83
|
-
подводные камни, что нельзя делать. Индекс всех страниц (summary и read_when) попадает в пакет каждой роли;
|
|
84
|
-
саму страницу роль читает, если read_when подходит к задаче.
|
|
85
|
-
`;
|
|
25
|
+
export const WIKI_README = readText(path.join(assetsDir(), 'project', 'wiki.README.md'));
|
|
86
26
|
//# sourceMappingURL=wiki.js.map
|
package/dist/core/wiki.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wiki.js","sourceRoot":"","sources":["../../src/core/wiki.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"wiki.js","sourceRoot":"","sources":["../../src/core/wiki.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAiB1D,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,MAAc;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,MAAc;IACnD,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE;SACtD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC;SAChE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE;QACjG,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACnG,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,KAAiB,EAAE,KAAe;IAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnH,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,MAAc;IACrD,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE;SACzD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,WAAW,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;SAClI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,MAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7G,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC"}
|
package/dist/wiki/cli.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { Command, CommanderError } from 'commander';
|
|
4
|
+
import { WikiStore, pageSummary } from './store.js';
|
|
5
|
+
import { findProjectRoot, packageVersion } from '../core/paths.js';
|
|
6
|
+
import { loadConfig } from '../core/config.js';
|
|
7
|
+
import { SboxError } from '../core/errors.js';
|
|
8
|
+
export function buildProgram() {
|
|
9
|
+
const program = new Command().name('sbox-wiki').description('Индекс, поиск и страницы локальной Markdown-wiki').version(packageVersion())
|
|
10
|
+
.option('--cwd <dir>', 'каталог проекта', process.cwd()).option('--dir <dir>', 'папка wiki, относительно cwd; без SDD по умолчанию wiki/').option('--json', 'машиночитаемый JSON');
|
|
11
|
+
const store = () => {
|
|
12
|
+
const g = program.opts();
|
|
13
|
+
const cwd = path.resolve(g.cwd);
|
|
14
|
+
const root = findProjectRoot(cwd);
|
|
15
|
+
const dir = g.dir ? path.resolve(cwd, g.dir) : root ? path.resolve(root, loadConfig(root).project.wiki) : path.join(cwd, 'wiki');
|
|
16
|
+
return new WikiStore(dir, root ?? cwd);
|
|
17
|
+
};
|
|
18
|
+
const emit = (value) => {
|
|
19
|
+
console.log(program.opts().json ? JSON.stringify({ ok: true, data: value }) : typeof value === 'string' ? value : JSON.stringify(value, null, 2));
|
|
20
|
+
};
|
|
21
|
+
program.command('index').description('Компактный индекс без текста страниц').option('--rebuild', 'полностью перечитать Markdown')
|
|
22
|
+
.action(opts => emit(store().pages(opts.rebuild).map(pageSummary)));
|
|
23
|
+
program.command('search [query]').description('Поиск по тексту, метаданным и области кода').option('--path <path>', 'путь к коду относительно проекта').option('--limit <n>', 'максимум результатов', '5')
|
|
24
|
+
.action((query, opts) => emit(store().search(query ?? '', opts.path, Number(opts.limit))));
|
|
25
|
+
program.command('get <page>').description('Прочитать страницу по id или пути').option('--section <section>', 'заголовок или якорь раздела')
|
|
26
|
+
.action((ref, opts) => { const result = store().get(ref, opts.section); emit(program.opts().json ? result : result.content); });
|
|
27
|
+
program.command('put <page>').description('Создать или обновить полную страницу с фронтматтером').requiredOption('--file <file>', 'файл с новым содержимым, - для stdin')
|
|
28
|
+
.option('--if-match <revision>', 'revision из get для обновления').option('--create', 'создать новый путь .md')
|
|
29
|
+
.action((ref, opts) => emit(store().put(ref, fs.readFileSync(opts.file === '-' ? 0 : path.resolve(program.opts().cwd, opts.file), 'utf8'), { create: opts.create, ifMatch: opts.ifMatch })));
|
|
30
|
+
program.command('backlinks <page>').description('Входящие ссылки, включая ссылки на разделы').action(ref => emit(store().backlinks(ref)));
|
|
31
|
+
program.command('validate').description('Проверить метаданные, id, локальные ссылки и якоря').action(() => {
|
|
32
|
+
const diagnostics = store().validate();
|
|
33
|
+
emit({ diagnostics });
|
|
34
|
+
if (diagnostics.some(d => d.severity === 'error'))
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
});
|
|
37
|
+
return program;
|
|
38
|
+
}
|
|
39
|
+
export async function main(argv) {
|
|
40
|
+
const program = buildProgram();
|
|
41
|
+
for (const command of [program, ...program.commands]) {
|
|
42
|
+
command.exitOverride();
|
|
43
|
+
if (argv.includes('--json'))
|
|
44
|
+
command.configureOutput({ writeErr: () => { } });
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await program.parseAsync(argv);
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
if (e instanceof CommanderError && e.exitCode === 0)
|
|
51
|
+
return;
|
|
52
|
+
const error = { code: e instanceof SboxError || e instanceof CommanderError ? e.code : 'WIKI_ERROR', message: e instanceof Error ? e.message : String(e) };
|
|
53
|
+
if (argv.includes('--json'))
|
|
54
|
+
console.log(JSON.stringify({ ok: false, error }));
|
|
55
|
+
else
|
|
56
|
+
console.error(`${error.code}: ${error.message}`);
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/wiki/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import MarkdownIt from 'markdown-it';
|
|
2
|
+
const md = new MarkdownIt({ html: false });
|
|
3
|
+
/** CommonMark: ссылки из кода не становятся рёбрами; reference links разрешает парсер. */
|
|
4
|
+
export function markdown(body) {
|
|
5
|
+
const tokens = md.parse(body, {});
|
|
6
|
+
const lineCount = body.split('\n').length;
|
|
7
|
+
const headings = [];
|
|
8
|
+
const links = [];
|
|
9
|
+
const used = new Set();
|
|
10
|
+
const texts = [];
|
|
11
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
12
|
+
const token = tokens[i];
|
|
13
|
+
if (token.type === 'heading_open') {
|
|
14
|
+
const inline = tokens[i + 1];
|
|
15
|
+
const title = (inline.children ?? []).filter(t => ['text', 'code_inline', 'image'].includes(t.type)).map(t => t.content).join('');
|
|
16
|
+
const base = title.toLowerCase().replace(/[^\p{L}\p{N}\p{M}\s_-]/gu, '').replace(/\s/g, '-');
|
|
17
|
+
let anchor = base;
|
|
18
|
+
let n = 0;
|
|
19
|
+
while (used.has(anchor))
|
|
20
|
+
anchor = `${base}-${++n}`;
|
|
21
|
+
used.add(anchor);
|
|
22
|
+
headings.push({ title, anchor, level: Number(token.tag.slice(1)), start: token.map[0], end: lineCount });
|
|
23
|
+
}
|
|
24
|
+
if (token.type === 'fence' || token.type === 'code_block')
|
|
25
|
+
texts.push(token.content);
|
|
26
|
+
if (token.type === 'inline') {
|
|
27
|
+
texts.push(token.content);
|
|
28
|
+
for (const child of token.children ?? []) {
|
|
29
|
+
if (child.type === 'link_open')
|
|
30
|
+
links.push(String(child.attrGet('href') ?? ''));
|
|
31
|
+
if (child.type === 'image')
|
|
32
|
+
links.push(String(child.attrGet('src') ?? ''));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (let i = 0; i < headings.length; i++) {
|
|
37
|
+
headings[i].end = headings.slice(i + 1).find(h => h.level <= headings[i].level)?.start ?? lineCount;
|
|
38
|
+
}
|
|
39
|
+
return { headings, links, text: texts.join('\n') };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/wiki/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
5
|
+
import fg from 'fast-glob';
|
|
6
|
+
import { parseDoc } from '../core/project-docs.js';
|
|
7
|
+
import { SboxError } from '../core/errors.js';
|
|
8
|
+
import { diag } from '../core/diagnostics.js';
|
|
9
|
+
import { markdown } from './markdown.js';
|
|
10
|
+
const hash = (value) => createHash('sha256').update(value).digest('hex');
|
|
11
|
+
const list = (value) => typeof value === 'string' ? [value] : Array.isArray(value) ? value.filter((x) => typeof x === 'string') : [];
|
|
12
|
+
export const pageSummary = ({ body, text, links, invalid, ...page }) => page;
|
|
13
|
+
export function parsePage(file, content) {
|
|
14
|
+
const doc = parseDoc(content);
|
|
15
|
+
const fm = doc.frontmatter;
|
|
16
|
+
const parsed = markdown(doc.body);
|
|
17
|
+
const invalid = Boolean(fm.__invalid) || !fm || typeof fm !== 'object' || Array.isArray(fm)
|
|
18
|
+
|| ['id', 'summary', 'title'].some(key => fm[key] !== undefined && typeof fm[key] !== 'string')
|
|
19
|
+
|| ['read_when', 'source_roots', 'areas'].some(key => fm[key] !== undefined && typeof fm[key] !== 'string' && !(Array.isArray(fm[key]) && fm[key].every((v) => typeof v === 'string')));
|
|
20
|
+
return {
|
|
21
|
+
file, id: typeof fm.id === 'string' ? fm.id : file.replace(/\.md$/i, ''),
|
|
22
|
+
title: typeof fm.title === 'string' ? fm.title : parsed.headings[0]?.title ?? file,
|
|
23
|
+
summary: typeof fm.summary === 'string' ? fm.summary : '', read_when: list(fm.read_when), source_roots: list(fm.source_roots), areas: list(fm.areas),
|
|
24
|
+
revision: hash(content), ...parsed, body: doc.body, invalid,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Markdown остаётся истиной. Кеш содержит текст для поиска, но index отдаёт только карточки. */
|
|
28
|
+
export class WikiStore {
|
|
29
|
+
projectRoot;
|
|
30
|
+
dir;
|
|
31
|
+
cacheFile;
|
|
32
|
+
constructor(dir, projectRoot = dir) {
|
|
33
|
+
this.projectRoot = projectRoot;
|
|
34
|
+
this.dir = path.resolve(dir);
|
|
35
|
+
this.cacheFile = path.join(os.tmpdir(), `sbox-wiki-${process.getuid?.() ?? 'user'}`, `${hash(this.dir)}.json`);
|
|
36
|
+
}
|
|
37
|
+
safe(file) {
|
|
38
|
+
const target = path.resolve(this.dir, file);
|
|
39
|
+
if (target === this.dir || !target.startsWith(this.dir + path.sep))
|
|
40
|
+
throw new SboxError('WIKI_PATH', `Путь вне wiki: ${file}`);
|
|
41
|
+
// Не следуем симлинкам ни при чтении, ни при записи.
|
|
42
|
+
let current = target;
|
|
43
|
+
for (;;) {
|
|
44
|
+
try {
|
|
45
|
+
if (fs.lstatSync(current).isSymbolicLink())
|
|
46
|
+
throw new SboxError('WIKI_PATH', `Символическая ссылка: ${current}`);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
if (e.code !== 'ENOENT')
|
|
50
|
+
throw e;
|
|
51
|
+
}
|
|
52
|
+
if (current === this.dir)
|
|
53
|
+
break;
|
|
54
|
+
current = path.dirname(current);
|
|
55
|
+
}
|
|
56
|
+
return target;
|
|
57
|
+
}
|
|
58
|
+
pages(rebuild = false) {
|
|
59
|
+
if (!fs.existsSync(this.dir))
|
|
60
|
+
return [];
|
|
61
|
+
let cache = { version: 1, entries: {} };
|
|
62
|
+
if (!rebuild) {
|
|
63
|
+
try {
|
|
64
|
+
const value = JSON.parse(fs.readFileSync(this.cacheFile, 'utf8'));
|
|
65
|
+
if (value.version === 1 && value.entries)
|
|
66
|
+
cache = value;
|
|
67
|
+
}
|
|
68
|
+
catch { /* восстанавливаемый кеш */ }
|
|
69
|
+
}
|
|
70
|
+
const entries = {};
|
|
71
|
+
for (const file of fg.sync('**/*.md', { cwd: this.dir, onlyFiles: true, followSymbolicLinks: false }).sort()) {
|
|
72
|
+
const target = this.safe(file);
|
|
73
|
+
const stat = fs.statSync(target);
|
|
74
|
+
const stamp = `${stat.mtimeMs}:${stat.ctimeMs}:${stat.size}:${stat.ino}`;
|
|
75
|
+
const cached = cache.entries[file];
|
|
76
|
+
const valid = cached?.page && ['id', 'title', 'summary', 'revision', 'body', 'text'].every(key => typeof cached.page[key] === 'string')
|
|
77
|
+
&& ['read_when', 'source_roots', 'areas', 'links'].every(key => { const value = cached.page[key]; return Array.isArray(value) && value.every(x => typeof x === 'string'); })
|
|
78
|
+
&& Array.isArray(cached.page.headings) && cached.page.headings.every(h => h && typeof h.anchor === 'string' && typeof h.title === 'string' && Number.isInteger(h.start) && Number.isInteger(h.end) && Number.isInteger(h.level))
|
|
79
|
+
&& cached.page.file === file && typeof cached.page.invalid === 'boolean';
|
|
80
|
+
entries[file] = cached?.stamp === stamp && valid ? cached : { stamp, page: parsePage(file, fs.readFileSync(target, 'utf8')) };
|
|
81
|
+
}
|
|
82
|
+
// Отсутствие доступа к кешу не должно мешать читать wiki.
|
|
83
|
+
try {
|
|
84
|
+
fs.mkdirSync(path.dirname(this.cacheFile), { recursive: true, mode: 0o700 });
|
|
85
|
+
const temp = `${this.cacheFile}.${randomUUID()}`;
|
|
86
|
+
try {
|
|
87
|
+
fs.writeFileSync(temp, JSON.stringify({ version: 1, entries }), { mode: 0o600 });
|
|
88
|
+
fs.renameSync(temp, this.cacheFile);
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
fs.rmSync(temp, { force: true });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch { /* кеш необязателен */ }
|
|
95
|
+
return Object.values(entries).map(e => e.page);
|
|
96
|
+
}
|
|
97
|
+
resolve(ref, pages = this.pages()) {
|
|
98
|
+
const byFile = pages.find(p => p.file === ref);
|
|
99
|
+
if (byFile)
|
|
100
|
+
return byFile;
|
|
101
|
+
const matches = pages.filter(p => p.id === ref);
|
|
102
|
+
if (matches.length !== 1)
|
|
103
|
+
throw new SboxError(matches.length ? 'WIKI_AMBIGUOUS' : 'WIKI_NOT_FOUND', `Страница «${ref}»: найдено ${matches.length}. Используйте уникальный id или путь .md.`);
|
|
104
|
+
return matches[0];
|
|
105
|
+
}
|
|
106
|
+
get(ref, section) {
|
|
107
|
+
const page = this.resolve(ref);
|
|
108
|
+
const content = fs.readFileSync(this.safe(page.file), 'utf8');
|
|
109
|
+
const fresh = parsePage(page.file, content);
|
|
110
|
+
if (!section)
|
|
111
|
+
return { ...pageSummary(fresh), content };
|
|
112
|
+
const matches = fresh.headings.filter(h => h.anchor === section || h.title === section);
|
|
113
|
+
if (matches.length !== 1)
|
|
114
|
+
throw new SboxError('WIKI_SECTION', `Раздел «${section}»: найдено ${matches.length}. Используйте якорь из index/get.`);
|
|
115
|
+
const h = matches[0];
|
|
116
|
+
return { ...pageSummary(fresh), content: fresh.body.split('\n').slice(h.start, h.end).join('\n') };
|
|
117
|
+
}
|
|
118
|
+
link(page, href) {
|
|
119
|
+
if (/^(?:[a-z][\w+.-]*:|\/\/)/i.test(href))
|
|
120
|
+
return null;
|
|
121
|
+
const split = href.indexOf('#');
|
|
122
|
+
try {
|
|
123
|
+
const file = decodeURIComponent((split < 0 ? href : href.slice(0, split)).split('?')[0]);
|
|
124
|
+
const anchor = decodeURIComponent(split < 0 ? '' : href.slice(split + 1));
|
|
125
|
+
const target = file ? path.resolve(this.dir, path.dirname(page.file), file) : path.join(this.dir, page.file);
|
|
126
|
+
const relative = path.relative(this.dir, target).split(path.sep).join('/');
|
|
127
|
+
this.safe(relative);
|
|
128
|
+
return { file: relative, anchor };
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
throw new SboxError('WIKI_LINK_PATH', `Недопустимая ссылка: ${href}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
validate(pages = this.pages()) {
|
|
135
|
+
const out = [];
|
|
136
|
+
const ids = new Set();
|
|
137
|
+
for (const p of pages) {
|
|
138
|
+
const add = (severity, code, message) => out.push(diag(severity, code, message, p.file));
|
|
139
|
+
if (p.invalid)
|
|
140
|
+
add('error', 'WIKI_METADATA', 'Некорректный YAML или тип поля метаданных');
|
|
141
|
+
if (!p.id.trim() || ids.has(p.id))
|
|
142
|
+
add('error', 'WIKI_ID', `Пустой или повторяющийся id: ${p.id}`);
|
|
143
|
+
ids.add(p.id);
|
|
144
|
+
if (!p.summary.trim())
|
|
145
|
+
add('warning', 'WIKI_SUMMARY', 'У страницы нет summary');
|
|
146
|
+
if (!p.read_when.some(x => x.trim()))
|
|
147
|
+
add('warning', 'WIKI_READ_WHEN', 'У страницы нет read_when');
|
|
148
|
+
for (const root of p.source_roots)
|
|
149
|
+
if (!fs.existsSync(path.resolve(this.projectRoot, root)))
|
|
150
|
+
add('warning', 'WIKI_SOURCE_ROOT', `Не существует source_roots: ${root}`);
|
|
151
|
+
for (const href of p.links) {
|
|
152
|
+
try {
|
|
153
|
+
const link = this.link(p, href);
|
|
154
|
+
if (!link)
|
|
155
|
+
continue;
|
|
156
|
+
const dest = pages.find(x => x.file === link.file);
|
|
157
|
+
if (!dest && (!fs.existsSync(this.safe(link.file)) || /\.md$/i.test(link.file)))
|
|
158
|
+
add('error', 'WIKI_LINK_MISSING', `Не найдена цель: ${href}`);
|
|
159
|
+
else if (dest && link.anchor && !dest.headings.some(h => h.anchor === link.anchor))
|
|
160
|
+
add('error', 'WIKI_LINK_ANCHOR', `Не найден раздел: ${href}`);
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
add('error', 'WIKI_LINK_PATH', e.message);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return out;
|
|
168
|
+
}
|
|
169
|
+
backlinks(ref) {
|
|
170
|
+
const pages = this.pages();
|
|
171
|
+
const target = this.resolve(ref, pages);
|
|
172
|
+
return pages.flatMap(p => p.links.flatMap(href => {
|
|
173
|
+
try {
|
|
174
|
+
return this.link(p, href)?.file === target.file ? [{ id: p.id, file: p.file, href }] : [];
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
search(query, sourcePath, limit = 5) {
|
|
182
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
183
|
+
throw new SboxError('WIKI_LIMIT', 'limit должен быть целым от 1 до 100');
|
|
184
|
+
const words = [...new Set(query.toLocaleLowerCase().match(/[\p{L}\p{N}_-]+/gu) ?? [])];
|
|
185
|
+
if (!words.length && !sourcePath)
|
|
186
|
+
throw new SboxError('WIKI_QUERY', 'Укажите запрос или --path');
|
|
187
|
+
const within = (a, b) => a === b || a.startsWith(b.replace(/\/$/, '') + '/');
|
|
188
|
+
return this.pages().map(p => {
|
|
189
|
+
const reasons = [];
|
|
190
|
+
let score = 0;
|
|
191
|
+
const fields = [['title', p.title, 5], ['summary', p.summary, 4], ['read_when', p.read_when.join(' '), 4], ['areas', p.areas.join(' '), 3], ['text', p.text, 1]];
|
|
192
|
+
for (const [name, value, weight] of fields) {
|
|
193
|
+
const found = words.filter(w => value.toLocaleLowerCase().includes(w));
|
|
194
|
+
if (found.length) {
|
|
195
|
+
score += found.length * weight;
|
|
196
|
+
reasons.push(`${name}: ${found.join(', ')}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (sourcePath && p.source_roots.some(r => within(sourcePath, r) || within(r, sourcePath))) {
|
|
200
|
+
score += 10;
|
|
201
|
+
reasons.push(`source_roots: ${sourcePath}`);
|
|
202
|
+
}
|
|
203
|
+
const lines = p.text.split('\n');
|
|
204
|
+
const snippet = (lines.find(line => words.some(w => line.toLocaleLowerCase().includes(w))) ?? p.summary).slice(0, 300);
|
|
205
|
+
return { ...pageSummary(p), score, reasons, snippet };
|
|
206
|
+
}).filter(p => p.score > 0).sort((a, b) => b.score - a.score || a.file.localeCompare(b.file)).slice(0, limit);
|
|
207
|
+
}
|
|
208
|
+
put(ref, content, options) {
|
|
209
|
+
fs.mkdirSync(this.dir, { recursive: true });
|
|
210
|
+
const lock = this.safe('.sbox-wiki.lock');
|
|
211
|
+
let fd;
|
|
212
|
+
try {
|
|
213
|
+
fd = fs.openSync(lock, 'wx', 0o600);
|
|
214
|
+
}
|
|
215
|
+
catch (e) {
|
|
216
|
+
if (e.code !== 'EEXIST')
|
|
217
|
+
throw e;
|
|
218
|
+
throw new SboxError('WIKI_BUSY', 'Другая запись wiki активна. После аварии удалите .sbox-wiki.lock, убедившись, что процесс завершён.');
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
fs.writeSync(fd, String(process.pid));
|
|
222
|
+
const pages = this.pages(true);
|
|
223
|
+
let file;
|
|
224
|
+
if (options.create) {
|
|
225
|
+
if (options.ifMatch)
|
|
226
|
+
throw new SboxError('WIKI_ARGUMENT', '--create несовместим с --if-match');
|
|
227
|
+
file = path.relative(this.dir, this.safe(ref)).split(path.sep).join('/');
|
|
228
|
+
if (!file.endsWith('.md'))
|
|
229
|
+
throw new SboxError('WIKI_PATH', 'Для новой страницы укажите относительный путь .md');
|
|
230
|
+
if (fs.existsSync(this.safe(file)))
|
|
231
|
+
throw new SboxError('WIKI_EXISTS', `Страница уже существует: ${file}`);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
const current = this.resolve(ref, pages);
|
|
235
|
+
file = current.file;
|
|
236
|
+
if (!options.ifMatch || current.revision !== options.ifMatch)
|
|
237
|
+
throw new SboxError('WIKI_CONFLICT', 'Нужна текущая revision из get в --if-match. Перечитайте страницу и примените правку к новой версии.');
|
|
238
|
+
}
|
|
239
|
+
const candidate = parsePage(file, content);
|
|
240
|
+
const diagnostics = this.validate([...pages.filter(p => p.file !== file), candidate]);
|
|
241
|
+
if (diagnostics.some(d => d.severity === 'error'))
|
|
242
|
+
throw new SboxError('WIKI_INVALID', JSON.stringify(diagnostics));
|
|
243
|
+
const target = this.safe(file);
|
|
244
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
245
|
+
const temp = `${target}.${randomUUID()}.tmp`;
|
|
246
|
+
try {
|
|
247
|
+
fs.writeFileSync(temp, content, { flag: 'wx', mode: fs.existsSync(target) ? fs.statSync(target).mode : 0o644 });
|
|
248
|
+
// Повторная проверка также ловит правку обычным редактором во время валидации.
|
|
249
|
+
if (!options.create && hash(fs.readFileSync(target, 'utf8')) !== options.ifMatch)
|
|
250
|
+
throw new SboxError('WIKI_CONFLICT', 'Страница изменилась во время записи');
|
|
251
|
+
if (options.create) {
|
|
252
|
+
fs.linkSync(temp, target);
|
|
253
|
+
}
|
|
254
|
+
else
|
|
255
|
+
fs.renameSync(temp, target);
|
|
256
|
+
}
|
|
257
|
+
finally {
|
|
258
|
+
fs.rmSync(temp, { force: true });
|
|
259
|
+
}
|
|
260
|
+
return { ...pageSummary(candidate), diagnostics };
|
|
261
|
+
}
|
|
262
|
+
finally {
|
|
263
|
+
fs.closeSync(fd);
|
|
264
|
+
fs.rmSync(lock, { force: true });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/wiki/store.ts"],"names":[],"mappings":"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"}
|
package/docs/design.md
CHANGED
|
@@ -463,7 +463,7 @@ runs:
|
|
|
463
463
|
|
|
464
464
|
Папка `.sbox/wiki/` хранит долговечные знания о коде, которые не помещаются в категории выше: механизмы, инварианты, подводные камни по областям. Страницы имеют тот же фронтматтер, роутер `sbox route --path | --query` возвращает план чтения из одной-двух страниц, линтер проверяет структуру. Роль distiller после мержа переносит записи `[CODE]` и `[RULE]` из `log.md` в wiki по правилам допуска: запись должна отвечать на повторяющийся вопрос и предотвращать класс ошибок, а не пересказывать один файл.
|
|
465
465
|
|
|
466
|
-
|
|
466
|
+
Индекс страниц (summary, read_when, source_roots) входит в пакет каждой роли, роль читает страницы с подходящим read_when. Отдельный инструмент `sbox-wiki` предоставляет индекс, лексический поиск с учётом путей, чтение и запись страниц, обратные ссылки и валидацию (раздел 16). Роутер с бюджетом контекста и дистилляция остаются расширениями.
|
|
467
467
|
|
|
468
468
|
### Метрики решателя
|
|
469
469
|
|
|
@@ -851,3 +851,26 @@ packages/
|
|
|
851
851
|
| 6. Расширения | Схема `bugfix` с причинным контрактом и RED-оракулом, wiki и дистилляция, шина событий для Arcadia (адаптер OpenSpec реализован досрочно) | Порядок определяют потребности пилотов |
|
|
852
852
|
|
|
853
853
|
Каждый этап заканчивается изменением в реальном проекте, а не демонстрацией на образце.
|
|
854
|
+
|
|
855
|
+
## 16. Отдельный инструмент wiki (реализовано)
|
|
856
|
+
|
|
857
|
+
`sbox-wiki` — отдельный бинарник в пакете, по аналогии с `sbox-browser`. Модуль `src/wiki` не требует состояния изменения или инициализации SDD: `--dir` выбирает произвольную папку Markdown, `--cwd` задаёт рабочий каталог. Без `--dir` используется `project.wiki` ближайшего проекта SDD, иначе `wiki/` в рабочем каталоге. Адаптер `src/core/wiki.ts` использует этот же модуль для пакетов ролей и диагностики `sbox doctor`.
|
|
858
|
+
|
|
859
|
+
### Контракт
|
|
860
|
+
|
|
861
|
+
- `index [--rebuild]` возвращает карточки всех Markdown-страниц, включая README: id (по умолчанию относительный путь без `.md`), заголовок, summary, read_when, source_roots, areas, revision и заголовки разделов с якорями. Текст страниц не включается. В пакетах SDD сохраняется прежнее исключение README.
|
|
862
|
+
- `search [query] [--path путь] [--limit N]` ищет без учёта регистра по тексту, заголовку, summary, read_when и areas. Совпадения в метаданных имеют больший вес; пересечение с source_roots повышает позицию. Возвращаются причины, оценка и фрагмент до 300 символов. Поиск лексический, без embeddings, морфологии или автоматического подбора синонимов; --path не является строгим фильтром. Лимит — от 1 до 100, по умолчанию 5.
|
|
863
|
+
- `get <id|путь.md> [--section заголовок|якорь]` возвращает полный Markdown с фронтматтером или выбранный раздел с вложенными подразделами. JSON всегда содержит SHA-256 revision всей страницы; для обновления нужно прочитать полную страницу.
|
|
864
|
+
- `put <id|путь.md> --file файл --if-match revision` сохраняет полную страницу, `--file -` читает stdin. Новая страница создаётся по относительному пути `.md` с `--create`. Устаревшая или отсутствующая revision отклоняется. Записи инструмента сериализуются блокировкой папки; файл заменяется атомарно. Правки сторонним редактором проверяются повторно перед заменой, но редактор не участвует в блокировке: полной транзакционной гарантии против произвольного внешнего процесса нет.
|
|
865
|
+
- `backlinks <id|путь.md>` возвращает входящие ссылки, включая ссылки на разделы.
|
|
866
|
+
- `validate` проверяет типы метаданных, уникальность непустых id, относительные Markdown-ссылки и якоря. summary/read_when и отсутствующие source_roots дают предупреждения. Битые ссылки, ссылки за пределы wiki, дубликаты id и некорректные метаданные дают ошибки и код выхода 1. put проверяет всю будущую wiki до записи: удаление заголовка с входящими ссылками запрещено. Для согласованной правки нескольких страниц используются обычные файлы с последующим validate.
|
|
867
|
+
|
|
868
|
+
Ссылки разбираются Markdown-парсером (markdown-it), включая reference links; кодовые примеры не образуют рёбра. Якорь строится из текста заголовка: нижний регистр, буквы/цифры/комбинируемые знаки/дефисы/подчёркивания, пробелы заменены дефисами; повторы получают суффикс `-1`, `-2`. Поддерживаются ATX и Setext. Пользовательские HTML-якоря и HTML-ссылки не поддерживаются. Локальные изображения и вложения проверяются на существование, якоря проверяются для Markdown-страниц. Внешние URL не загружаются. Символические ссылки исключаются из обхода, чтение/запись через них запрещены.
|
|
869
|
+
|
|
870
|
+
### Индекс и авторство
|
|
871
|
+
|
|
872
|
+
Markdown остаётся источником истины. Кеш хранится в системной временной папке пользователя, вне репозитория, с правами каталога 0700 и файла 0600. Содержит метаданные, разобранные ссылки, заголовки и текст для поиска. При каждом обращении сравниваются список файлов и stat (mtime, ctime, размер, inode); перечитываются только изменённые страницы, удалённые исчезают из индекса. Кеш можно удалить или пересобрать `index --rebuild`; отсутствие права записать кеш не препятствует чтению.
|
|
873
|
+
|
|
874
|
+
summary и read_when пишет автор или агент: CLI не генерирует смысловые описания. При обновлении текста автор пересматривает метаданные. revision — версия содержимого, а не свидетельство истинности; автоматическое определение устаревания по коду, семантический поиск и дистилляция остаются расширениями этапа 6.
|
|
875
|
+
|
|
876
|
+
Все команды поддерживают `--json`: результат `{ok:true,data:...}`, ошибка команды `{ok:false,error:{code,message}}`; validate возвращает диагностики в data и код выхода 1 при ошибках. Скилл `assets/skills/sbox-wiki.md` устанавливается обоим хостам и подключается всем ролям; право записи ограничивается полномочиями роли. Wiki-шаблон хранится в `assets/project/wiki.README.md`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spec-box/sdd",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "@spec-box/sdd: автономная реализация продуктовых фич ИИ-агентами",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
},
|
|
15
15
|
"bin": {
|
|
16
16
|
"sbox": "bin/sbox.js",
|
|
17
|
-
"sbox-browser": "bin/sbox-browser.js"
|
|
17
|
+
"sbox-browser": "bin/sbox-browser.js",
|
|
18
|
+
"sbox-wiki": "bin/sbox-wiki.js"
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
21
|
"bin",
|
|
@@ -40,12 +41,14 @@
|
|
|
40
41
|
"@puppeteer/browsers": "^3.2.3",
|
|
41
42
|
"commander": "^15.0.0",
|
|
42
43
|
"fast-glob": "^3.3.3",
|
|
44
|
+
"markdown-it": "^15.0.2",
|
|
43
45
|
"picomatch": "^4.0.7",
|
|
44
46
|
"puppeteer-core": "^25.12.0",
|
|
45
47
|
"yaml": "^2.9.0",
|
|
46
48
|
"zod": "^4.6.2"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
51
|
+
"@types/markdown-it": "^14.2.0",
|
|
49
52
|
"@types/node": "^22.20.2",
|
|
50
53
|
"@types/picomatch": "^4.0.3",
|
|
51
54
|
"tsx": "^4.23.13",
|