@nitra/cursor 1.29.5 → 1.32.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/CHANGELOG.md +40 -0
- package/package.json +1 -1
- package/rules/ci4/ci4.mdc +89 -50
- package/rules/ci4/js/data/marksman_config/marksman.baseline.toml +27 -0
- package/rules/ci4/js/marksman_config.mjs +52 -0
- package/rules/ci4/policy/vscode_extensions/target.json +4 -0
- package/rules/ci4/policy/vscode_extensions/template/extensions.json.snippet.json +3 -0
- package/rules/ci4/policy/vscode_extensions/vscode_extensions.rego +12 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,46 @@
|
|
|
4
4
|
|
|
5
5
|
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
6
6
|
|
|
7
|
+
## [1.32.0] - 2026-05-30
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`rules/ci4/js/marksman_config.mjs`** + **`rules/ci4/js/data/marksman_config/marksman.baseline.toml`** — новий JS-концерн `marksman_config` за зразком `test.stryker_config`: при `npx @nitra/cursor fix ci4` копіює canonical `.marksman.toml` baseline у корінь cwd, якщо файлу ще немає. Idempotent через паттерн `ensureBaselineFile` (existsSync → pass+skip vs copyFile → pass+create) — ручні правки користувача між прогонами зберігаються, повторний прогон не перетирає. Baseline містить три ключові опції: `[core] markdown.glfm = true` (GLFM-фічі portable subset — alerts/таблиці/todo), `[completion] wiki.style = "file-stem"` (ADR slug == ім'я файла; стабільний ідентифікатор у AUTOGEN `sources`/manifest/валідаторі — заголовок міняється, посилання не ламається), `[code_action] toc.enable = true` (Insert/Update TOC code action для довгих arc42-сторінок). Дефолти marksman (`title-slug-ref` + вимкнений GLFM) ламали б частину задокументованої навігації. Розміщення в `cwd` (корені репо) робить весь монорепо одним marksman-workspace — README.md і docs/ перехресно навігуються. Тести: `+4` сценарії у `rules/ci4/js/tests/marksman_config.test.mjs` через `withTmpDir` (порожній cwd → файл створюється; idempotency — кастомний контент не перетирається; валідні TOML-секції `[core]`/`[completion]`/`[code_action]`; exit 0 у обох сценаріях). 4/4 PASS через `bunx vitest run rules/ci4/js/tests/marksman_config.test.mjs`.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- **`rules/ci4/ci4.mdc`** (`version` 3.1 → 3.2) — у секцію «Viewer/editor: Zed + marksman LSP» додано параграф про авто-створення `.marksman.toml` правилом ci4 з посиланням на canonical baseline і поясненням кожної з трьох ключових опцій (glfm/wiki.style/toc.enable). У frontmatter `description` додано пункт про `.marksman.toml`. Дзеркало `.cursor/rules/n-ci4.mdc` синхронізується наступним прогоном `npx @nitra/cursor`.
|
|
16
|
+
|
|
17
|
+
## [1.31.0] - 2026-05-30
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **`rules/ci4/policy/vscode_extensions/`** — нова policy за зразком text/style-lint/rego/ga/js-lint/graphql/nginx-default-tpl/rust/tauri: `vscode_extensions.rego` (deny якщо рекомендація з template-snippet відсутня в `.vscode/extensions.json`) + `vscode_extensions_test.rego` (5 сценаріїв: canonical, missing marksman, empty recommendations, extra recommendations пропускаються, drift-test що канон керується через `data.template`) + `template/extensions.json.snippet.json` (`{"recommendations": ["arr.marksman"]}`) + `target.json` (single `.vscode/extensions.json`). Призначення — контрибʼютори, що працюють у VSCode/Cursor замість Zed, отримують той самий шар marksman-навігації (cmd+click по `[link](file.md)`/`[[wiki-link]]`, find-references, refactor-перейменування заголовків) через офіційне розширення marksman LSP. Дзеркальна правка у репо: `.vscode/extensions.json` отримав `arr.marksman` у `recommendations`. Тести: 5/5 PASS через `opa test npm/rules/ci4/policy/vscode_extensions/`.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **`rules/ci4/ci4.mdc`** (`version` 3.0 → 3.1) — у секцію «Viewer/editor: Zed + marksman LSP» додано підсекцію **«VSCode-альтернатива»** з канонічним JSON-блоком `.vscode/extensions.json` (`recommendations: ["arr.marksman"]`) і посиланням на snippet-файл policy (за стилем `text.mdc`); також згадка про marksman-сумісні редактори (Neovim, Helix, Emacs). У frontmatter `description` додано пункт про VSCode-розширення. Дзеркало `.cursor/rules/n-ci4.mdc` синхронізується наступним прогоном `npx @nitra/cursor`.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **`vitest.config.js`** — git-залежні тести (`rules/changelog/check.test.mjs`, `rules/ga/workflows.test.mjs`) масово таймаутили локально (`23 failed | 13 passed`, 187s; усі фейли — `Test timed out in 5000ms`, не assertion), хоча в CI зелені. Першопричина: глобальний `~/.gitconfig` тестової машини має `trace2.eventtarget=af_unix:stream:~/.git-ai/.../trace2.sock` (tooling `git-ai`), який успадковується tmp-репо в тестах → кожна git-команда під'єднується до Unix-сокета даемона; коли даемон деградований, запис у сокет блокується (~1s/команда не на CPU), а під `pool: 'forks'` десятки паралельних git-операцій × латентність > 5000ms `testTimeout`. Фікс: `env: { GIT_TRACE2_EVENT: '0' }` прибирає trace2-залежність із гарячого шляху тестового git (root-cause), плюс `testTimeout: 20000` як defence-in-depth проти будь-якої залишкової локальної I/O-латентності. Після фіксу `bun run vitest run rules/changelog/` → `36 passed` за ~7s (відтворювано); повний suite — `1248 passed | 2 skipped`. CI не зачеплено (там немає trace2-таргета).
|
|
30
|
+
|
|
31
|
+
## [1.30.1] - 2026-05-29
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **`rules/test/coverage/tests/coverage.test.mjs`** — три нові тести `/n-coverage-fix`-ітерації, що вбивають усі чотири вцілілі мутанти на `rules/test/coverage/coverage.mjs`. (1) `opts.fix=false → fixSurvivedMutants НЕ викликається` і (2) `opts.fix=true → fixSurvivedMutants викликається` фіксують умовну гілку `if (opts.fix)` (L189) через лог `'✓ Всі мутанти вбиті — доповнення тестів не потрібне'`, який друкує `fixSurvivedMutants` для порожнього `survived[]`. (3) `source 2-ї стрілки містить fix:false` перевіряє джерело захопленої callback-стрілки 2-го `withLock` через `Function.prototype.toString()`: токени `fix` і `false` мають бути присутні, а `fix: true` — заборонений; це поведінково невловимо (`{}` і `{ fix: false }` дають однаковий falsy `opts.fix`), тому інваріант на рівні джерела.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- **`CHANGELOG.md`** — заголовок секції `[1.30.0]` піднято з `#` на `##` (Keep a Changelog vN.M.M вимагає H2 для версій). Чек `npm-module.mdc` зчитував h1 як «без версії», знаходив `[1.29.5]` першою і скаржився на розбіжність із `package.json#version "1.30.0"`.
|
|
40
|
+
|
|
41
|
+
## [1.30.0] - 2026-05-29
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **`rules/ci4/ci4.mdc`** (`version` 2.1 → 3.0) — viewer-story повністю переписано під **Zed + marksman LSP без site-generator-а**. MkDocs Material і pymdownx-розширення (`!!! note`, `??? engineer`, `=== "tab"`, кастомні audience-CSS) прибрані як рекомендація: їх не рендерить вбудований MD-preview Zed, що ламає принцип «відкрив файл = бачу фінальний вигляд». Collapsible-блоки для змішаної аудиторії — через нативний HTML5 `<details>` / `<summary>`, що рендериться скрізь (Zed preview, GitHub, будь-який майбутній збирач) без розширень парсера. Введено **portable-only subset**: CommonMark + GFM + Mermaid у fenced code + KaTeX + `<details>`; заборонені VitePress containers (`::: tip`), MDX/Astro-компоненти, Hugo shortcodes, AsciiDoc-вкраплення, RST-директиви. Конвенція маркера у `<summary>`: перше слово — аудиторія з фіксованого словника (`Engineer:`/`Ops:`/`Security:`/`Manager:`) → детермінований regex для валідатора. Валідатор отримав чотири нові перевірки: жоден `Engineer:`/`Ops:`/`Security:` блок у manager-only проекціях; кожен `<details>` має оточуючі порожні рядки (інакше `<summary>` рендериться як plain HTML); у `docs/` немає заборонених framework-specific конструкцій; inter-doc посилання працюють для marksman LSP (відносні шляхи або wiki-links). Промпт-скелет LLM-проекцій оновлено — генератор видає `<details>`, не `???`, і дотримується списку заборонених синтаксисів. Subset **forward-compatible**: будь-який збирач (MkDocs, VitePress, Antora) підключається пізніше без переписування контенту. Дзеркало `.cursor/rules/n-ci4.mdc` синхронізується наступним прогоном `npx @nitra/cursor`.
|
|
46
|
+
|
|
7
47
|
## [1.29.5] - 2026-05-29
|
|
8
48
|
|
|
9
49
|
### Added
|
package/package.json
CHANGED
package/rules/ci4/ci4.mdc
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Архітектурна документація продукту — Markdown як джерело істини; рекомендований стек arc42 + Diátaxis + ADR (MADR v4, формат описаний у правилі `adr`) + C4 як набір нотацій; гібридна модель manual + autogen-зон, що регенеруються з accepted ADR;
|
|
2
|
+
description: Архітектурна документація продукту — Markdown як джерело істини; рекомендований стек arc42 + Diátaxis + ADR (MADR v4, формат описаний у правилі `adr`) + C4 як набір нотацій; гібридна модель manual + autogen-зон, що регенеруються з accepted ADR; Zed + marksman LSP як viewer без site-generator-а, portable subset (CommonMark + GFM + Mermaid + KaTeX), collapsible engineer-блоки через нативний `<details>`; рекомендоване VSCode-розширення `arr.marksman` для контрибʼюторів поза Zed; `.marksman.toml` авто-створюється у корені проєкту з canonical baseline
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '2
|
|
4
|
+
version: '3.2'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Архітектурна документація проєкту живе у Markdown поряд із кодом. Це не довідник «для людей із порталу архітектора» — це **джерело істини**, з якого LLM-агент і людина читають намір системи перед будь-якою зміною коду. Тому правила нижче — не оформлення, а робочий процес: який стек використовуємо, як зберігаємо рішення, як автоматично перегенеровуємо проекції з ADR і як рендеримо для змішаної аудиторії (менеджери + інженери + ops).
|
|
@@ -47,7 +47,7 @@ RAG витягує **фрагменти**, не цілі документи. Т
|
|
|
47
47
|
|
|
48
48
|
Доповнюємо **під domain**:
|
|
49
49
|
|
|
50
|
-
- **DDD Context Maps** — коли є >1 bounded context (типово для multi-agent: agents, orchestration, memory, tooling). Одна Mermaid-діаграма в `explanation/architecture.md`, ховається під
|
|
50
|
+
- **DDD Context Maps** — коли є >1 bounded context (типово для multi-agent: agents, orchestration, memory, tooling). Одна Mermaid-діаграма в `explanation/architecture.md`, ховається під `<details><summary><strong>Engineer:</strong> Context Map</summary>`.
|
|
51
51
|
- **EventModeling** — для event-driven систем (агентські pipeline, CQRS, Event Sourcing). Структура: trigger → command → event → read model. Читається менеджером як наратив, інженером — як креслення.
|
|
52
52
|
- **Business Capability Map** — верхньорівневий manager-overview. Autogen через семантичну класифікацію accepted ADR за тематикою.
|
|
53
53
|
- **Wardley Map** — стратегічний артефакт для board/інвесторів. Manual, не autogen. Квартальне оновлення. Живе в `explanation/strategy.md`.
|
|
@@ -108,7 +108,7 @@ docs/
|
|
|
108
108
|
|
|
109
109
|
## Гібрид manual + autogen
|
|
110
110
|
|
|
111
|
-
Реальні проєкти мають legacy docs, написані до появи ADR. Розв'язок — **зони** через HTML-коментарі (виживають у Markdown, не рендеряться у
|
|
111
|
+
Реальні проєкти мають legacy docs, написані до появи ADR. Розв'язок — **зони** через HTML-коментарі (виживають у Markdown, не рендеряться у жодному MD viewer — ні в Zed built-in preview, ні на GitHub, ні в будь-якому майбутньому site-generator-і):
|
|
112
112
|
|
|
113
113
|
```markdown
|
|
114
114
|
# User Service
|
|
@@ -191,61 +191,80 @@ User Service відповідає за автентифікацію та про
|
|
|
191
191
|
- **Incremental**: LLM отримує поточний doc + новий ADR (або `## Update`) — видає diff. Дешевше, але дрейф накопичується.
|
|
192
192
|
- **Компроміс**: incremental + періодичний full rebuild (раз на місяць або після N нових ADR).
|
|
193
193
|
|
|
194
|
-
##
|
|
194
|
+
## Viewer/editor: Zed + marksman LSP
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
Окремого site-generator-а **немає** — каталог `docs/` сам є інтерфейсом читання. Інженер відкриває `.md`-файл у Zed і одразу бачить рендер через built-in preview (`cmd+shift+m`). Між сторінками рухається через **`marksman`** LSP: `cmd+click` по `[link](file.md)` і `[[wiki-link]]`, автокомпліт заголовків, find-references, refactor-перейменування заголовків з оновленням посилань у всьому `docs/`.
|
|
197
197
|
|
|
198
|
-
|
|
198
|
+
`~/.config/zed/settings.json`:
|
|
199
199
|
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"languages": {
|
|
203
|
+
"Markdown": {
|
|
204
|
+
"language_servers": ["marksman"],
|
|
205
|
+
"soft_wrap": "editor_width"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**`.marksman.toml`** у корені проєкту авто-створюється правилом ci4 при першому `npx @nitra/cursor fix ci4` із canonical baseline ([data/marksman_config/marksman.baseline.toml](./js/data/marksman_config/marksman.baseline.toml)). Ключові опції — `markdown.glfm = true` (потрібен для GFM-alerts/таблиць/todo з portable subset), `[completion] wiki.style = "file-stem"` (ADR slug == ім'я файла, стабільний ідентифікатор у AUTOGEN `sources`/manifest/валідаторі — заголовок змінюється, посилання не ламається), `[code_action] toc.enable = true` (TOC code action для довгих arc42-сторінок). Без явного конфіга marksman використовує `title-slug-ref` і вимкнений GLFM — частина задокументованої навігації працювала б інакше. Ручні правки конфіга не перетираються — `ensureBaselineFile` ідемпотентний.
|
|
206
212
|
|
|
207
|
-
|
|
208
|
-
- admonition
|
|
209
|
-
- pymdownx.details
|
|
210
|
-
- pymdownx.superfences
|
|
211
|
-
- pymdownx.tabbed: { alternate_style: true }
|
|
212
|
-
- attr_list
|
|
213
|
+
**VSCode-альтернатива.** Контрибʼютори, що працюють у VSCode/Cursor замість Zed, отримують той самий шар навігації через офіційне розширення marksman LSP. Канонічний запис у `.vscode/extensions.json`:
|
|
213
214
|
|
|
214
|
-
|
|
215
|
-
|
|
215
|
+
```json title=".vscode/extensions.json"
|
|
216
|
+
{
|
|
217
|
+
"recommendations": ["arr.marksman"]
|
|
218
|
+
}
|
|
216
219
|
```
|
|
217
220
|
|
|
218
|
-
|
|
221
|
+
Канон `recommendations` (substring requirement): [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json). Інші marksman-сумісні редактори (Neovim, Helix, Emacs) налаштовують `marksman` як LSP-сервер за документацією свого редактора — поведінка ідентична (cmd+click по `[link](file.md)`/`[[wiki-link]]`, find-references, refactor-перейменування).
|
|
222
|
+
|
|
223
|
+
**Portable-only синтаксис.** Усе, що пишемо в `docs/`, обмежене **CommonMark + GFM + Mermaid у fenced code (` ```mermaid `) + KaTeX (`$...$`) + нативний HTML5 `<details>`**. Заборонено:
|
|
224
|
+
|
|
225
|
+
- pymdownx admonitions (`!!! note`, `??? engineer`, `=== "tab"`)
|
|
226
|
+
- VitePress containers (`::: tip`, `::: details`)
|
|
227
|
+
- MDX/Astro-компоненти (`<MyComponent />`)
|
|
228
|
+
- Hugo shortcodes (`{{< youtube id >}}`)
|
|
229
|
+
- AsciiDoc-вкраплення, RST-директиви
|
|
230
|
+
|
|
231
|
+
Усе вище не рендериться у Zed built-in preview і ламає головний принцип: **«відкрив файл = побачив фінальний вигляд»**. Обмеження **forward-compatible**: portable subset рендериться у GitHub, MkDocs, VitePress, Antora — підключення збирача в майбутньому не потребує переписування контенту.
|
|
232
|
+
|
|
233
|
+
## Collapsible-блоки для змішаної аудиторії
|
|
234
|
+
|
|
235
|
+
Менеджер читає прозу зверху, інженер розгортає деталі. Реалізація — нативний HTML5 `<details>` / `<summary>`, що рендериться **скрізь**: Zed preview, GitHub, будь-який майбутній збирач. Жодних розширень парсера не треба.
|
|
219
236
|
|
|
220
237
|
```markdown
|
|
221
238
|
User Service автентифікує користувачів і керує профілями.
|
|
222
239
|
Підтримуємо OIDC-логін та email/password.
|
|
223
240
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
241
|
+
<details>
|
|
242
|
+
<summary><strong>Engineer:</strong> Технічна реалізація автентифікації</summary>
|
|
243
|
+
|
|
244
|
+
OIDC-сервер на Fastify з PKCE flow [oidc-pkce-flow].
|
|
245
|
+
Refresh-токени з rotation, TTL 30 днів, Redis storage.
|
|
246
|
+
|
|
247
|
+
</details>
|
|
227
248
|
|
|
228
249
|
Профілі зберігаються в основній БД, кешуються в Redis на 5 хв.
|
|
229
250
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
251
|
+
<details>
|
|
252
|
+
<summary><strong>Ops:</strong> Деталі кешу та інвалідації</summary>
|
|
253
|
+
|
|
254
|
+
Cache key: `user:profile:{userId}:v2`.
|
|
255
|
+
Інвалідація — NATS подія `user.profile.updated` [user-profile-events].
|
|
256
|
+
|
|
257
|
+
</details>
|
|
233
258
|
```
|
|
234
259
|
|
|
235
|
-
|
|
260
|
+
**Конвенція маркера у `<summary>`:** перше слово — аудиторія з фіксованого словника (`Engineer:`, `Ops:`, `Security:`, `Manager:`), далі — описова назва. Це дає валідатору детермінований regex для перевірок типу «жоден `Engineer:`-блок не з'являється в manager-only проекціях».
|
|
236
261
|
|
|
237
|
-
|
|
262
|
+
**Технічні нюанси `<details>`:**
|
|
238
263
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
.md-typeset details.ops > summary {
|
|
245
|
-
background-color: rgba(255, 152, 0, 0.1);
|
|
246
|
-
border-color: #ff9800;
|
|
247
|
-
}
|
|
248
|
-
```
|
|
264
|
+
- порожній рядок до `<details>` і після `<summary>` обов'язковий — інакше Markdown-парсер не активує блочний рендер усередині
|
|
265
|
+
- за замовчуванням блок згорнутий; `<details open>` — розгорнутий
|
|
266
|
+
- візуальна типізація аудиторій робиться **через текст `<summary>`**, не через CSS — у Zed preview кастомні стилі недоступні
|
|
267
|
+
- `<details>` ≠ HTML-обгортка з правила «жодних `<div>`/`<span>`»: це **семантичний** HTML5-елемент, а не презентаційний; його token-cost мізерний
|
|
249
268
|
|
|
250
269
|
## Промпт для LLM-проекцій
|
|
251
270
|
|
|
@@ -259,21 +278,35 @@ User Service автентифікує користувачів і керує п
|
|
|
259
278
|
як пов'язано з іншими частинами продукту. Без технологій, версій, коду.
|
|
260
279
|
|
|
261
280
|
2. Технічні деталі — тільки всередині блоків:
|
|
262
|
-
|
|
263
|
-
|
|
281
|
+
<details>
|
|
282
|
+
<summary><strong>Engineer:</strong> Описова назва блоку</summary>
|
|
283
|
+
|
|
284
|
+
Код, конфіги, версії, посилання на ADR.
|
|
285
|
+
|
|
286
|
+
</details>
|
|
264
287
|
|
|
265
288
|
3. Operational деталі:
|
|
266
|
-
|
|
289
|
+
<details>
|
|
290
|
+
<summary><strong>Ops:</strong> Що моніторити та як реагувати</summary>
|
|
291
|
+
|
|
292
|
+
Метрики, алерти, runbook-кроки.
|
|
293
|
+
|
|
294
|
+
</details>
|
|
267
295
|
|
|
268
296
|
Правила:
|
|
269
|
-
- Якщо прибрати всі
|
|
270
|
-
-
|
|
297
|
+
- Якщо прибрати всі <details>-блоки, текст лишається зв'язним менеджерським документом.
|
|
298
|
+
- Перше слово у <summary> — аудиторія з фіксованого словника
|
|
299
|
+
(Engineer:/Ops:/Security:/Manager:), далі — описова назва
|
|
300
|
+
(наприклад «<strong>Engineer:</strong> Чому Percona, а не MariaDB»).
|
|
301
|
+
- Порожній рядок до і після вмісту <details> обов'язковий.
|
|
302
|
+
- Кожен факт з ADR маркуй [<slug>] всередині <details>-блоку — slug це ім'я clean ADR
|
|
271
303
|
без розширення (наприклад `[ланцюжок-запуску-abie]`).
|
|
272
|
-
- Назви блоків — описові («Чому Percona, а не MariaDB»).
|
|
273
304
|
- НЕ виходь за межі <!-- AUTOGEN:start --> ... <!-- AUTOGEN:end -->.
|
|
274
305
|
- ADR без рядка `**Status:** Accepted` ігноруй.
|
|
275
306
|
- Якщо в ADR є `## Update YYYY-MM-DD` секції — враховуй найсвіжіший стан рішення,
|
|
276
307
|
старі формулювання вважай застарілими.
|
|
308
|
+
- Заборонені framework-specific synaxes: !!! note, ??? engineer, ::: tip,
|
|
309
|
+
MDX-компоненти, Hugo shortcodes — тільки CommonMark + GFM + Mermaid + <details>.
|
|
277
310
|
```
|
|
278
311
|
|
|
279
312
|
## Типові поломки LLM і захист
|
|
@@ -293,7 +326,10 @@ User Service автентифікує користувачів і керує п
|
|
|
293
326
|
- Усі `[<slug>]` посилання вказують на існуючі файли `docs/adr/<slug>.md` із рядком `**Status:** Accepted`
|
|
294
327
|
- Усі `AUTOGEN:start` мають парний `AUTOGEN:end` з тим самим `id`
|
|
295
328
|
- Hash у `manifest.json` відповідає фактичному контенту зон
|
|
296
|
-
- Жоден
|
|
329
|
+
- Жоден `<details>`-блок з `<summary>` що починається на `Engineer:` / `Ops:` / `Security:` не з'являється в manager-only проекціях
|
|
330
|
+
- Кожен `<details>` має оточуючі порожні рядки (інакше `<summary>`-вміст рендериться як plain HTML, не collapsible)
|
|
331
|
+
- У `docs/` немає заборонених framework-specific конструкцій: `!!! note`, `??? `, `::: tip`, `::: details`, MDX-теги `<[A-Z][a-zA-Z]*`, Hugo shortcodes `{{< `
|
|
332
|
+
- Усі inter-doc посилання працюють для `marksman` LSP (відносні шляхи `[text](./other.md)` або `[[wiki-link]]`, не absolute URLs усередині `docs/`)
|
|
297
333
|
- Якщо в зоні згадано компонент — він є в `docs/glossary.md`
|
|
298
334
|
- ADR без `**Status:** Accepted` не потрапили у проекцію
|
|
299
335
|
|
|
@@ -317,7 +353,7 @@ ADR (`docs/adr/<slug>.md`) — джерело правди для autogen-про
|
|
|
317
353
|
|
|
318
354
|
## Зв'язок із документацією
|
|
319
355
|
|
|
320
|
-
Архітектурні артефакти — частина **користувацької документації**, а не закритий артефакт для команди. Контекстна діаграма (C4 рівень 1) і контейнерна (рівень 2) живуть там, де читач шукає вступ у проєкт — у `explanation/architecture.md`, не у відокремленій теці «for-architects».
|
|
356
|
+
Архітектурні артефакти — частина **користувацької документації**, а не закритий артефакт для команди. Контекстна діаграма (C4 рівень 1) і контейнерна (рівень 2) живуть там, де читач шукає вступ у проєкт — у `explanation/architecture.md`, не у відокремленій теці «for-architects». Нативний `<details>`-блок дає collapsible-вигляд у будь-якому MD-viewer (Zed built-in preview, GitHub web UI, потенційний майбутній site-generator) без залежності від конкретного фреймворку — менеджер бачить прозу, інженер розгортає деталі.
|
|
321
357
|
|
|
322
358
|
## Зв'язок із `.cursor/rules`
|
|
323
359
|
|
|
@@ -330,8 +366,11 @@ ADR (`docs/adr/<slug>.md`) — джерело правди для autogen-про
|
|
|
330
366
|
- **Claude Code** як runner — slash-команда `/regen-docs` або post-commit hook на зміни `docs/adr/**`
|
|
331
367
|
- **capture-decisions.sh** + **normalize-decisions.sh** — Stop-hooks створення ADR (керує правило `adr`)
|
|
332
368
|
- **gray-matter** на Bun — лише для парсингу draft frontmatter; clean ADR парситься regexp по `**Status:**` / `**Date:**`
|
|
333
|
-
- **
|
|
334
|
-
- **
|
|
369
|
+
- **Zed** як viewer/editor — built-in MD preview (`cmd+shift+m`) рендерить кожен файл без site-generator-а; `<details>` для collapsible-блоків
|
|
370
|
+
- **marksman** LSP як шар навігації — `cmd+click` по `[text](file.md)`/`[[wiki-link]]`, find-references, refactor-перейменування заголовків
|
|
371
|
+
- **Mermaid** для C4-діаграм, EventModeling, Context Maps — рендериться у Zed preview напряму з ` ```mermaid ` fenced code, без розширень
|
|
372
|
+
- **KaTeX** (опційно) — інлайн-математика `$...$` для метрик/формул; рендериться у Zed preview
|
|
373
|
+
- Site-generator (MkDocs Material / VitePress / Antora) — **не використовується**; portable subset гарантує, що його можна підключити пізніше без переписування контенту
|
|
335
374
|
|
|
336
375
|
## Query mode як бонус
|
|
337
376
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Workspace-маркер marksman LSP. У корені репо робить весь монорепо одним
|
|
2
|
+
# marksman-workspace — README.md і docs/ перехресно навігуються через
|
|
3
|
+
# [text](file.md) і [[wiki-link]]. Файли .mdc не індексуються — marksman
|
|
4
|
+
# дивиться лише на розширення нижче.
|
|
5
|
+
#
|
|
6
|
+
# Створюється правилом ci4 (npx @nitra/cursor fix ci4) із canonical baseline.
|
|
7
|
+
# Ручні правки не перетираються: повторні прогони ідемпотентні (no-op).
|
|
8
|
+
|
|
9
|
+
[core]
|
|
10
|
+
markdown.file_extensions = ["md", "markdown"]
|
|
11
|
+
|
|
12
|
+
# GitHub-Flavored Markdown (таблиці, todo, alerts, math) — наш portable subset.
|
|
13
|
+
markdown.glfm = true
|
|
14
|
+
|
|
15
|
+
[completion]
|
|
16
|
+
# Стиль резолву [[wiki-link]]:
|
|
17
|
+
# "file-stem" → [[oidc-pkce-flow]] резолвиться у docs/adr/oidc-pkce-flow.md
|
|
18
|
+
# "title-slug-ref" → резолв за slugified H1 заголовком
|
|
19
|
+
# Беремо file-stem: ADR-slug == ім'я файла, стабільний ідентифікатор у
|
|
20
|
+
# AUTOGEN sources, manifest, валідаторі. Заголовок може мінятися — посилання
|
|
21
|
+
# не ламається.
|
|
22
|
+
wiki.style = "file-stem"
|
|
23
|
+
|
|
24
|
+
[code_action]
|
|
25
|
+
# Code action "Insert/Update TOC" — корисно для довгих arc42-сторінок
|
|
26
|
+
# (architecture.md з 12 розділами).
|
|
27
|
+
toc.enable = true
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Концерн `marksman_config` правила ci4 (ci4.mdc): копіює canonical
|
|
3
|
+
* `.marksman.toml` baseline у корінь cwd, якщо файлу ще немає.
|
|
4
|
+
*
|
|
5
|
+
* Marksman LSP читає `.marksman.toml` для визначення workspace-роота,
|
|
6
|
+
* GLFM-флага (GitHub-Flavored Markdown), стилю wiki-links і code actions.
|
|
7
|
+
* Дефолти marksman не вмикають GLFM і використовують `title-slug-ref` —
|
|
8
|
+
* але portable subset з ci4.mdc вимагає GLFM (alerts/таблиці/todo) +
|
|
9
|
+
* `file-stem` (ADR slug == ім'я файла). Без явного конфіга частина
|
|
10
|
+
* marksman-функцій працює інакше, ніж задокументовано у правилі.
|
|
11
|
+
*
|
|
12
|
+
* Idempotent: якщо `.marksman.toml` вже існує (навіть з кастомним вмістом)
|
|
13
|
+
* — не перетирається, тільки рапортується факт існування. Ручні правки
|
|
14
|
+
* користувача зберігаються між прогонами.
|
|
15
|
+
*
|
|
16
|
+
* Файл скопійовано в `cwd`, бо marksman визначає workspace-root за
|
|
17
|
+
* розташуванням свого `.marksman.toml`. У корені репо марксман бачить
|
|
18
|
+
* і docs/, і README.md усіх workspaces одним workspace-ом.
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync } from 'node:fs'
|
|
21
|
+
import { copyFile } from 'node:fs/promises'
|
|
22
|
+
import { dirname, join, relative } from 'node:path'
|
|
23
|
+
import { fileURLToPath } from 'node:url'
|
|
24
|
+
|
|
25
|
+
import { createCheckReporter } from '../../../scripts/lib/check-reporter.mjs'
|
|
26
|
+
|
|
27
|
+
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
28
|
+
const MARKSMAN_BASELINE_PATH = join(HERE, 'data', 'marksman_config', 'marksman.baseline.toml')
|
|
29
|
+
const MARKSMAN_TARGET_FILENAME = '.marksman.toml'
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} [cwd] корінь проєкту (default: `process.cwd()` — CLI-сумісність)
|
|
33
|
+
* @returns {Promise<number>} 0 — OK (створено або вже існує), 1 — baseline-файл пакета зламаний
|
|
34
|
+
*/
|
|
35
|
+
export async function check(cwd = process.cwd()) {
|
|
36
|
+
const reporter = createCheckReporter()
|
|
37
|
+
|
|
38
|
+
if (!existsSync(MARKSMAN_BASELINE_PATH)) {
|
|
39
|
+
reporter.fail(`canonical baseline не знайдено (${MARKSMAN_BASELINE_PATH}) — перевстанови @nitra/cursor`)
|
|
40
|
+
return reporter.getExitCode()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const target = join(cwd, MARKSMAN_TARGET_FILENAME)
|
|
44
|
+
if (existsSync(target)) {
|
|
45
|
+
reporter.pass(`${MARKSMAN_TARGET_FILENAME} існує (${relative(cwd, target)})`)
|
|
46
|
+
return reporter.getExitCode()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
await copyFile(MARKSMAN_BASELINE_PATH, target)
|
|
50
|
+
reporter.pass(`${MARKSMAN_TARGET_FILENAME} створено з canonical baseline (${relative(cwd, target)}) (ci4.mdc)`)
|
|
51
|
+
return reporter.getExitCode()
|
|
52
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Перевірка `.vscode/extensions.json` для ci4 (ci4.mdc).
|
|
2
|
+
#
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
package ci4.vscode_extensions
|
|
5
|
+
|
|
6
|
+
import rego.v1
|
|
7
|
+
|
|
8
|
+
deny contains msg if {
|
|
9
|
+
some rec in data.template.snippet.recommendations
|
|
10
|
+
not rec in {r | some r in object.get(input, "recommendations", [])}
|
|
11
|
+
msg := sprintf(".vscode/extensions.json: recommendations має містити %q (ci4.mdc)", [rec])
|
|
12
|
+
}
|