@7n/rules 1.7.3 → 1.7.5
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 +12 -0
- package/package.json +2 -2
- package/rules/js/eslint/docs/main.md +2 -2
- package/rules/js/eslint/main.mjs +10 -3
- package/scripts/docs/sync-claude-config.md +1 -1
- package/scripts/lib/changed-files.mjs +15 -2
- package/scripts/lib/docs/changed-files.md +3 -1
- package/scripts/utils/docs/walkDir.md +7 -5
- package/scripts/utils/walkDir.mjs +18 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.7.5] - 2026-07-16
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- npm: підняти нижню межу @7n/llm-lib до ^2.7.0 (skills-cli.mjs імпортує ./acp, доданий лише у 2.7.0 — старіші 2.x без цього subpath ламали npx @7n/rules з ERR_PACKAGE_PATH_NOT_EXPORTED)
|
|
8
|
+
|
|
9
|
+
## [1.7.4] - 2026-07-16
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- lint не бачить worktree-чекаутів (.worktrees/, .claude/worktrees/): виключені у walkDir, delta-списку змінених файлів і js/eslint (ESLint+oxlint)
|
|
14
|
+
|
|
3
15
|
## [1.7.3] - 2026-07-16
|
|
4
16
|
|
|
5
17
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@7n/rules",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.5",
|
|
4
4
|
"description": "CLI еталонних правил і skills (префікс n-): синк у репозиторій, дельта-lint, конформність",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"rename-yaml-extensions": "bun ./bin/n-rules.js rename-yaml-extensions"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@7n/llm-lib": "^2.
|
|
66
|
+
"@7n/llm-lib": "^2.7.0",
|
|
67
67
|
"@7n/mt": "^0.5.1",
|
|
68
68
|
"@zed-industries/agent-client-protocol": "^0.4.5",
|
|
69
69
|
"ajv": "^8.20.0",
|
|
@@ -3,7 +3,7 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/js/eslint/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 0d2a5e02
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
issues: judge:inaccurate:0.99
|
|
@@ -32,4 +32,4 @@ lint — проводить статичний аналіз коду (пофай
|
|
|
32
32
|
|
|
33
33
|
**warnIgnored: false.** ESLint конструюється з `warnIgnored: false` — файли з delta-списку, що матчать ignore-патерни `eslint.config.js` (наприклад, синковані `.pi/extensions/**` чи згенеровані `npm/types/**`), не рахуються порушеннями.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
**Worktree-чекаути ігноруються.** Обидва інструменти виключають `.worktrees/**` і `.claude/worktrees/**` (копії репо від сесійних git-worktree, яких споживацький конфіг зазвичай не виключає): ESLint — через global ignores у `overrideConfig`, oxlint — через `--ignore-pattern`. Діє і у full-режимі, і для явно переданих файлів.
|
package/rules/js/eslint/main.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
8
8
|
import { ESLint } from 'eslint'
|
|
9
9
|
|
|
10
10
|
import { addedLinesByFile } from '../../../scripts/lib/diff-added-lines.mjs'
|
|
11
|
+
import { WORKTREE_CHECKOUT_GLOBS } from '../../../scripts/utils/walkDir.mjs'
|
|
11
12
|
import { classifyFindings, eslintResultsToFindings, parseOxlint } from '../lint-findings/main.mjs'
|
|
12
13
|
|
|
13
14
|
const JS_EXT_RE = /\.(?:mjs|cjs|js|jsx|ts|tsx|vue)$/u
|
|
@@ -55,12 +56,18 @@ function toViolation(f, cwd, severity) {
|
|
|
55
56
|
* @returns {Promise<Array<{ file: string, line: number, rule: string, message: string, tool: string }>>} зібрані знахідки oxlint+eslint
|
|
56
57
|
*/
|
|
57
58
|
async function collectFindings(js, cwd) {
|
|
58
|
-
// warnIgnored:false — файли з delta, що матчать ignore-патерни конфігу, не є
|
|
59
|
-
|
|
59
|
+
// warnIgnored:false — файли з delta, що матчать ignore-патерни конфігу, не є порушеннями.
|
|
60
|
+
// overrideConfig лише з ignores → global ignores: worktree-чекаути (.worktrees/,
|
|
61
|
+
// .claude/worktrees/) — копії репо, споживацький eslint-конфіг їх не виключає.
|
|
62
|
+
const eslint = new ESLint({ cwd, warnIgnored: false, overrideConfig: { ignores: WORKTREE_CHECKOUT_GLOBS } })
|
|
60
63
|
const esResults = await eslint.lintFiles(js === null ? [cwd] : js.map(f => resolve(cwd, f)))
|
|
61
64
|
const es = eslintResultsToFindings(esResults)
|
|
62
65
|
|
|
63
|
-
const
|
|
66
|
+
const worktreeIgnoreArgs = WORKTREE_CHECKOUT_GLOBS.map(g => `--ignore-pattern=${g}`)
|
|
67
|
+
const oxArgs =
|
|
68
|
+
js === null
|
|
69
|
+
? ['oxlint', '--format=json', ...worktreeIgnoreArgs]
|
|
70
|
+
: ['oxlint', '--format=json', ...worktreeIgnoreArgs, ...js]
|
|
64
71
|
const oxRes = runOxlintJson(oxArgs, cwd)
|
|
65
72
|
const ox = parseOxlint(oxRes.stdout)
|
|
66
73
|
if (ox === null && oxRes.status !== 0) {
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { spawnSync } from 'node:child_process'
|
|
9
9
|
|
|
10
|
+
import { isWorktreeCheckoutPath } from '../utils/walkDir.mjs'
|
|
11
|
+
|
|
10
12
|
/**
|
|
11
13
|
* @param {string[]} args аргументи git
|
|
12
14
|
* @param {string} cwd корінь
|
|
@@ -29,7 +31,18 @@ function gitLines(args, cwd) {
|
|
|
29
31
|
export function collectChangedFiles(cwd = process.cwd()) {
|
|
30
32
|
const modified = gitLines(['diff', 'HEAD', '--name-only', '--diff-filter=ACMR'], cwd)
|
|
31
33
|
const untracked = gitLines(['ls-files', '--others', '--exclude-standard'], cwd)
|
|
32
|
-
return [...new Set([...modified, ...untracked])]
|
|
34
|
+
return dropWorktreeCheckouts([...new Set([...modified, ...untracked])])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Прибирає шляхи всередині worktree-чекаутів (`.worktrees/`, `.claude/worktrees/`):
|
|
39
|
+
* це повні копії репо (сесійні worktree Claude/агентів), а не робочий код, і в
|
|
40
|
+
* споживацьких репо вони можуть бути не gitignored — git тоді віддає їх як untracked.
|
|
41
|
+
* @param {string[]} paths relative-posix шляхи
|
|
42
|
+
* @returns {string[]} шляхи без worktree-чекаутів
|
|
43
|
+
*/
|
|
44
|
+
function dropWorktreeCheckouts(paths) {
|
|
45
|
+
return paths.filter(p => !isWorktreeCheckoutPath(p))
|
|
33
46
|
}
|
|
34
47
|
|
|
35
48
|
/**
|
|
@@ -79,5 +92,5 @@ export function collectChangedFilesSince(base, cwd = process.cwd()) {
|
|
|
79
92
|
}
|
|
80
93
|
const changed = gitLines(['diff', base, '--name-only', '--diff-filter=ACMR'], cwd)
|
|
81
94
|
const untracked = gitLines(['ls-files', '--others', '--exclude-standard'], cwd)
|
|
82
|
-
return [...new Set([...changed, ...untracked])]
|
|
95
|
+
return dropWorktreeCheckouts([...new Set([...changed, ...untracked])])
|
|
83
96
|
}
|
|
@@ -3,7 +3,7 @@ type: JS Module
|
|
|
3
3
|
title: changed-files.mjs
|
|
4
4
|
resource: npm/scripts/lib/changed-files.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 483db255
|
|
7
7
|
score: 100
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -27,6 +27,8 @@ collectChangedFilesSince Збирає змінені та незакомічен
|
|
|
27
27
|
|
|
28
28
|
## Гарантії поведінки
|
|
29
29
|
|
|
30
|
+
- Обидва збирачі відкидають шляхи всередині worktree-чекаутів (`.worktrees/`, `.claude/worktrees/`): це повні копії репо (сесійні git-worktree Claude/агентів), а не робочий код; у споживацьких репо вони можуть бути не gitignored і інакше потрапляли б у delta-список як untracked.
|
|
31
|
+
|
|
30
32
|
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
31
33
|
- За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
|
|
32
34
|
- Не звертається до мережі.
|
|
@@ -3,29 +3,31 @@ type: JS Module
|
|
|
3
3
|
title: walkDir.mjs
|
|
4
4
|
resource: npm/scripts/utils/walkDir.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 6f26e08f
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
Публічна функція `walkDir` здійснює рекурсивний пошук файлів у вказаному каталозі. Вона обходить файлову систему, ігноруючи каталоги `.git` та
|
|
11
|
+
Публічна функція `walkDir` здійснює рекурсивний пошук файлів у вказаному каталозі. Вона обходить файлову систему, ігноруючи каталоги `.git`, `node_modules` та worktree-чекаути (`.worktrees/`, `.claude/worktrees/` — повні копії репо від сесійних git-worktree Claude/агентів). Знаходячи кожен файл, вона передає його повний шлях у колбек для подальшої обробки. Компонент є read-only, тобто не виконує записів у файлову систему чи бази даних. При роботі з файловою системою він перехоплює помилки, забезпечуючи безпечну роботу без викидання винятків.
|
|
12
12
|
|
|
13
13
|
## Поведінка
|
|
14
14
|
|
|
15
15
|
1. Викликається функція walkDir для початку рекурсивного обходу каталогу.
|
|
16
16
|
2. Система розшифровує вхідний шлях до кореня обходу.
|
|
17
17
|
3. Система формує додаткові правила ігнорування на основі наданих шляхів.
|
|
18
|
-
4. Система завжди ігнорує каталоги .git
|
|
18
|
+
4. Система завжди ігнорує каталоги .git, node_modules і worktree-чекаути (.worktrees/, .claude/worktrees/) на будь-якій глибині.
|
|
19
19
|
5. Система виконує пошук усіх файлів у каталозі, застосовуючи правила ігнорування, включаючи ті, що визначені в .gitignore.
|
|
20
20
|
6. У разі виникнення помилки під час пошуку, процес обходу припиняється без генерації винятку.
|
|
21
21
|
7. Для кожного знайденого файлу система викликає наданий колбек, передаючи йому повний абсолютний шлях до цього файлу.
|
|
22
22
|
|
|
23
23
|
## Публічний API
|
|
24
24
|
|
|
25
|
-
walkDir — рекурсивно переглядає файли та папки, ігноруючи ті, що вказані у файлі `.gitignore`.
|
|
25
|
+
- walkDir — рекурсивно переглядає файли та папки, ігноруючи ті, що вказані у файлі `.gitignore`.
|
|
26
|
+
- isWorktreeCheckoutPath — предикат для відносного posix-шляху: чи лежить він усередині worktree-чекаута (`.worktrees/` або `.claude/worktrees/`). Для фільтрації git-списків, що не проходять через walkDir (наприклад, delta-список змінених файлів).
|
|
27
|
+
- ALWAYS_IGNORE, WORKTREE_CHECKOUT_GLOBS — експортовані glob-константи безумовних пропусків обходу.
|
|
26
28
|
|
|
27
29
|
## Гарантії поведінки
|
|
28
30
|
|
|
29
31
|
- Read-only: не виконує операцій запису (ФС/БД).
|
|
30
32
|
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
31
|
-
- Свідомо пропускає шляхи: `.git`, `node_modules`.
|
|
33
|
+
- Свідомо пропускає шляхи: `.git`, `node_modules`, `.worktrees/`, `.claude/worktrees/`.
|
|
@@ -2,9 +2,26 @@
|
|
|
2
2
|
import { join, relative, resolve, sep } from 'node:path'
|
|
3
3
|
import { globby } from 'globby'
|
|
4
4
|
|
|
5
|
+
// Сесійні git-worktree чекаути (Claude/агенти): повні копії репо, не робочий код.
|
|
6
|
+
// Споживацькі репо часто не мають цих шляхів у .gitignore, тож без safety net
|
|
7
|
+
// lint-обхід бачив би дубль усього дерева.
|
|
8
|
+
export const WORKTREE_CHECKOUT_GLOBS = ['**/.worktrees/**', '**/.claude/worktrees/**']
|
|
9
|
+
|
|
5
10
|
// .git ніколи не потрапляє в .gitignore — пропускаємо завжди.
|
|
6
11
|
// node_modules — safety net: проєкт може не мати .gitignore або запускатись поза git-репо.
|
|
7
|
-
export const ALWAYS_IGNORE = ['.git/**', 'node_modules/**']
|
|
12
|
+
export const ALWAYS_IGNORE = ['.git/**', 'node_modules/**', ...WORKTREE_CHECKOUT_GLOBS]
|
|
13
|
+
|
|
14
|
+
const WORKTREE_CHECKOUT_RE = /(?:^|\/)(?:\.worktrees|\.claude\/worktrees)\//u
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Чи лежить відносний posix-шлях усередині worktree-чекаута (`.worktrees/` або
|
|
18
|
+
* `.claude/worktrees/`). Для фільтрації git-списків, що не проходять через walkDir.
|
|
19
|
+
* @param {string} relPath відносний posix-шлях від кореня репо.
|
|
20
|
+
* @returns {boolean} true, якщо шлях у worktree-чекауті.
|
|
21
|
+
*/
|
|
22
|
+
export function isWorktreeCheckoutPath(relPath) {
|
|
23
|
+
return WORKTREE_CHECKOUT_RE.test(relPath)
|
|
24
|
+
}
|
|
8
25
|
|
|
9
26
|
/**
|
|
10
27
|
* Прибирає всі кінцеві `/` без regex-бектрекінгу.
|