@nitra/cursor 12.11.2 → 12.11.3
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 +6 -0
- package/bin/n-cursor.js +0 -15
- package/package.json +1 -1
- package/rules/bun/docs/index.md +2 -2
- package/rules/bun/docs/main.md +9 -9
- package/rules/bun/js/docs/index.md +3 -2
- package/rules/bun/main.json +1 -1
- package/rules/bun/main.mjs +53 -3
- package/rules/changelog/js/docs/index.md +3 -2
- package/rules/ci4/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/ga/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/graphql/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/js/js/dep-policy.mdc +19 -0
- package/rules/js/js/dep-policy.mjs +14 -6
- package/rules/js/js/docs/index.md +5 -5
- package/rules/js/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/js-run/js/docs/index.md +3 -2
- package/rules/nginx-default-tpl/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/python/docs/index.md +2 -2
- package/rules/python/docs/main.md +12 -10
- package/rules/python/main.mjs +1 -0
- package/rules/rego/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/rust/docs/index.md +2 -2
- package/rules/rust/docs/main.md +8 -6
- package/rules/rust/main.mjs +11 -0
- package/rules/rust/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/style/js/docs/index.md +3 -2
- package/rules/style/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/tauri/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/text/policy/vscode_extensions/docs/index.md +11 -0
- package/scripts/lib/docs/index.md +35 -35
- package/scripts/lib/fix/docs/index.md +12 -10
- package/skills/doc-aggregate/SKILL.md +8 -18
- package/skills/doc-aggregate/js/docs/index.md +0 -1
- package/skills/doc-aggregate/js/docgen-scan.mjs +0 -195
- package/skills/doc-aggregate/js/docs/docgen-scan.md +0 -76
package/CHANGELOG.md
CHANGED
package/bin/n-cursor.js
CHANGED
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
* весь репо (`per-file` ∪ `full`); `--read-only` = без мутацій/LLM (CI); позиційні
|
|
15
15
|
* (не-флаг) аргументи — фільтр правил конформності (мапить колишній `fix <rule>`).
|
|
16
16
|
* CI = `lint --read-only --full` (весь репо, нуль мутацій/LLM).
|
|
17
|
-
* `npx \@nitra/cursor doc-aggregate modules` — JSON-лістинг логічних модулів (межі за `package.json`) для Tier 2 скілу doc-aggregate
|
|
18
17
|
* `npx \@nitra/cursor skill list` — скіли пакета без синку в проєкт
|
|
19
18
|
* `npx \@nitra/cursor skill taze` — промпт на stdout
|
|
20
19
|
* `npx \@nitra/cursor skill cursor taze ["task"]` — Cursor CLI (`cursor-agent -p`)
|
|
@@ -1593,20 +1592,6 @@ try {
|
|
|
1593
1592
|
|
|
1594
1593
|
break
|
|
1595
1594
|
}
|
|
1596
|
-
case 'doc-aggregate': {
|
|
1597
|
-
// n-cursor doc-aggregate modules — детермінований лістинг логічних модулів
|
|
1598
|
-
// (межі за package.json) для Tier 2 module-summary скілу doc-aggregate.
|
|
1599
|
-
// Друкує JSON; module-summary і доменні доки пише скіл, диспатчачи субагентів.
|
|
1600
|
-
const { runDocAggregateModulesCli } = await import('../skills/doc-aggregate/js/docgen-scan.mjs')
|
|
1601
|
-
if (args[0] === 'modules') {
|
|
1602
|
-
process.exitCode = await runDocAggregateModulesCli(args.slice(1))
|
|
1603
|
-
} else {
|
|
1604
|
-
console.error('Usage: npx @nitra/cursor doc-aggregate <modules> [--root <dir>]')
|
|
1605
|
-
process.exitCode = 1
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
|
-
break
|
|
1609
|
-
}
|
|
1610
1595
|
case undefined:
|
|
1611
1596
|
case '': {
|
|
1612
1597
|
await runSync()
|
package/package.json
CHANGED
package/rules/bun/docs/index.md
CHANGED
package/rules/bun/docs/main.md
CHANGED
|
@@ -3,24 +3,24 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/bun/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: a2cfc572
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
-
score:
|
|
8
|
+
score: 90
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Модуль виконує перевірку відповідності коду встановленим політикам, використовуючи маркер повідомлень (bun.mdc). Він також аналізує ліцензії залежностей, спираючись на конфігурацію .licensee.json. Модуль надає функції для запуску перевірок (run) та лінтингу (lint).
|
|
12
14
|
|
|
13
15
|
## Поведінка
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
3. Якщо код виконується як окремий інструмент (standalone), ініціюється повний запуск правила.
|
|
18
|
-
4. Повний запуск правила включає завантаження конфігурацій, застосування білих списків та підбиття підсумків.
|
|
19
|
-
5. Результат виконання повертається як код виходу процесу.
|
|
17
|
+
run виконує перевірку коду, застосовуючи політики та посилання MDC.
|
|
18
|
+
lint виконує перевірку ліцензій npm-залежностей, якщо існує файл .licensee.json у корені проєкту.
|
|
20
19
|
|
|
21
20
|
## Публічний API
|
|
22
21
|
|
|
23
|
-
run —
|
|
22
|
+
run — Основний вхідний пункт правила, який виконує перевірку: застосовує логіку, перевіряє відповідність політикам та згадки в (bun.mdc).
|
|
23
|
+
lint — Інструмент для перевірки ліцензій npm-залежностей у всьому репозиторії, що активується через конфігурацію (.licensee.json).
|
|
24
24
|
|
|
25
25
|
## Гарантії поведінки
|
|
26
26
|
|
package/rules/bun/main.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "auto": { "glob": "package.json" } }
|
|
1
|
+
{ "auto": { "glob": "package.json" }, "lint": "full" }
|
package/rules/bun/main.mjs
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { spawnSync } from 'node:child_process'
|
|
4
|
+
|
|
5
|
+
import { createCheckReporter } from '../../scripts/lib/check-reporter.mjs'
|
|
6
|
+
import { runStandardLint } from '../../scripts/lib/run-standard-lint.mjs'
|
|
7
|
+
import { resolveCmd } from '../../scripts/utils/resolve-cmd.mjs'
|
|
1
8
|
import { isRunAsCli, runRuleCli } from '../../scripts/lib/run-rule-cli.mjs'
|
|
2
9
|
import { runStandardRule } from '../../scripts/lib/run-standard-rule.mjs'
|
|
3
10
|
|
|
4
11
|
/**
|
|
5
12
|
* Єдиний entrypoint правила (ADR 2026-06-21). `run()` — check-поверхня: applies →
|
|
6
|
-
* JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
7
|
-
* (
|
|
8
|
-
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
13
|
+
* JS-concerns → policy → mdc-refs (через runStandardRule). `lint()` — lint-поверхня
|
|
14
|
+
* (licensee — перевірка ліцензій npm-залежностей, лише у `--full`).
|
|
9
15
|
* @param {import('../../scripts/lib/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
10
16
|
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
11
17
|
*/
|
|
@@ -13,6 +19,50 @@ export function run(ctx) {
|
|
|
13
19
|
return runStandardRule(import.meta.dirname, ctx)
|
|
14
20
|
}
|
|
15
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Перевірка ліцензій npm-залежностей через `licensee`. Opt-in: пропускається якщо
|
|
24
|
+
* `.licensee.json` відсутній у cwd (проєкт не налаштував allowlist). `bun x licensee`
|
|
25
|
+
* не потребує локальної установки — bunx завантажує пакет ad-hoc.
|
|
26
|
+
* @param {string} [cwd] корінь проєкту
|
|
27
|
+
* @returns {number} 0 — OK, 1 — порушення
|
|
28
|
+
*/
|
|
29
|
+
function runLicenseeSteps(cwd = process.cwd()) {
|
|
30
|
+
const reporter = createCheckReporter()
|
|
31
|
+
const { pass, fail } = reporter
|
|
32
|
+
|
|
33
|
+
if (!existsSync(join(cwd, '.licensee.json'))) {
|
|
34
|
+
pass('lint-bun: licensee — немає .licensee.json, перевірку ліцензій пропущено')
|
|
35
|
+
return reporter.getExitCode()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const bun = resolveCmd('bun')
|
|
39
|
+
if (!bun) {
|
|
40
|
+
fail('lint-bun: `bun` не знайдено в PATH (bun.mdc)')
|
|
41
|
+
return reporter.getExitCode()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const r = spawnSync(bun, ['x', 'licensee', '--production', '--quiet'], { cwd, stdio: 'inherit', shell: false })
|
|
45
|
+
if (r.status === 0) {
|
|
46
|
+
pass('lint-bun: licensee — ліцензії OK')
|
|
47
|
+
} else {
|
|
48
|
+
const code = typeof r.status === 'number' ? r.status : 1
|
|
49
|
+
fail(`lint-bun: licensee — порушення ліцензій (код ${code}, bun.mdc)`)
|
|
50
|
+
}
|
|
51
|
+
return reporter.getExitCode()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Оркестраторний адаптер `n-cursor lint bun`: licensee-перевірка ліцензій npm-залежностей.
|
|
56
|
+
* Whole-repo (ігнорує `_files`). Opt-in через `.licensee.json` у cwd.
|
|
57
|
+
* @param {string[] | undefined} _files ігнорується
|
|
58
|
+
* @param {string} [cwd] корінь
|
|
59
|
+
* @param {{ readOnly?: boolean }} [_opts] не використовується (licensee завжди read-only)
|
|
60
|
+
* @returns {Promise<number>} exit code
|
|
61
|
+
*/
|
|
62
|
+
export function lint(_files, cwd = process.cwd(), _opts = {}) {
|
|
63
|
+
return runStandardLint(import.meta.dirname, () => runLicenseeSteps(cwd))
|
|
64
|
+
}
|
|
65
|
+
|
|
16
66
|
if (isRunAsCli(import.meta.url)) {
|
|
17
67
|
// Standalone: bun rules/<id>/main.mjs — повний еквівалент `npx @nitra/cursor check <id>`
|
|
18
68
|
// (config-loading + whitelist + summary): library-роль (run) + standalone-роль (CLI-блок).
|
|
@@ -6,6 +6,7 @@ resource: npm/rules/changelog/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/changelog/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
|---|---|
|
|
11
11
|
| [consistency.mjs](consistency.md) | JS Module |
|
|
12
|
+
| [fix-consistency.mjs](fix-consistency.md) | JS Module |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/ci4/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/ci4/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/ci4/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/ga/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/ga/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/ga/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/graphql/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/graphql/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/graphql/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
`@e18e/eslint-plugin` окремо не додавай — він уже в залежностях `@nitra/eslint-config` (з **3.8.0**), oxlint підвантажує його з `node_modules`. Пакети `oxlint`/`eslint`/`jscpd`/`knip` теж не додавай у `devDependencies` без потреби монорепо — `bunx` тягне їх ad-hoc.
|
|
4
4
|
|
|
5
|
+
### Заборона `ua-parser-js`
|
|
6
|
+
|
|
7
|
+
Пакет **`ua-parser-js`** заборонений починаючи з версії **2.x**, де ліцензія змінилась з MIT на **AGPL-3.0** — несумісну з комерційним використанням у закритому SaaS. Замінити на **`bowser`** (MIT, ~6 KB gzip):
|
|
8
|
+
|
|
9
|
+
```javascript title="❌ до"
|
|
10
|
+
import { UAParser } from 'ua-parser-js'
|
|
11
|
+
const parser = new UAParser(userAgent)
|
|
12
|
+
const result = parser.getResult()
|
|
13
|
+
const browserName = result.browser.name
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```javascript title="✅ після"
|
|
17
|
+
import Bowser from 'bowser'
|
|
18
|
+
const browser = Bowser.getParser(userAgent)
|
|
19
|
+
const browserName = browser.getBrowserName()
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Bowser надає ті самі поля: `getBrowserName()`, `getOSName()`, `getPlatform().vendor`. Міграція займає кілька рядків; логіка не змінюється.
|
|
23
|
+
|
|
5
24
|
### Заборона `@nitra/as-integrations-fastify`
|
|
6
25
|
|
|
7
26
|
Пакет **`@nitra/as-integrations-fastify`** заборонений у **`dependencies`**, **`peerDependencies`** та в import-specifier-ах. Це чистий републіш upstream, застряглий на peer `@apollo/server: "^4.0.0"`, тож на Apollo 5 `bun install` дає `warn: incorrect peer dependency`. Заміна — upstream **`@as-integrations/fastify`** (**`^3.1.0`**): peer `@apollo/server: "^4.0.0 || ^5.0.0"` + `fastify: "^5.3.0"`.
|
|
@@ -16,8 +16,17 @@ import {
|
|
|
16
16
|
|
|
17
17
|
const JS_SOURCE_RE = /\.(?:[cm]?[jt]sx?)$/u
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Пакети, заборонені як import-specifier у будь-якому JS/TS-файлі.
|
|
21
|
+
* Ключ — specifier, значення — підказка про заміну.
|
|
22
|
+
*/
|
|
23
|
+
const BANNED_SPECIFIERS = new Map([
|
|
24
|
+
['@nitra/as-integrations-fastify', 'використовуй @as-integrations/fastify'],
|
|
25
|
+
[
|
|
26
|
+
'ua-parser-js',
|
|
27
|
+
'замінити на bowser (MIT, ~6 KB) — npm i bowser. ua-parser-js v2 змінив ліцензію на AGPL-3.0, несумісну з комерційним використанням'
|
|
28
|
+
]
|
|
29
|
+
])
|
|
21
30
|
|
|
22
31
|
/**
|
|
23
32
|
* Витягає з джерела всі import-specifier'и (static + dynamic + require).
|
|
@@ -73,11 +82,10 @@ export async function check(cwdParam = process.cwd()) {
|
|
|
73
82
|
const source = await readFile(absPath, 'utf8')
|
|
74
83
|
const specifiers = extractImportSpecifiers(source, absPath)
|
|
75
84
|
for (const spec of specifiers) {
|
|
76
|
-
|
|
85
|
+
const hint = BANNED_SPECIFIERS.get(spec)
|
|
86
|
+
if (hint !== undefined) {
|
|
77
87
|
const rel = relative(cwd, absPath)
|
|
78
|
-
reporter.fail(
|
|
79
|
-
`${rel}: заборонений import '${spec}' — використовуй @as-integrations/fastify (js.mdc dep-policy)`
|
|
80
|
-
)
|
|
88
|
+
reporter.fail(`${rel}: заборонений import '${spec}' — ${hint} (js.mdc dep-policy)`)
|
|
81
89
|
violations += 1
|
|
82
90
|
}
|
|
83
91
|
}
|
|
@@ -6,10 +6,10 @@ resource: npm/rules/js/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/js/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
11
|
-
| [check.mjs](check.md)
|
|
12
|
-
| [dep-policy.mjs](dep-policy.md)
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
|---|---|
|
|
11
|
+
| [check.mjs](check.md) | JS Module |
|
|
12
|
+
| [dep-policy.mjs](dep-policy.md) | JS Module |
|
|
13
13
|
| [lint-findings.mjs](lint-findings.md) | JS Module |
|
|
14
|
-
| [tooling.mjs](tooling.md)
|
|
14
|
+
| [tooling.mjs](tooling.md) | JS Module |
|
|
15
15
|
| [utils_imports.mjs](utils_imports.md) | JS Module |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/js/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/js/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/js/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/nginx-default-tpl/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/nginx-default-tpl/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/nginx-default-tpl/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -3,26 +3,28 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/python/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 7021a379
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 90
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Запускає `lint-python` за правилом `python.mdc` на базі [uv](https://docs.astral.sh/uv/). Якщо `pyproject.toml` відсутній у корені, вихід дорівнює 0 без запуску інструментів. Якщо `pyproject.toml` присутній, але `uv` не знайдено в PATH, це помилка (використовується лише `uv`, без Poetry). Обов'язково виконує `uv lock --check` для перевірки актуальності lock-файлу та `uv sync --frozen` для збірки середовища. Опціональні лінтери (`ruff`, `mypy`) запускаються лише якщо доступні через `uv run`. `ruff` виконується в режимі автоматичного виправлення (`ruff check --fix .`, `ruff format .`) та перевірки коду (`mypy .`). Це відповідає канону патерну `lint-*` (серіалізація через `runStandardLint`, без прямого `withLock`).
|
|
12
14
|
|
|
13
15
|
## Поведінка
|
|
14
16
|
|
|
15
|
-
run виконує стандартну перевірку для
|
|
16
|
-
runLintPythonSteps виконує послідовність кроків лінтування Python,
|
|
17
|
-
runLintPython запускає послідовність кроків лінтування Python,
|
|
18
|
-
lint
|
|
17
|
+
run виконує стандартну перевірку для правила.
|
|
18
|
+
runLintPythonSteps виконує послідовність кроків лінтування Python, включаючи перевірку `pyproject.toml`, виконання `uv lock --check` та `uv sync --frozen`, а також запуск опціональних лінтерів (`ruff`, `mypy`, `liccheck`) через `uv run` за умови їх доступності.
|
|
19
|
+
runLintPython запускає послідовність кроків лінтування Python, використовуючи механізм стандартного лінтування.
|
|
20
|
+
lint оркеструє запуск `runLintPython` для виконання лінтування Python.
|
|
19
21
|
|
|
20
22
|
## Публічний API
|
|
21
23
|
|
|
22
|
-
run — Основна точка входу для виконання правил, яка перевіряє
|
|
23
|
-
runLintPythonSteps — Виконує внутрішні етапи
|
|
24
|
-
runLintPython — Публічний інтерфейс для запуску
|
|
25
|
-
lint —
|
|
24
|
+
run — Основна точка входу для виконання правил, яка перевіряє аспекти застосування (JS-занепокложення $\rightarrow$ політика $\rightarrow$ mdc-посилання) та виконує лінтинг.
|
|
25
|
+
runLintPythonSteps — Виконує внутрішні етапи лінтингу Python без збереження логів.
|
|
26
|
+
runLintPython — Публічний інтерфейс командного рядка для запуску лінтингу Python, який синхронізується з станом Git-дерева.
|
|
27
|
+
lint — Координатор, що викликає публічний інтерфейс для лінтингу Python.
|
|
26
28
|
|
|
27
29
|
## Гарантії поведінки
|
|
28
30
|
|
package/rules/python/main.mjs
CHANGED
|
@@ -118,6 +118,7 @@ export function runLintPythonSteps(cwd = process.cwd(), opts = {}) {
|
|
|
118
118
|
if (!runOptionalUvTool('ruff', readOnly ? 'ruff format --check' : 'ruff format', ruffFormat))
|
|
119
119
|
return reporter.getExitCode()
|
|
120
120
|
if (!runOptionalUvTool('mypy', 'mypy', ['.'])) return reporter.getExitCode()
|
|
121
|
+
if (!runOptionalUvTool('liccheck', 'liccheck', [])) return reporter.getExitCode()
|
|
121
122
|
|
|
122
123
|
return reporter.getExitCode()
|
|
123
124
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/rego/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/rego/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/rego/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
package/rules/rust/docs/index.md
CHANGED
package/rules/rust/docs/main.md
CHANGED
|
@@ -3,22 +3,24 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/rust/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: cbe9e650
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Огляд
|
|
12
|
+
|
|
13
|
+
Модуль забезпечує виконання перевірки коду Rust на відповідність встановленим правилам. Він також надає функціонал для запуску повного процесу лінтингу, що включає форматування та аналіз коду.
|
|
12
14
|
|
|
13
15
|
## Поведінка
|
|
14
16
|
|
|
15
|
-
run виконує перевірку коду Rust
|
|
16
|
-
lint запускає
|
|
17
|
+
run виконує перевірку коду Rust, застосовуючи політику, визначену в документації.
|
|
18
|
+
lint запускає повний процес лінтингу Rust, включаючи форматування та аналіз, і повертає код виходу.
|
|
17
19
|
|
|
18
20
|
## Публічний API
|
|
19
21
|
|
|
20
|
-
run —
|
|
21
|
-
lint —
|
|
22
|
+
run — точка входу для виконання правила, що перевіряє логіку, пов'язану з JS-зацікавленостями, політикою та посиланнями MDC.
|
|
23
|
+
lint — точка входу для запуску лінтера Rust-коду.
|
|
22
24
|
|
|
23
25
|
## Гарантії поведінки
|
|
24
26
|
|
package/rules/rust/main.mjs
CHANGED
|
@@ -82,6 +82,17 @@ function runRustLint(cwd = process.cwd(), opts = {}) {
|
|
|
82
82
|
pass,
|
|
83
83
|
fail
|
|
84
84
|
)
|
|
85
|
+
|
|
86
|
+
// cargo deny check licenses (opt-in): потрібен deny.toml + cargo-deny у PATH
|
|
87
|
+
if (existsSync(join(cwd, 'deny.toml'))) {
|
|
88
|
+
const hasDeny = spawnSync(cargo, ['deny', '--version'], { stdio: 'ignore', shell: false }).status === 0
|
|
89
|
+
if (hasDeny) {
|
|
90
|
+
runCargo('cargo deny check licenses', cargo, ['deny', 'check', 'licenses'], pass, fail)
|
|
91
|
+
} else {
|
|
92
|
+
pass('lint-rust: cargo deny — не встановлений (cargo install cargo-deny), перевірку ліцензій пропущено')
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
85
96
|
return reporter.getExitCode()
|
|
86
97
|
}
|
|
87
98
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/rust/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/rust/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/rust/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/style/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/style/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/style/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/tauri/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/tauri/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/tauri/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/text/policy/vscode_extensions
|
|
4
|
+
resource: npm/rules/text/policy/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/text/policy/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -6,39 +6,39 @@ resource: npm/scripts/lib/
|
|
|
6
6
|
|
|
7
7
|
# npm/scripts/lib
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
11
|
-
| [assert-project-root.mjs](assert-project-root.md)
|
|
12
|
-
| [changed-files.mjs](changed-files.md)
|
|
13
|
-
| [check-mdc-template-refs.mjs](check-mdc-template-refs.md)
|
|
14
|
-
| [check-reporter.mjs](check-reporter.md)
|
|
15
|
-
| [diff-added-lines.mjs](diff-added-lines.md)
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
|---|---|
|
|
11
|
+
| [assert-project-root.mjs](assert-project-root.md) | JS Module |
|
|
12
|
+
| [changed-files.mjs](changed-files.md) | JS Module |
|
|
13
|
+
| [check-mdc-template-refs.mjs](check-mdc-template-refs.md) | JS Module |
|
|
14
|
+
| [check-reporter.mjs](check-reporter.md) | JS Module |
|
|
15
|
+
| [diff-added-lines.mjs](diff-added-lines.md) | JS Module |
|
|
16
16
|
| [discover-check-rules-from-cursor.mjs](discover-check-rules-from-cursor.md) | JS Module |
|
|
17
|
-
| [discover-checkable-rules.mjs](discover-checkable-rules.md)
|
|
18
|
-
| [ensure-tool.mjs](ensure-tool.md)
|
|
19
|
-
| [generated-markdown.mjs](generated-markdown.md)
|
|
20
|
-
| [gha-workflow.mjs](gha-workflow.md)
|
|
21
|
-
| [inline-template-links.mjs](inline-template-links.md)
|
|
22
|
-
| [list-project-rules-mdc.mjs](list-project-rules-mdc.md)
|
|
23
|
-
| [list-rule-ids.mjs](list-rule-ids.md)
|
|
24
|
-
| [load-cursor-config.mjs](load-cursor-config.md)
|
|
25
|
-
| [mirror-parity.mjs](mirror-parity.md)
|
|
26
|
-
| [read-n-cursor-config-lite.mjs](read-n-cursor-config-lite.md)
|
|
27
|
-
| [resolve-target-files.mjs](resolve-target-files.md)
|
|
28
|
-
| [root-notice.mjs](root-notice.md)
|
|
29
|
-
| [rule-meta-helpers.mjs](rule-meta-helpers.md)
|
|
30
|
-
| [rule-meta.mjs](rule-meta.md)
|
|
31
|
-
| [rule-predicates.mjs](rule-predicates.md)
|
|
32
|
-
| [run-conftest-batch.mjs](run-conftest-batch.md)
|
|
33
|
-
| [run-lint-step.mjs](run-lint-step.md)
|
|
34
|
-
| [run-lint.mjs](run-lint.md)
|
|
35
|
-
| [run-rule-cli.mjs](run-rule-cli.md)
|
|
36
|
-
| [run-rule.mjs](run-rule.md)
|
|
37
|
-
| [run-standard-lint.mjs](run-standard-lint.md)
|
|
38
|
-
| [run-standard-rule.mjs](run-standard-rule.md)
|
|
39
|
-
| [skill-meta.mjs](skill-meta.md)
|
|
40
|
-
| [sync-gitignore-worktree.mjs](sync-gitignore-worktree.md)
|
|
41
|
-
| [template.mjs](template.md)
|
|
42
|
-
| [timing-summary.mjs](timing-summary.md)
|
|
43
|
-
| [workspaces.mjs](workspaces.md)
|
|
44
|
-
| [worktree-notice.mjs](worktree-notice.md)
|
|
17
|
+
| [discover-checkable-rules.mjs](discover-checkable-rules.md) | JS Module |
|
|
18
|
+
| [ensure-tool.mjs](ensure-tool.md) | JS Module |
|
|
19
|
+
| [generated-markdown.mjs](generated-markdown.md) | JS Module |
|
|
20
|
+
| [gha-workflow.mjs](gha-workflow.md) | JS Module |
|
|
21
|
+
| [inline-template-links.mjs](inline-template-links.md) | JS Module |
|
|
22
|
+
| [list-project-rules-mdc.mjs](list-project-rules-mdc.md) | JS Module |
|
|
23
|
+
| [list-rule-ids.mjs](list-rule-ids.md) | JS Module |
|
|
24
|
+
| [load-cursor-config.mjs](load-cursor-config.md) | JS Module |
|
|
25
|
+
| [mirror-parity.mjs](mirror-parity.md) | JS Module |
|
|
26
|
+
| [read-n-cursor-config-lite.mjs](read-n-cursor-config-lite.md) | JS Module |
|
|
27
|
+
| [resolve-target-files.mjs](resolve-target-files.md) | JS Module |
|
|
28
|
+
| [root-notice.mjs](root-notice.md) | JS Module |
|
|
29
|
+
| [rule-meta-helpers.mjs](rule-meta-helpers.md) | JS Module |
|
|
30
|
+
| [rule-meta.mjs](rule-meta.md) | JS Module |
|
|
31
|
+
| [rule-predicates.mjs](rule-predicates.md) | JS Module |
|
|
32
|
+
| [run-conftest-batch.mjs](run-conftest-batch.md) | JS Module |
|
|
33
|
+
| [run-lint-step.mjs](run-lint-step.md) | JS Module |
|
|
34
|
+
| [run-lint.mjs](run-lint.md) | JS Module |
|
|
35
|
+
| [run-rule-cli.mjs](run-rule-cli.md) | JS Module |
|
|
36
|
+
| [run-rule.mjs](run-rule.md) | JS Module |
|
|
37
|
+
| [run-standard-lint.mjs](run-standard-lint.md) | JS Module |
|
|
38
|
+
| [run-standard-rule.mjs](run-standard-rule.md) | JS Module |
|
|
39
|
+
| [skill-meta.mjs](skill-meta.md) | JS Module |
|
|
40
|
+
| [sync-gitignore-worktree.mjs](sync-gitignore-worktree.md) | JS Module |
|
|
41
|
+
| [template.mjs](template.md) | JS Module |
|
|
42
|
+
| [timing-summary.mjs](timing-summary.md) | JS Module |
|
|
43
|
+
| [workspaces.mjs](workspaces.md) | JS Module |
|
|
44
|
+
| [worktree-notice.mjs](worktree-notice.md) | JS Module |
|
|
@@ -6,14 +6,16 @@ resource: npm/scripts/lib/fix/
|
|
|
6
6
|
|
|
7
7
|
# npm/scripts/lib/fix
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
11
|
-
| [analyze-escalation.mjs](analyze-escalation.md)
|
|
12
|
-
| [
|
|
13
|
-
| [
|
|
14
|
-
| [llm-
|
|
15
|
-
| [llm-
|
|
16
|
-
| [
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
|---|---|
|
|
11
|
+
| [analyze-escalation.mjs](analyze-escalation.md) | JS Module |
|
|
12
|
+
| [discover-t0-patterns.mjs](discover-t0-patterns.md) | JS Module |
|
|
13
|
+
| [escalation-log.mjs](escalation-log.md) | JS Module |
|
|
14
|
+
| [llm-fix-apply.mjs](llm-fix-apply.md) | JS Module |
|
|
15
|
+
| [llm-lint-fix.mjs](llm-lint-fix.md) | JS Module |
|
|
16
|
+
| [llm-worker.mjs](llm-worker.md) | JS Module |
|
|
17
|
+
| [orchestrator.mjs](orchestrator.md) | JS Module |
|
|
17
18
|
| [run-conformance-check.mjs](run-conformance-check.md) | JS Module |
|
|
18
|
-
| [t0.mjs](t0.md)
|
|
19
|
-
| [verbose-block.mjs](verbose-block.md)
|
|
19
|
+
| [t0.mjs](t0.md) | JS Module |
|
|
20
|
+
| [verbose-block.mjs](verbose-block.md) | JS Module |
|
|
21
|
+
| [vscode-ext-add.mjs](vscode-ext-add.md) | JS Module |
|
|
@@ -37,29 +37,19 @@ npx @nitra/cursor lint-doc-files --git
|
|
|
37
37
|
|
|
38
38
|
## Крок 1: Tier 2 — module-summary
|
|
39
39
|
|
|
40
|
-
Зібрати список
|
|
40
|
+
Зібрати список воркспейсів з кореневого `package.json`:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
|
|
43
|
+
node -e "const p=JSON.parse(require('fs').readFileSync('package.json','utf8')); console.log(JSON.stringify(p.workspaces))"
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
{
|
|
51
|
-
"moduleRoot": "/abs/npm/rules/adr",
|
|
52
|
-
"relRoot": "npm/rules/adr",
|
|
53
|
-
"slug": "npm-rules-adr",
|
|
54
|
-
"docPath": "/abs/npm/rules/adr/docs/ARCHITECTURE.md",
|
|
55
|
-
"members": ["npm/rules/adr/index.mjs"],
|
|
56
|
-
"exists": false
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
```
|
|
46
|
+
Для кожного воркспейсу `<ws>`:
|
|
47
|
+
- `relRoot` = `<ws>` (напр. `npm`, `demo`)
|
|
48
|
+
- `docPath` = `<ws>/docs/ARCHITECTURE.md`
|
|
49
|
+
- `members` — кодові файли (`.mjs .ts .vue .py`, крім тестів) у `<ws>/`
|
|
60
50
|
|
|
61
|
-
module-summary **завжди
|
|
62
|
-
|
|
51
|
+
module-summary **завжди регенерується**. Розбий воркспейси на батчі по 5 і диспатч субагентів.
|
|
52
|
+
Промпт кожного (підстав `relRoot`, `docPath`, `members`):
|
|
63
53
|
|
|
64
54
|
```
|
|
65
55
|
Напиши module-summary для одного логічного модуля.
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/** @see ./docs/docgen-scan.md */
|
|
2
|
-
import { join, relative, dirname, extname, sep, isAbsolute, resolve } from 'node:path'
|
|
3
|
-
import { existsSync, readdirSync, statSync } from 'node:fs'
|
|
4
|
-
|
|
5
|
-
import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
|
|
6
|
-
import { isDocgenIgnored } from './docgen-ignore.mjs'
|
|
7
|
-
|
|
8
|
-
/** Кодові розширення, для яких генеруємо документацію. */
|
|
9
|
-
const SOURCE_EXTENSIONS = new Set(['.js', '.mjs', '.ts', '.vue', '.py'])
|
|
10
|
-
|
|
11
|
-
/** `*.test.*`, `*.spec.*` — тести, документувати не треба. */
|
|
12
|
-
const TEST_FILE_RE = /\.(?:test|spec)\.[^.]+$/u
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Чи корінь має system-wide docs layout (зарезервований під repo docs/adr тощо).
|
|
16
|
-
* @param {string} root абсолютний корінь обходу
|
|
17
|
-
* @returns {boolean} true — корінь system-wide docs
|
|
18
|
-
*/
|
|
19
|
-
function isSystemWideDocsRoot(root) {
|
|
20
|
-
return existsSync(join(root, 'docs', 'adr')) || existsSync(join(root, 'docs', 'explanation'))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Чи є файл кодовим джерелом для документування.
|
|
25
|
-
* @param {string} fileName базове ім'я файлу
|
|
26
|
-
* @returns {boolean} true — документуємо
|
|
27
|
-
*/
|
|
28
|
-
export function isSourceFile(fileName) {
|
|
29
|
-
if (fileName.endsWith('.d.ts')) return false
|
|
30
|
-
if (TEST_FILE_RE.test(fileName)) return false
|
|
31
|
-
return SOURCE_EXTENSIONS.has(extname(fileName))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Рекурсивно збирає кодові файли проєкту (posix-шляхи від кореня).
|
|
36
|
-
* @param {string} root абсолютний корінь обходу
|
|
37
|
-
* @returns {string[]} sourcePath-и
|
|
38
|
-
*/
|
|
39
|
-
export function scanSourceFiles(root) {
|
|
40
|
-
const results = []
|
|
41
|
-
|
|
42
|
-
/** @param {string} dir поточний каталог обходу */
|
|
43
|
-
function walk(dir) {
|
|
44
|
-
let entries
|
|
45
|
-
try {
|
|
46
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
47
|
-
} catch {
|
|
48
|
-
return
|
|
49
|
-
}
|
|
50
|
-
for (const entry of entries) {
|
|
51
|
-
const fullPath = join(dir, entry.name)
|
|
52
|
-
const relPath = relative(root, fullPath)
|
|
53
|
-
if (entry.isDirectory()) {
|
|
54
|
-
if (isDocgenIgnored(relPath, 'dir')) continue
|
|
55
|
-
walk(fullPath)
|
|
56
|
-
} else if (entry.isFile() && isSourceFile(entry.name)) {
|
|
57
|
-
if (isSystemWideDocsRoot(root) && dirname(relPath) === '.') continue
|
|
58
|
-
const sourcePath = relPath.split(sep).join('/')
|
|
59
|
-
if (isDocgenIgnored(sourcePath)) continue
|
|
60
|
-
results.push(sourcePath)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
walk(root)
|
|
66
|
-
return results
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Стабільний slug модуля з його відносного шляху (для лейблів/логів).
|
|
71
|
-
* @param {string} root абсолютний корінь обходу
|
|
72
|
-
* @param {string} moduleRoot абсолютний корінь модуля
|
|
73
|
-
* @returns {string} slug: `npm/rules/adr` → `npm-rules-adr`, корінь → `root`
|
|
74
|
-
*/
|
|
75
|
-
export function slugForModule(root, moduleRoot) {
|
|
76
|
-
const rel = relative(root, moduleRoot)
|
|
77
|
-
if (rel === '') return 'root'
|
|
78
|
-
return rel
|
|
79
|
-
.split(sep)
|
|
80
|
-
.join('-')
|
|
81
|
-
.replaceAll(/[^\w-]+/gu, '-')
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Знаходить корені модулів — теки з `package.json` (корінь завжди модуль).
|
|
86
|
-
* @param {string} root абсолютний корінь обходу
|
|
87
|
-
* @returns {string[]} абсолютні шляхи коренів модулів
|
|
88
|
-
*/
|
|
89
|
-
export function findModuleRoots(root) {
|
|
90
|
-
const roots = [root]
|
|
91
|
-
|
|
92
|
-
/** @param {string} dir поточний каталог обходу */
|
|
93
|
-
function walk(dir) {
|
|
94
|
-
let entries
|
|
95
|
-
try {
|
|
96
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
97
|
-
} catch {
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
for (const entry of entries) {
|
|
101
|
-
const fullPath = join(dir, entry.name)
|
|
102
|
-
const relPath = relative(root, fullPath)
|
|
103
|
-
if (entry.isDirectory()) {
|
|
104
|
-
if (isDocgenIgnored(relPath, 'dir')) continue
|
|
105
|
-
walk(fullPath)
|
|
106
|
-
} else if (entry.isFile() && entry.name === 'package.json' && dir !== root) {
|
|
107
|
-
roots.push(dir)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
walk(root)
|
|
113
|
-
return roots
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Найближчий модуль-предок для файлу (найдовший збіг шляху).
|
|
118
|
-
* @param {string} filePath абсолютний шлях до файлу
|
|
119
|
-
* @param {string[]} moduleRoots абсолютні корені модулів
|
|
120
|
-
* @returns {string|null} абсолютний корінь модуля або null
|
|
121
|
-
*/
|
|
122
|
-
export function nearestModuleRoot(filePath, moduleRoots) {
|
|
123
|
-
let best = null
|
|
124
|
-
for (const moduleRoot of moduleRoots) {
|
|
125
|
-
const rel = relative(moduleRoot, filePath)
|
|
126
|
-
if (rel.startsWith('..') || isAbsolute(rel)) continue
|
|
127
|
-
if (best === null || moduleRoot.length > best.length) best = moduleRoot
|
|
128
|
-
}
|
|
129
|
-
return best
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Лістить логічні модулі проєкту з членами-файлами і docPath module-summary.
|
|
134
|
-
* Модулі без кодових файлів пропускаються.
|
|
135
|
-
* @param {string} root абсолютний корінь обходу
|
|
136
|
-
* @returns {Array<{moduleRoot:string, relRoot:string, slug:string, docPath:string, members:string[], exists:boolean}>} модулі (members — sourcePath-и від root)
|
|
137
|
-
*/
|
|
138
|
-
export function scanForModules(root) {
|
|
139
|
-
const files = scanSourceFiles(root)
|
|
140
|
-
const moduleRoots = findModuleRoots(root)
|
|
141
|
-
const byRoot = new Map()
|
|
142
|
-
for (const sourcePath of files) {
|
|
143
|
-
const moduleRoot = nearestModuleRoot(join(root, sourcePath), moduleRoots)
|
|
144
|
-
if (moduleRoot === null) continue
|
|
145
|
-
if (!byRoot.has(moduleRoot)) byRoot.set(moduleRoot, [])
|
|
146
|
-
byRoot.get(moduleRoot).push(sourcePath)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const results = []
|
|
150
|
-
for (const moduleRoot of moduleRoots) {
|
|
151
|
-
const members = byRoot.get(moduleRoot)
|
|
152
|
-
if (!members || members.length === 0) continue
|
|
153
|
-
const docPath = join(moduleRoot, 'docs', 'ARCHITECTURE.md')
|
|
154
|
-
results.push({
|
|
155
|
-
moduleRoot,
|
|
156
|
-
relRoot: relative(root, moduleRoot) || '.',
|
|
157
|
-
slug: slugForModule(root, moduleRoot),
|
|
158
|
-
docPath,
|
|
159
|
-
members: members.toSorted(),
|
|
160
|
-
exists: existsSync(docPath)
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
return results
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Парсить `--root <dir>`; default — cwd.
|
|
168
|
-
* @param {string[]} argv аргументи після підкоманди
|
|
169
|
-
* @returns {string} абсолютний корінь
|
|
170
|
-
*/
|
|
171
|
-
export function resolveRoot(argv) {
|
|
172
|
-
const i = argv.indexOf('--root')
|
|
173
|
-
return i !== -1 && argv[i + 1] ? resolve(argv[i + 1]) : process.cwd()
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* `doc-aggregate modules` — сканує модулі і друкує JSON-масив у stdout.
|
|
178
|
-
* @param {string[]} argv аргументи після назви субкоманди
|
|
179
|
-
* @returns {number} exit-код: 0 — успіх, 1 — корінь не існує
|
|
180
|
-
*/
|
|
181
|
-
export function runDocAggregateModulesCli(argv) {
|
|
182
|
-
const root = resolveRoot(argv)
|
|
183
|
-
if (!existsSync(root) || !statSync(root).isDirectory()) {
|
|
184
|
-
console.error(`doc-aggregate modules: корінь не існує або не є директорією: ${root}`)
|
|
185
|
-
return 1
|
|
186
|
-
}
|
|
187
|
-
console.log(JSON.stringify(scanForModules(root), null, 2))
|
|
188
|
-
return 0
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (isRunAsCli(import.meta.url)) {
|
|
192
|
-
// Прямий запуск: `node skills/doc-aggregate/js/docgen-scan.mjs modules --root <dir>`
|
|
193
|
-
const [sub, ...rest] = process.argv.slice(2)
|
|
194
|
-
process.exitCode = runDocAggregateModulesCli(sub === 'modules' ? rest : process.argv.slice(2))
|
|
195
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: docgen-scan.mjs
|
|
4
|
-
resource: npm/skills/doc-aggregate/js/docgen-scan.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: 193dd362
|
|
7
|
-
score: 100
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
isSourceFile
|
|
11
|
-
Перевіряє, чи є файл коду, який слугує джерелом для документування.
|
|
12
|
-
|
|
13
|
-
scanSourceFiles
|
|
14
|
-
Рекурсивно збирає кодові файли проєкту за позикс-шляхами від кореня.
|
|
15
|
-
|
|
16
|
-
slugForModule
|
|
17
|
-
Генерує стабільний slug модуля на основі його відносного шляху.
|
|
18
|
-
|
|
19
|
-
findModuleRoots
|
|
20
|
-
Знаходить абсолютні шляхи коренів модулів, використовуючи дані з package.json.
|
|
21
|
-
|
|
22
|
-
nearestModuleRoot
|
|
23
|
-
Визначає найближчий модуль-предок для заданого файлу серед усіх доступних коренів модулів.
|
|
24
|
-
|
|
25
|
-
scanForModules
|
|
26
|
-
Лістить логічні модулі, збираючи члени-файли та інформацію про наявність документації.
|
|
27
|
-
|
|
28
|
-
resolveRoot
|
|
29
|
-
Парсить аргументи для визначення абсолютної кореневої директорії.
|
|
30
|
-
|
|
31
|
-
runDocAggregateModulesCli
|
|
32
|
-
Сканує модулі та виводить масив JSON у stdout.
|
|
33
|
-
|
|
34
|
-
## Поведінка
|
|
35
|
-
|
|
36
|
-
isSourceFile
|
|
37
|
-
Перевіряє, чи є файл кодовим джерелом для документування
|
|
38
|
-
|
|
39
|
-
scanSourceFiles
|
|
40
|
-
Рекурсивно збирає кодові файли проєкту по позикс-шляхах від кореня
|
|
41
|
-
|
|
42
|
-
slugForModule
|
|
43
|
-
Генерує стабільний slug модуля з його відносним шляхом
|
|
44
|
-
|
|
45
|
-
findModuleRoots
|
|
46
|
-
Знаходить абсолютні шляхи коренів модулів з файлами package.json
|
|
47
|
-
|
|
48
|
-
nearestModuleRoot
|
|
49
|
-
Знаходить найближчий модуль-предок для файлу серед наявних коренів модулів
|
|
50
|
-
|
|
51
|
-
scanForModules
|
|
52
|
-
Лістить логічні модулі, збираючи члени-файли та інформацію про наявність документації
|
|
53
|
-
|
|
54
|
-
resolveRoot
|
|
55
|
-
Парсить аргументи для визначення абсолютного кореня
|
|
56
|
-
|
|
57
|
-
runDocAggregateModulesCli
|
|
58
|
-
Сканує модулі та виводить JSON-масив у stdout
|
|
59
|
-
|
|
60
|
-
## Публічний API
|
|
61
|
-
|
|
62
|
-
- isSourceFile — визначає, чи є файл коду для документування.
|
|
63
|
-
- scanSourceFiles — рекурсивно збирає файли коду проєкту (від кореня за POSIX-шляхом).
|
|
64
|
-
- slugForModule — генерує стабільний slug модуля з його відносним шляхом (для лейблів/логів).
|
|
65
|
-
- findModuleRoots — знаходить кореневі директорії модулів у `package.json` (корінь — це модуль).
|
|
66
|
-
- nearestModuleRoot — визначає найближчий модуль-предок для файлу (найдовший збіг шляху).
|
|
67
|
-
- scanForModules — лістить логічні модулі проєкту з членами-файлами та `docPath module-summary`. Пропускає модулі без кодових файлів.
|
|
68
|
-
- resolveRoot — парсить аргумент `--root <dir>`; за замовчуванням використовує поточну директорію.
|
|
69
|
-
- runDocAggregateModulesCli — виконує команду `doc-aggregate modules`, скануючи модулі та виводячи JSON-масив у stdout.
|
|
70
|
-
|
|
71
|
-
## Гарантії поведінки
|
|
72
|
-
|
|
73
|
-
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
74
|
-
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
75
|
-
- За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
|
|
76
|
-
- Не звертається до мережі.
|