agent-quality-kit 0.10.1 → 0.12.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 +10 -3
- package/README.ru.md +10 -3
- package/kit/gates/_native.sh +4 -0
- package/kit/gates/_skip.sh +7 -0
- package/kit/gates/api-contract-has-arbiter/check.sh +7 -0
- package/kit/gates/color-from-token/check.sh +7 -0
- package/kit/gates/commit-explains-itself/check.sh +8 -2
- package/kit/gates/complexity-limit/check.sh +22 -4
- package/kit/gates/complexity-limit/gate.yml +7 -2
- package/kit/gates/complexity-limit/red/deep.js +15 -0
- package/kit/gates/dead-code/gate.yml +5 -0
- package/kit/gates/duplicate-code/check.sh +7 -0
- package/kit/gates/duplicate-code/gate.yml +10 -1
- package/kit/gates/file-size-limit/check.sh +7 -0
- package/kit/gates/file-size-limit/red/big.js +600 -0
- package/kit/gates/gate-not-weakened/check.sh +7 -0
- package/kit/gates/gate-not-weakened/green/suppress.js +4 -0
- package/kit/gates/gate-not-weakened/red/suppress.js +5 -0
- package/kit/gates/mcp-server-resolves/check.sh +7 -0
- package/kit/gates/no-phantom-package/check.sh +7 -0
- package/kit/gates/no-print-in-prod/gate.yml +8 -3
- package/kit/gates/personal-config-not-shared/check.sh +7 -0
- package/kit/gates/secrets-not-in-code/check.sh +7 -0
- package/kit/gates/secrets-not-in-code/gate.yml +20 -0
- package/kit/gates/secrets-not-in-code/green/config.js +4 -0
- package/kit/gates/secrets-not-in-code/red/leak.js +6 -0
- package/kit/gates/swallowed-error/gate.yml +8 -3
- package/kit/gates/test-has-assertion/check.sh +7 -0
- package/kit/gates/test-has-assertion/green/checkout.test.js +5 -0
- package/kit/gates/test-has-assertion/red/checkout.test.js +8 -0
- package/kit/gates/test-not-adjusted/check.sh +8 -2
- package/kit/gates/todo-without-task/check.sh +7 -0
- package/kit/gates/todo-without-task/gate.yml +7 -2
- package/kit/gates/todo-without-task/green/app.js +2 -0
- package/kit/gates/todo-without-task/red/later.js +4 -0
- package/llms.txt +4 -2
- package/package.json +1 -1
- package/tool/commands/badge.mjs +1 -1
- package/tool/commands/context.mjs +3 -1
- package/tool/commands/doctor.mjs +94 -152
- package/tool/commands/gates.mjs +3 -2
- package/tool/commands/probe.mjs +284 -44
- package/tool/commands/report.mjs +1 -1
- package/tool/commands/vitals.mjs +6 -1
- package/tool/i18n/en-docs.mjs +2 -1
- package/tool/i18n/en-gates.mjs +23 -5
- package/tool/i18n/en.mjs +16 -0
- package/tool/i18n/ru-docs.mjs +2 -1
- package/tool/i18n/ru-gates.mjs +24 -6
- package/tool/i18n/ru.mjs +16 -0
- package/tool/lib/adopt.mjs +98 -0
- package/tool/lib/cadence.mjs +36 -1
- package/tool/lib/execution.mjs +50 -1
- package/tool/lib/history.mjs +89 -8
- package/tool/lib/prove.mjs +2 -2
- package/tool/lib/repo.mjs +47 -0
- package/tool/lib/run.mjs +194 -0
- package/tool/selfcheck/gates.sh +42 -4
- package/tool/selfcheck/smoke/_fixture.mjs +24 -2
- package/tool/selfcheck/smoke/fail-closed.test.mjs +112 -0
- package/tool/selfcheck/smoke/own-samples.test.mjs +131 -0
- package/tool/selfcheck/units-cadence.mjs +37 -1
- package/tool/selfcheck/units-execution.mjs +78 -1
- package/tool/selfcheck/units-level.mjs +24 -0
- package/tool/selfcheck/units-probe.mjs +385 -22
- package/tool/selfcheck/units-repo.mjs +123 -1
- package/tool/selfcheck/units.mjs +34 -1
package/README.md
CHANGED
|
@@ -14,13 +14,18 @@ Your `AGENTS.md` says what the project promises. Nothing checks that those promi
|
|
|
14
14
|
that the commands it lists even run. AQK is that missing layer: one command reads the repository,
|
|
15
15
|
reports a level from AQK-0 to AQK-3, and names every guard that is missing.
|
|
16
16
|
|
|
17
|
+
And one step further than the tools next door: `probe` plants a known defect into a copy of your
|
|
18
|
+
project and checks whether your **declared** guards actually go red. "Tests exist" and "tests
|
|
19
|
+
catch" are different claims — readiness scores measure the first one.
|
|
20
|
+
|
|
17
21
|
```bash
|
|
18
22
|
npx agent-quality-kit doctor # code already exists: your level and what to install
|
|
19
23
|
npx agent-quality-kit start # no code yet: day-zero guards, right away
|
|
20
24
|
```
|
|
21
25
|
|
|
22
26
|
`doctor` only reads. It writes no file and sends nothing anywhere — safe to point at a repository
|
|
23
|
-
you have decided nothing about yet. Nothing to install: `npx` fetches the package (
|
|
27
|
+
you have decided nothing about yet. Nothing to install: `npx` fetches the package (574.1 kB, measured 2026-09-10 — nothing guards this number, so check it
|
|
28
|
+
when it matters).
|
|
24
29
|
|
|
25
30
|
The one exception, named here because it is the only one: with `--brief` (how the hooks run it)
|
|
26
31
|
`doctor` asks the npm registry for its own latest version — **at most once a day, never in CI**,
|
|
@@ -41,6 +46,8 @@ Go, Rust, Java, Ruby, PHP, C#, Kotlin, Swift, Scala. Where the project already h
|
|
|
41
46
|
says so out loud when it falls back.
|
|
42
47
|
|
|
43
48
|
**Requirements:** Node 18+ and an `sh` shell. Present on macOS, Linux and WSL; Git Bash on Windows.
|
|
49
|
+
On Windows the gates run through Git Bash even when `bash` on your PATH is the WSL stub in
|
|
50
|
+
`System32` — it is found next to `git.exe`; set `AQK_BASH` to point elsewhere.
|
|
44
51
|
|
|
45
52
|
### One movement, and everything follows from it
|
|
46
53
|
|
|
@@ -340,7 +347,7 @@ Already using [pre-commit](https://pre-commit.com)? Three lines in the file you
|
|
|
340
347
|
```yaml
|
|
341
348
|
repos:
|
|
342
349
|
- repo: https://github.com/arsen-ask-lx/Agent_Quality_Kit
|
|
343
|
-
rev: v0.
|
|
350
|
+
rev: v0.12.0
|
|
344
351
|
hooks:
|
|
345
352
|
- id: aqk # runs what the repository declares; blocks below AQK-1
|
|
346
353
|
# - id: aqk-doctor # read-only: the level and what is missing, blocks nothing
|
|
@@ -361,7 +368,7 @@ layer AQK adds.
|
|
|
361
368
|
[](https://github.com/marketplace/actions/agent-quality-kit-aqk)
|
|
362
369
|
|
|
363
370
|
```yaml
|
|
364
|
-
- uses: arsen-ask-lx/Agent_Quality_Kit@v0.
|
|
371
|
+
- uses: arsen-ask-lx/Agent_Quality_Kit@v0.12.0
|
|
365
372
|
with:
|
|
366
373
|
min: 1 # the build fails below AQK-1, or if any declared gate failed
|
|
367
374
|
```
|
package/README.ru.md
CHANGED
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
вообще перечисленные там команды. AQK — тот самый недостающий слой: одна команда читает
|
|
15
15
|
репозиторий, называет ступень от AQK-0 до AQK-3 и перечисляет каждого недостающего сторожа.
|
|
16
16
|
|
|
17
|
+
И один шаг дальше, чем соседние инструменты: `probe` подсаживает заведомый дефект в копию вашего
|
|
18
|
+
проекта и смотрит, покраснеет ли **объявленная** защита. «Тесты есть» и «тесты ловят» — разные
|
|
19
|
+
утверждения, и оценки готовности меряют первое.
|
|
20
|
+
|
|
17
21
|
```bash
|
|
18
22
|
npx agent-quality-kit doctor # код уже есть: уровень и что поставить
|
|
19
23
|
npx agent-quality-kit start # кода ещё нет: сторожа дня 0 сразу
|
|
@@ -21,7 +25,8 @@ npx agent-quality-kit start # кода ещё нет: сторожа дня
|
|
|
21
25
|
|
|
22
26
|
`doctor` только читает: ни одного файла не пишет и никуда ничего не отправляет — его можно
|
|
23
27
|
направить на репозиторий, о котором ещё ничего не решено. Ставить ничего не нужно, `npx` скачает
|
|
24
|
-
пакет сам (
|
|
28
|
+
пакет сам (574.1 kB, замер 2026-09-10 — это число не сторожит никто, так что при случае
|
|
29
|
+
перемерьте).
|
|
25
30
|
|
|
26
31
|
Единственное исключение, и названо оно здесь именно потому, что единственное: с `--brief`
|
|
27
32
|
(так его запускают хуки) `doctor` спрашивает у реестра npm свою последнюю версию — **не чаще
|
|
@@ -43,6 +48,8 @@ TypeScript, Go, Rust, Java, Ruby, PHP, C#, Kotlin, Swift, Scala. Там, где
|
|
|
43
48
|
сообщает, когда откатилась на переносимый.
|
|
44
49
|
|
|
45
50
|
**Требуется:** Node 18+ и оболочка `sh`. Есть на macOS, Linux и в WSL; на Windows — Git Bash.
|
|
51
|
+
На Windows гейты идут через Git Bash, даже если `bash` в PATH — заглушка WSL из `System32`:
|
|
52
|
+
он ищется рядом с `git.exe`; другой путь задаётся `AQK_BASH`.
|
|
46
53
|
|
|
47
54
|
### Одно движение, из которого следует всё остальное
|
|
48
55
|
|
|
@@ -343,7 +350,7 @@ aqk badge --check # в конвейере: код 1 в тот день, ког
|
|
|
343
350
|
```yaml
|
|
344
351
|
repos:
|
|
345
352
|
- repo: https://github.com/arsen-ask-lx/Agent_Quality_Kit
|
|
346
|
-
rev: v0.
|
|
353
|
+
rev: v0.12.0
|
|
347
354
|
hooks:
|
|
348
355
|
- id: aqk # запускает объявленное; роняет коммит ниже AQK-1
|
|
349
356
|
# - id: aqk-doctor # только осмотр: уровень и чего не хватает, ничего не роняет
|
|
@@ -362,7 +369,7 @@ repos:
|
|
|
362
369
|
[](https://github.com/marketplace/actions/agent-quality-kit-aqk)
|
|
363
370
|
|
|
364
371
|
```yaml
|
|
365
|
-
- uses: arsen-ask-lx/Agent_Quality_Kit@v0.
|
|
372
|
+
- uses: arsen-ask-lx/Agent_Quality_Kit@v0.12.0
|
|
366
373
|
with:
|
|
367
374
|
min: 1 # сборка падает ниже AQK-1 или если упал любой объявленный гейт
|
|
368
375
|
```
|
package/kit/gates/_native.sh
CHANGED
|
@@ -21,6 +21,10 @@ shift || true
|
|
|
21
21
|
[ "$#" -gt 0 ] || { echo "нечего запускать: не передана команда инструмента"; exit 2; }
|
|
22
22
|
|
|
23
23
|
. "$(dirname "$0")/_skip.sh" 2>/dev/null || { echo "не найден _skip.sh рядом с _native.sh"; exit 2; }
|
|
24
|
+
if [ "${AQK_SKIP_READY:-}" != 1 ]; then
|
|
25
|
+
echo "_skip.sh есть, но обход не собрался — проверка НЕ СОСТОЯЛАСЬ, а не прошла"
|
|
26
|
+
exit 2
|
|
27
|
+
fi
|
|
24
28
|
|
|
25
29
|
# Два фильтра, а не один: own_samples_filter прячет образцы гейтов и то, что назвал проект
|
|
26
30
|
# в .aqkignore, а skip_paths_filter — общий список каталогов, который переносимые проверки
|
package/kit/gates/_skip.sh
CHANGED
|
@@ -182,3 +182,10 @@ drop_comments() { grep -vE '^[^:]*:[0-9]+:[[:space:]]*(//|\*|#|/\*|--)' ; }
|
|
|
182
182
|
# `sh` в списке нет намеренно: печать в скрипте — его способ говорить с человеком, и запрет
|
|
183
183
|
# отладочной печати покрасил бы каждый из них.
|
|
184
184
|
only_code() { grep -E "\.($(printf '%s' "$CODE_EXT" | tr ' ' '|'))$"; }
|
|
185
|
+
|
|
186
|
+
# Метка собранности. Ставится ПОСЛЕДНЕЙ строкой намеренно: она подтверждает, что файл дочитан
|
|
187
|
+
# до конца, а не только начат. Подключающий обязан её проверить — до 2026-09-10 он проверял
|
|
188
|
+
# лишь НАЛИЧИЕ файла, и подмена содержимого давала код 0: гейт печатал «command not found» и
|
|
189
|
+
# объявлял проект чистым. Библиотеку подключает каждая запись каталога, то есть одним
|
|
190
|
+
# испорченным файлом гасился весь набор защит.
|
|
191
|
+
AQK_SKIP_READY=1
|
|
@@ -21,6 +21,13 @@ if [ ! -f "$SKIP_LIB" ]; then
|
|
|
21
21
|
exit 2
|
|
22
22
|
fi
|
|
23
23
|
. "$SKIP_LIB"
|
|
24
|
+
# Файл на месте — этого мало: подмена содержимого давала код 0. Метка стоит в КОНЦЕ _skip.sh,
|
|
25
|
+
# поэтому проверка ловит и обрыв файла на середине.
|
|
26
|
+
if [ "${AQK_SKIP_READY:-}" != 1 ]; then
|
|
27
|
+
echo "_skip.sh есть, но обход не собрался — проверка НЕ СОСТОЯЛАСЬ, а не прошла"
|
|
28
|
+
echo " почини: замени kit/gates/_skip.sh целым файлом из каталога"
|
|
29
|
+
exit 2
|
|
30
|
+
fi
|
|
24
31
|
|
|
25
32
|
# --- есть ли договор ----------------------------------------------------------
|
|
26
33
|
# По имени файла, а не по расположению: спецификацию кладут в корень, в `docs/`, рядом с
|
|
@@ -18,6 +18,13 @@ if [ ! -f "$SKIP_LIB" ]; then
|
|
|
18
18
|
exit 2
|
|
19
19
|
fi
|
|
20
20
|
. "$SKIP_LIB"
|
|
21
|
+
# Файл на месте — этого мало: подмена содержимого давала код 0. Метка стоит в КОНЦЕ _skip.sh,
|
|
22
|
+
# поэтому проверка ловит и обрыв файла на середине.
|
|
23
|
+
if [ "${AQK_SKIP_READY:-}" != 1 ]; then
|
|
24
|
+
echo "_skip.sh есть, но обход не собрался — проверка НЕ СОСТОЯЛАСЬ, а не прошла"
|
|
25
|
+
echo " почини: замени kit/gates/_skip.sh целым файлом из каталога"
|
|
26
|
+
exit 2
|
|
27
|
+
fi
|
|
21
28
|
|
|
22
29
|
# Расширения, где живёт ТЕМИЗИРУЕМЫЙ интерфейс. Своё, а не общий CODE_EXT: там нет ни css, ни
|
|
23
30
|
# vue — они не код в смысле «отладочная печать», но именно в них живёт цвет.
|
|
@@ -15,8 +15,14 @@ if [ -f "$DIR/.aqk-commit-msg" ]; then
|
|
|
15
15
|
MSG=$(cat "$DIR/.aqk-commit-msg")
|
|
16
16
|
else
|
|
17
17
|
if ! (cd "$DIR" 2>/dev/null && git rev-parse --git-dir >/dev/null 2>&1); then
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
# НЕ «проверять нечего», а «проверить нечем»: без истории свидетель слеп, и код 0 здесь
|
|
19
|
+
# неотличим от «проверено и чисто». Договор комплекта: 0 — чисто, 1 — находка, остальное —
|
|
20
|
+
# не смогли. Тот же довод уже записан ниже про мелкий клон и в protection-not-removed:
|
|
21
|
+
# когда свидетель слеп, зеленеть нельзя.
|
|
22
|
+
echo "не git-репозиторий — историю смотреть нечем, проверка НЕ СОСТОЯЛАСЬ"
|
|
23
|
+
echo " почини: запусти проверку в репозитории, либо убери запись из манифеста —"
|
|
24
|
+
echo " почини: гейт, который не может посмотреть, не защищает ничего."
|
|
25
|
+
exit 2
|
|
20
26
|
fi
|
|
21
27
|
# Мелкий клон: у коммита не видно родителя, и git выдаёт всё дерево как изменённое. Состав
|
|
22
28
|
# коммита в этом случае не определить, а требовать отчёт вслепую нельзя — конвейер краснел бы
|
|
@@ -19,6 +19,13 @@ if [ ! -f "$SKIP_LIB" ]; then
|
|
|
19
19
|
exit 2
|
|
20
20
|
fi
|
|
21
21
|
. "$SKIP_LIB"
|
|
22
|
+
# Файл на месте — этого мало: подмена содержимого давала код 0. Метка стоит в КОНЦЕ _skip.sh,
|
|
23
|
+
# поэтому проверка ловит и обрыв файла на середине.
|
|
24
|
+
if [ "${AQK_SKIP_READY:-}" != 1 ]; then
|
|
25
|
+
echo "_skip.sh есть, но обход не собрался — проверка НЕ СОСТОЯЛАСЬ, а не прошла"
|
|
26
|
+
echo " почини: замени kit/gates/_skip.sh целым файлом из каталога"
|
|
27
|
+
exit 2
|
|
28
|
+
fi
|
|
22
29
|
MAX="${AQK_MAX_DEPTH:-5}"
|
|
23
30
|
|
|
24
31
|
# Тесты исключены намеренно — тем же списком, что и в duplicate-code. Глубокая вложенность в
|
|
@@ -36,8 +43,19 @@ find "$DIR" $(skip_find "$DIR") $TESTS -type f \
|
|
|
36
43
|
# Разметка вложена по природе: пять уровней тегов — это не сложная логика, а обычная
|
|
37
44
|
# вёрстка. Меряя её тем же пределом, гейт краснеет на нормальном коде и его выключают.
|
|
38
45
|
function limit() { return (wf ~ /\.(jsx|tsx|vue|svelte)$/) ? MAX + 3 : MAX }
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
# Шаг отступа берётся ИЗ ФАЙЛА, а не считается равным четырём. Пока он был прибит к
|
|
47
|
+
# четырём, проверка видела ВДВОЕ МЕНЬШУЮ вложенность в javascript и typescript, где
|
|
48
|
+
# общепринятый отступ — два пробела: шесть уровней давали «три» и проходили предел
|
|
49
|
+
# молча. Замечено 2026-09-10, когда в каталог впервые добавили образец на .js: go и
|
|
50
|
+
# python отступают на четыре, и на них дефекта не видно в принципе.
|
|
51
|
+
# Минимум зажат снизу двойкой: файл с одиночным пробелом в продолжении строки иначе
|
|
52
|
+
# вчетверо завысил бы вложенность и дал ложную тревогу.
|
|
53
|
+
function unit() { return (step >= 2 && step <= 8) ? step : 4 }
|
|
54
|
+
function flush() {
|
|
55
|
+
if (wf != "" && int(worstN / unit()) > limit())
|
|
56
|
+
print wf ":" wl ": вложенность " int(worstN / unit()) ", предел " limit()
|
|
57
|
+
}
|
|
58
|
+
FNR == 1 { flush(); worstN = 0; wl = 0; step = 0; wf = FILENAME }
|
|
41
59
|
/^[[:space:]]*$/ { next }
|
|
42
60
|
{
|
|
43
61
|
# ширина отступа: табуляция считается за четыре пробела. Отступ берётся ОДНИМ
|
|
@@ -45,8 +63,8 @@ find "$DIR" $(skip_find "$DIR") $TESTS -type f \
|
|
|
45
63
|
# символ отступа и стоил больше, чем весь остальной разбор. Замер 2026-09-08 на uv.
|
|
46
64
|
match($0, /^[ \t]*/); ind = substr($0, 1, RLENGTH)
|
|
47
65
|
n = gsub(/\t/, "", ind) * 4 + length(ind)
|
|
48
|
-
|
|
49
|
-
if (
|
|
66
|
+
if (n > 0 && (step == 0 || n < step)) step = n
|
|
67
|
+
if (n > worstN) { worstN = n; wl = FNR }
|
|
50
68
|
}
|
|
51
69
|
END { flush() }
|
|
52
70
|
' > /tmp/.cplx.$$ 2>/dev/null
|
|
@@ -4,11 +4,16 @@ intent_en: a function does not grow past the complexity you can hold in your hea
|
|
|
4
4
|
trigger:
|
|
5
5
|
always: true
|
|
6
6
|
|
|
7
|
+
# Домашние страницы готовых инструментов, которые зовут рецепты ниже. Адреса сверены
|
|
8
|
+
# по реестру github 2026-09-10, а не написаны по памяти: три выдуманных адреса чужих
|
|
9
|
+
# репозиториев — записанная шишка комплекта.
|
|
10
|
+
tool: https://github.com/astral-sh/ruff · https://github.com/eslint/eslint
|
|
11
|
+
|
|
7
12
|
recipes:
|
|
8
13
|
# Переносимая мера грубая — глубина вложенности. Готовые правила считают ветвления и
|
|
9
14
|
# инструкции, это точнее; см. kit/docs/ready-made-rules.md
|
|
10
15
|
any: bash {gate}/check.sh {dir}
|
|
11
|
-
python: ruff check --select C901,PLR0912,PLR0915 {dir}
|
|
12
|
-
typescript: eslint --rule '{"complexity":["error",10],"max-depth":["error",4]}' {dir}
|
|
16
|
+
python: ruff check -q --output-format=concise --select C901,PLR0912,PLR0915 {dir}
|
|
17
|
+
typescript: eslint --no-config-lookup --ignore-pattern 'gates/*/red/**' --ignore-pattern 'gates/*/green/**' --rule '{"complexity":["error",10],"max-depth":["error",4]}' {dir}
|
|
13
18
|
|
|
14
19
|
proof: incidents/README.md — «2026-08-27 ревизия гейтов», п. 6: 75 функций сложнее нормы, худшая с 29 ветвлениями
|
|
@@ -10,6 +10,11 @@ trigger:
|
|
|
10
10
|
# Переносимого рецепта здесь нет намеренно: чтобы понять, вызывают ли функцию, нужен граф
|
|
11
11
|
# вызовов, а не поиск по тексту. Это тот случай, когда без готового инструмента не обойтись —
|
|
12
12
|
# и он есть под каждый распространённый стек.
|
|
13
|
+
# Домашние страницы готовых инструментов, которые зовут рецепты ниже. Адреса сверены
|
|
14
|
+
# по реестру github 2026-09-10, а не написаны по памяти: три выдуманных адреса чужих
|
|
15
|
+
# репозиториев — записанная шишка комплекта.
|
|
16
|
+
tool: https://github.com/jendrikseipp/vulture · https://github.com/webpro-nl/knip
|
|
17
|
+
|
|
13
18
|
recipes:
|
|
14
19
|
python: vulture --min-confidence 60 {dir}
|
|
15
20
|
typescript: npx --yes knip@6 --directory {dir}
|
|
@@ -18,6 +18,13 @@ if [ ! -f "$SKIP_LIB" ]; then
|
|
|
18
18
|
exit 2
|
|
19
19
|
fi
|
|
20
20
|
. "$SKIP_LIB"
|
|
21
|
+
# Файл на месте — этого мало: подмена содержимого давала код 0. Метка стоит в КОНЦЕ _skip.sh,
|
|
22
|
+
# поэтому проверка ловит и обрыв файла на середине.
|
|
23
|
+
if [ "${AQK_SKIP_READY:-}" != 1 ]; then
|
|
24
|
+
echo "_skip.sh есть, но обход не собрался — проверка НЕ СОСТОЯЛАСЬ, а не прошла"
|
|
25
|
+
echo " почини: замени kit/gates/_skip.sh целым файлом из каталога"
|
|
26
|
+
exit 2
|
|
27
|
+
fi
|
|
21
28
|
WIN="${AQK_DUP_LINES:-8}"
|
|
22
29
|
|
|
23
30
|
# Тесты исключены намеренно. Повтор в тестах часто осознанный: читаемость там важнее сухости,
|
|
@@ -4,6 +4,11 @@ intent_en: the same code does not multiply into copies across the project
|
|
|
4
4
|
trigger:
|
|
5
5
|
files_gt: 20
|
|
6
6
|
|
|
7
|
+
# Домашние страницы готовых инструментов, которые зовут рецепты ниже. Адреса сверены
|
|
8
|
+
# по реестру github 2026-09-10, а не написаны по памяти: три выдуманных адреса чужих
|
|
9
|
+
# репозиториев — записанная шишка комплекта.
|
|
10
|
+
tool: https://github.com/kucherenko/jscpd · https://github.com/pylint-dev/pylint
|
|
11
|
+
|
|
7
12
|
recipes:
|
|
8
13
|
any: bash {gate}/check.sh {dir}
|
|
9
14
|
# jscpd умеет и Python, и TypeScript одним прогоном и считает похожесть, а не совпадение.
|
|
@@ -25,6 +30,10 @@ recipes:
|
|
|
25
30
|
# Родной инструмент стека, а не jscpd: питоновскому проекту незачем ставить Node ради одной
|
|
26
31
|
# проверки. R0801 сравнивает не байты, а разобранный код — переименованная переменная его
|
|
27
32
|
# не обманет, в отличие от переносимого рецепта.
|
|
28
|
-
|
|
33
|
+
# `--ignore-paths` — исключение на ВХОДЕ, а не фильтром вывода. `aqk add` кладёт красные
|
|
34
|
+
# образцы в проект, и они по построению дублируют друг друга: без исключения pylint
|
|
35
|
+
# предъявлял пользователю НАШИ ЖЕ файлы как его дубликаты. Найдено 2026-09-10 табличной
|
|
36
|
+
# проверкой own-samples в тот час, когда pylint появился на машине.
|
|
37
|
+
python: pylint --disable=all --enable=R0801 --min-similarity-lines=8 --ignore-paths='.*gates/[^/]+/(red|green)(/|$).*' {dir}
|
|
29
38
|
|
|
30
39
|
proof: incidents/README.md — «2026-08-25 разбор 1069 коммитов»: число моделей захардкожено в четырёх местах четырьмя разными значениями
|
|
@@ -18,6 +18,13 @@ if [ ! -f "$SKIP_LIB" ]; then
|
|
|
18
18
|
exit 2
|
|
19
19
|
fi
|
|
20
20
|
. "$SKIP_LIB"
|
|
21
|
+
# Файл на месте — этого мало: подмена содержимого давала код 0. Метка стоит в КОНЦЕ _skip.sh,
|
|
22
|
+
# поэтому проверка ловит и обрыв файла на середине.
|
|
23
|
+
if [ "${AQK_SKIP_READY:-}" != 1 ]; then
|
|
24
|
+
echo "_skip.sh есть, но обход не собрался — проверка НЕ СОСТОЯЛАСЬ, а не прошла"
|
|
25
|
+
echo " почини: замени kit/gates/_skip.sh целым файлом из каталога"
|
|
26
|
+
exit 2
|
|
27
|
+
fi
|
|
21
28
|
|
|
22
29
|
# Один обход и один wc на все файлы разом: на проекте в 36 тысяч файлов цикл с wc на каждый
|
|
23
30
|
# не укладывался в две минуты.
|