agent-quality-kit 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -9
- package/README.ru.md +167 -23
- package/kit/docs/ai/project-baseline.md +14 -0
- package/kit/docs/ready-made-rules.md +103 -0
- package/kit/gates/_skip.sh +61 -1
- package/kit/gates/ci-not-hijackable/README.md +56 -0
- package/kit/gates/ci-not-hijackable/check.sh +73 -0
- package/kit/gates/ci-not-hijackable/gate.yml +19 -0
- package/kit/gates/ci-not-hijackable/green/.github/workflows/triage.yml +19 -0
- package/kit/gates/ci-not-hijackable/red/.github/workflows/triage.yml +18 -0
- package/kit/gates/color-from-token/check.sh +10 -2
- package/kit/gates/color-from-token/green/Button.tsx +2 -0
- package/kit/gates/complexity-limit/check.sh +6 -7
- package/kit/gates/duplicate-code/check.sh +5 -1
- package/kit/gates/entry-links-exist/check.sh +4 -1
- package/kit/gates/entry-links-exist/green/AGENTS.md +2 -0
- package/kit/gates/file-size-limit/check.sh +1 -1
- package/kit/gates/lesson-has-outcome/check.sh +5 -1
- package/kit/gates/mcp-server-resolves/README.md +62 -0
- package/kit/gates/mcp-server-resolves/check.sh +110 -0
- package/kit/gates/mcp-server-resolves/gate.yml +18 -0
- package/kit/gates/mcp-server-resolves/green/.mcp.json +20 -0
- package/kit/gates/mcp-server-resolves/red/.mcp.json +16 -0
- package/kit/gates/secrets-not-in-code/check.sh +16 -3
- package/kit/gates/secrets-not-in-code/green/testdata/certificate/key.pem +3 -0
- package/kit/gates/todo-without-task/check.sh +1 -1
- package/kit/gates/todo-without-task/green/app.py +1 -0
- package/llms.txt +38 -2
- package/package.json +2 -3
- package/tool/commands/context.mjs +264 -0
- package/tool/commands/doctor.mjs +104 -28
- package/tool/commands/learn.mjs +159 -0
- package/tool/commands/project.mjs +19 -2
- package/tool/commands/prove.mjs +1 -0
- package/tool/commands/report.mjs +33 -1
- package/tool/commands/vitals.mjs +159 -0
- package/tool/i18n/en-docs.mjs +125 -1
- package/tool/i18n/en.mjs +39 -36
- package/tool/i18n/index.mjs +36 -3
- package/tool/i18n/ru-docs.mjs +127 -1
- package/tool/i18n/ru.mjs +39 -36
- package/tool/lib/banner.mjs +59 -0
- package/tool/lib/brief.mjs +192 -0
- package/tool/lib/core.mjs +32 -1
- package/tool/lib/evidence.mjs +124 -0
- package/tool/lib/manifest.mjs +173 -15
- package/tool/lib/prove.mjs +24 -2
- package/tool/lib/repo.mjs +31 -1
- package/tool/lib/scope.mjs +10 -1
- package/tool/lib/templates.mjs +1 -0
- package/tool/program.mjs +45 -23
- package/tool/selfcheck/smoke.sh +592 -3
- package/tool/selfcheck/units-banner.mjs +65 -0
- package/tool/selfcheck/units-brief.mjs +97 -0
- package/tool/selfcheck/units-context.mjs +188 -0
- package/tool/selfcheck/units-evidence.mjs +83 -0
- package/tool/selfcheck/units-learn.mjs +88 -0
- package/tool/selfcheck/units-level.mjs +211 -3
- package/tool/selfcheck/units-repo.mjs +134 -0
- package/tool/selfcheck/units-vitals.mjs +62 -0
- package/tool/selfcheck/units.mjs +4 -75
package/README.md
CHANGED
|
@@ -22,6 +22,12 @@ npx agent-quality-kit start # no code yet: day-zero guards, right away
|
|
|
22
22
|
`doctor` only reads. It writes no file and sends nothing anywhere — safe to point at a repository
|
|
23
23
|
you have decided nothing about yet. Nothing to install: `npx` fetches the package (230 KB).
|
|
24
24
|
|
|
25
|
+
The one exception, named here because it is the only one: with `--brief` (how the hooks run it)
|
|
26
|
+
`doctor` asks the npm registry for its own latest version — **at most once a day, never in CI**,
|
|
27
|
+
with a 3-second timeout, silent on any failure, and never affecting the exit code. Turn it off
|
|
28
|
+
with `AQK_UPDATE=0`. There is no auto-update: a tool that silently replaces itself while
|
|
29
|
+
standing on the commit gate is exactly the door this kit teaches you to close.
|
|
30
|
+
|
|
25
31
|
### Works with any agent, any language
|
|
26
32
|
|
|
27
33
|
**Any agent.** Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, Windsurf, Aider, OpenCode
|
|
@@ -63,6 +69,50 @@ tooling: [the dark factory and the minimum that isn't optional](kit/docs/ai/proj
|
|
|
63
69
|
a promise without an exit code is just a sentence
|
|
64
70
|
```
|
|
65
71
|
|
|
72
|
+
## Every command
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
aqk doctor what this repository is at, and what is missing
|
|
76
|
+
aqk doctor --run run every gate the manifest declares
|
|
77
|
+
aqk doctor --run --since main only what the diff introduced
|
|
78
|
+
aqk doctor --run --min 1 fail a pipeline below a level
|
|
79
|
+
aqk doctor --baseline the minimum a project needs, confirmed by a run
|
|
80
|
+
|
|
81
|
+
aqk init lay the kit into an existing repository
|
|
82
|
+
aqk start start a new project from the kit
|
|
83
|
+
aqk add <name> install one guard from the catalogue
|
|
84
|
+
aqk new <name> scaffold a guard of your own
|
|
85
|
+
aqk find <text> find a guard by intent
|
|
86
|
+
aqk why <name> what failure this guard was written for
|
|
87
|
+
|
|
88
|
+
aqk prove run every declared gate against its own samples:
|
|
89
|
+
red on the red one, quiet on the green one
|
|
90
|
+
aqk report the report form, assembled by a run
|
|
91
|
+
aqk report --since main ...plus what proves this diff, file by file
|
|
92
|
+
aqk badge write the level badge into the README
|
|
93
|
+
aqk badge --check fail if the badge disagrees with a run
|
|
94
|
+
|
|
95
|
+
aqk context the repository state in one block, for an agent's context:
|
|
96
|
+
level, what is red now, rules nobody enforces, ratchets
|
|
97
|
+
aqk vitals is what the kit runs on wired up: gate tools, hooks, freshness
|
|
98
|
+
aqk doctor --run --brief one line on success, the whole run on failure — for hooks
|
|
99
|
+
aqk context --full the same plus the command map and the rulebook verbatim (~7000
|
|
100
|
+
tokens against ~375: the price of an agent that does not guess)
|
|
101
|
+
aqk context --install put a SessionStart hook into .claude/settings.json
|
|
102
|
+
(add --full to install the full block)
|
|
103
|
+
|
|
104
|
+
aqk learn rule candidates from local transcripts:
|
|
105
|
+
said out loud, never written down
|
|
106
|
+
aqk note "..." write a bruise into the journal
|
|
107
|
+
aqk ratchet <name> a debt registry for a declared gate: may only get shorter
|
|
108
|
+
aqk blob every guide as a single file
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Exit codes: `0` pass, `1` below the level or a gate failed. Two exceptions, both deliberate:
|
|
112
|
+
`learn` never fails a build — it reads transcripts and prints to the terminal only, writing
|
|
113
|
+
nothing. And `--baseline` is an inspection, not a run: it always exits `0`, so combining it with
|
|
114
|
+
`--run` or `--min` is refused outright rather than handing you a pipeline that cannot go red.
|
|
115
|
+
|
|
66
116
|
## What this looks like
|
|
67
117
|
|
|
68
118
|
Someone else's project, three files, nothing configured:
|
|
@@ -123,9 +173,13 @@ The whole standard is one `.aqk.yml` file in the repository root:
|
|
|
123
173
|
aqk: 1
|
|
124
174
|
entry: [AGENTS.md] # what the agent reads first
|
|
125
175
|
rules: .aqk/rules # where the standards live
|
|
176
|
+
docs: .aqk/docs # where the guides live (optional; this is the default)
|
|
177
|
+
lang: en # output language for THIS repo, over the machine locale
|
|
126
178
|
gates: # what must pass — as commands, not as prose
|
|
127
179
|
lint: "npm run lint"
|
|
128
180
|
secrets-not-in-code: "bash gates/secrets-not-in-code/check.sh ."
|
|
181
|
+
covers: # what a declared gate already holds — not counted as debt
|
|
182
|
+
lint: [no-print-in-prod, swallowed-error]
|
|
129
183
|
samples: gates # a red and a green sample for every entry
|
|
130
184
|
ratchets: ratchets # debt registries: the list may only get shorter
|
|
131
185
|
lessons: incidents # where lessons accumulate
|
|
@@ -177,6 +231,43 @@ A hundred working checks with no manifest is AQK-0, and that is honest: nothing
|
|
|
177
231
|
aqk doctor --run --min 1 # in CI: fails below AQK-1 OR if any gate failed
|
|
178
232
|
```
|
|
179
233
|
|
|
234
|
+
### How a gate is proven — what `prove` actually does
|
|
235
|
+
|
|
236
|
+
Level AQK-2 and the badge rest on one command, so here it is in full: the first outside user
|
|
237
|
+
tripped over it three times, and all three times this page was to blame.
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
aqk prove
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
For every gate in `gates:` its samples are taken — `<samples>/<name>/red` and `/green` — and the
|
|
244
|
+
gate is run against each. **The directory is substituted for the LAST word of the command:**
|
|
245
|
+
catalogue recipes are written as `… {dir}`, and on install `{dir}` becomes `.`. Wrappers are
|
|
246
|
+
stripped first: `ratchet.sh` (otherwise the debt registry is rewritten with findings from the
|
|
247
|
+
sample) and `_native.sh` (otherwise the filter hides exactly what the sample must show).
|
|
248
|
+
|
|
249
|
+
Each entry gets one of three verdicts:
|
|
250
|
+
|
|
251
|
+
| Verdict | What it means |
|
|
252
|
+
|---|---|
|
|
253
|
+
| **proven** | exit ≠ 0 on `red/` and exit 0 on `green/` |
|
|
254
|
+
| **does not catch** | stayed quiet on the red one, or went red on the green one |
|
|
255
|
+
| **nothing to prove with** | four different reasons, and each is named out loud |
|
|
256
|
+
|
|
257
|
+
The four reasons: no samples · samples written for another recipe (`samples_for`) while a
|
|
258
|
+
different one is installed · the command does not end in a directory, so it was written by hand
|
|
259
|
+
and there is nowhere to substitute · **the program named in `requires:` is not on the machine.**
|
|
260
|
+
|
|
261
|
+
That last reason was added 2026-09-09 and deserves a word. A portable recipe is sometimes a
|
|
262
|
+
wrapper around a ready-made tool: the first word of the command is then `bash`, and nothing in it
|
|
263
|
+
shows what is missing. Without the program the wrapper goes red on **both** samples — and `prove`
|
|
264
|
+
declared a working gate broken, taking a level away from a project because somebody else's tool
|
|
265
|
+
was not installed. An accusation instead of a diagnosis; the same class as the Windows paths.
|
|
266
|
+
|
|
267
|
+
The level is granted when **no provable gate is broken AND at least one is proven**. The second
|
|
268
|
+
condition is not optional: a project where everything is unprovable has proven nothing — that is
|
|
269
|
+
exactly what the forgery with three `true` gates looks like.
|
|
270
|
+
|
|
180
271
|
## The badge
|
|
181
272
|
|
|
182
273
|
```bash
|
|
@@ -196,7 +287,7 @@ Already using [pre-commit](https://pre-commit.com)? Three lines in the file you
|
|
|
196
287
|
```yaml
|
|
197
288
|
repos:
|
|
198
289
|
- repo: https://github.com/arsen-ask-lx/Agent_Quality_Kit
|
|
199
|
-
rev: v0.
|
|
290
|
+
rev: v0.9.0
|
|
200
291
|
hooks:
|
|
201
292
|
- id: aqk # runs what the repository declares; blocks below AQK-1
|
|
202
293
|
# - id: aqk-doctor # read-only: the level and what is missing, blocks nothing
|
|
@@ -217,7 +308,7 @@ layer AQK adds.
|
|
|
217
308
|
[](https://github.com/marketplace/actions/agent-quality-kit-aqk)
|
|
218
309
|
|
|
219
310
|
```yaml
|
|
220
|
-
- uses: arsen-ask-lx/Agent_Quality_Kit@v0.
|
|
311
|
+
- uses: arsen-ask-lx/Agent_Quality_Kit@v0.9.0
|
|
221
312
|
with:
|
|
222
313
|
min: 1 # the build fails below AQK-1, or if any declared gate failed
|
|
223
314
|
```
|
|
@@ -229,6 +320,27 @@ the same thing in a single line:
|
|
|
229
320
|
- run: npx agent-quality-kit doctor --run --min 1
|
|
230
321
|
```
|
|
231
322
|
|
|
323
|
+
## Without Node at all
|
|
324
|
+
|
|
325
|
+
A Python, Go or Rust project where nobody installed Node and nobody will:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
docker build -t aqk . # from this repository
|
|
329
|
+
docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/work" aqk doctor
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
From v0.9.0 the image is pushed to the registry by the same run that publishes the package, so
|
|
333
|
+
there is nothing to build: `ghcr.io/arsen-ask-lx/aqk`. Before that tag the registry holds no
|
|
334
|
+
image, and this says so plainly: a command that points at nothing is worse than no command.
|
|
335
|
+
|
|
336
|
+
**The `--user` flag is not decoration.** Without it the container runs as root and the files
|
|
337
|
+
`init` writes end up owned by root — you cannot edit your own manifest. Measured 2026-09-09:
|
|
338
|
+
`.aqk.yml` and `AGENTS.md` came out `root:root`.
|
|
339
|
+
|
|
340
|
+
Debian-slim on purpose, not alpine: the gates are `sh`, `grep`, `awk`, `find`, and in alpine
|
|
341
|
+
those are busybox, whose `awk` differs. An image where the gates behave differently from the
|
|
342
|
+
machine the person is on is worse than no image: it hands out a green that means nothing.
|
|
343
|
+
|
|
232
344
|
## Installing a gate
|
|
233
345
|
|
|
234
346
|
```bash
|
|
@@ -273,8 +385,17 @@ advisory:
|
|
|
273
385
|
|
|
274
386
|
Declared in the manifest, not passed as a flag. A flag that says "fail nothing" downgrades every
|
|
275
387
|
check at once, is invisible in the diff, and is never named in the summary — that is
|
|
276
|
-
`continue-on-error`, which this tool marks red elsewhere.
|
|
277
|
-
|
|
388
|
+
`continue-on-error`, which this tool marks red elsewhere.
|
|
389
|
+
|
|
390
|
+
**An advisory gate is marked on EVERY run, including when it is green:**
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
✔ complexity-limit (advisory — cannot fail the run) 0.4s · …
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Otherwise a gate that cannot fail the build looks exactly like one that can, and you learn what
|
|
397
|
+
is in `advisory:` only on the day it goes red. Red ones are additionally named by name in the
|
|
398
|
+
summary: an advisory gate everyone forgot about is a switched-off check.
|
|
278
399
|
|
|
279
400
|
## When a bug slips past the guards
|
|
280
401
|
|
|
@@ -369,8 +490,13 @@ scenarios, the success criterion, and what is left.
|
|
|
369
490
|
|
|
370
491
|
Version 1, one author. The kit holds **AQK-3** on itself: everything declared is executed by CI
|
|
371
492
|
on every push, two debt registries under a ratchet — `node tool/program.mjs doctor --run --min 1`.
|
|
372
|
-
|
|
373
|
-
|
|
493
|
+
|
|
494
|
+
**The first outside user arrived on 2026-09-08** — ran the kit on their own project (28 gates,
|
|
495
|
+
AQK-1) and sent back a review. That review found two defects ninety-odd checks of our own had
|
|
496
|
+
missed: both live only on Windows, or only on somebody else's directory layout (bruise journal,
|
|
497
|
+
entry of 2026-09-08). That is exactly what an outsider is for — but it is one review, not settled
|
|
498
|
+
use. Until somebody comes back to the tool a second time, the standard is unproven on foreign
|
|
499
|
+
projects.
|
|
374
500
|
|
|
375
501
|
**A standard cannot be shipped first.** A specification ahead of practice is the thirty-first
|
|
376
502
|
abandoned repository with a manifest and zero users. The order is the other way round:
|
|
@@ -380,7 +506,7 @@ abandoned repository with a manifest and zero users. The order is the other way
|
|
|
380
506
|
| 1 | live by this on our own projects | ⬜ measured: three of our own projects have no manifest |
|
|
381
507
|
| 2 | `doctor` computes the level | ✅ done |
|
|
382
508
|
| 3 | what settled is written up as a short spec | ✅ [`SPEC.md`](SPEC.md) |
|
|
383
|
-
| 4 | a third project — **someone else's** |
|
|
509
|
+
| 4 | a third project — **someone else's** | 🟡 one outside run and review, 2026-09-08; no repeat use yet |
|
|
384
510
|
| 5 | badge, site, talking to people | ❌ only after step four |
|
|
385
511
|
|
|
386
512
|
## The work queue
|
|
@@ -388,7 +514,7 @@ abandoned repository with a manifest and zero users. The order is the other way
|
|
|
388
514
|
Lives in one place — [`PROJECT.md` §9](PROJECT.md). It is not repeated here: two lists drift
|
|
389
515
|
apart within a month, and then nobody knows which is real.
|
|
390
516
|
|
|
391
|
-
What is missing: a second
|
|
392
|
-
exercised by a clean-folder run, but not individually)
|
|
517
|
+
What is missing: a user who came back a second time; per-command coverage of the commands that
|
|
518
|
+
write to disk (they are exercised by a clean-folder run, but not individually).
|
|
393
519
|
|
|
394
520
|
MIT.
|
package/README.ru.md
CHANGED
|
@@ -23,6 +23,13 @@ npx agent-quality-kit start # кода ещё нет: сторожа дня
|
|
|
23
23
|
направить на репозиторий, о котором ещё ничего не решено. Ставить ничего не нужно, `npx` скачает
|
|
24
24
|
пакет сам (230 КБ).
|
|
25
25
|
|
|
26
|
+
Единственное исключение, и названо оно здесь именно потому, что единственное: с `--brief`
|
|
27
|
+
(так его запускают хуки) `doctor` спрашивает у реестра npm свою последнюю версию — **не чаще
|
|
28
|
+
раза в сутки и никогда в конвейере**, с таймаутом в три секунды, молча при любой ошибке и
|
|
29
|
+
не влияя на код возврата. Выключается `AQK_UPDATE=0`. Автообновления нет: инструмент,
|
|
30
|
+
который молча подменяет себя, стоя на воротах коммита, — ровно та дверь, которую комплект
|
|
31
|
+
учит закрывать.
|
|
32
|
+
|
|
26
33
|
### Работает с любым агентом и любым языком
|
|
27
34
|
|
|
28
35
|
**Любой агент.** Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, Windsurf, Aider,
|
|
@@ -64,6 +71,50 @@ flowchart LR
|
|
|
64
71
|
обещание без кода возврата — просто предложение
|
|
65
72
|
```
|
|
66
73
|
|
|
74
|
+
## Все команды
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
aqk doctor где этот репозиторий и чего в нём не хватает
|
|
78
|
+
aqk doctor --run прогнать все гейты, объявленные в манифесте
|
|
79
|
+
aqk doctor --run --since main только то, что внёс диф
|
|
80
|
+
aqk doctor --run --min 1 уронить конвейер ниже ступени
|
|
81
|
+
aqk doctor --baseline обязательный минимум проекта, подтверждённый прогоном
|
|
82
|
+
|
|
83
|
+
aqk init разложить комплект в существующий репозиторий
|
|
84
|
+
aqk start начать новый проект с комплектом
|
|
85
|
+
aqk add <имя> поставить один гейт из каталога
|
|
86
|
+
aqk new <имя> завести свой гейт по форме
|
|
87
|
+
aqk find <текст> найти гейт по намерению
|
|
88
|
+
aqk why <имя> какой отказ этот гейт поймал
|
|
89
|
+
|
|
90
|
+
aqk prove прогнать каждый объявленный гейт по его образцам:
|
|
91
|
+
красный на красном, тишина на зелёном
|
|
92
|
+
aqk report форма отчёта, собранная прогоном
|
|
93
|
+
aqk report --since main ...и чем доказан этот диф, файл за файлом
|
|
94
|
+
aqk badge вписать значок уровня в README
|
|
95
|
+
aqk badge --check упасть, если значок расходится с прогоном
|
|
96
|
+
|
|
97
|
+
aqk context состояние репозитория одним блоком, для контекста агента:
|
|
98
|
+
уровень, что красное сейчас, правила без арбитра, храповики
|
|
99
|
+
aqk vitals подключено ли то, чем комплект работает: инструменты, хуки, свежесть
|
|
100
|
+
aqk doctor --run --brief одна строка на успехе, весь прогон при провале — для хуков
|
|
101
|
+
aqk context --full то же плюс карта команд и свод правил дословно (≈7000 токенов
|
|
102
|
+
против ≈375 — плата за то, чтобы агент не догадывался)
|
|
103
|
+
aqk context --install поставить хук SessionStart в .claude/settings.json
|
|
104
|
+
(с --full ставится полный блок)
|
|
105
|
+
|
|
106
|
+
aqk learn кандидаты в правила из локальной переписки:
|
|
107
|
+
что сказано вслух и не записано
|
|
108
|
+
aqk note "..." записать шишку в журнал
|
|
109
|
+
aqk ratchet <имя> реестр долга для объявленного гейта: может только укорачиваться
|
|
110
|
+
aqk blob все методички одним файлом
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Коды возврата: `0` — прошло, `1` — ниже ступени или упал гейт. Два исключения, оба намеренные:
|
|
114
|
+
`learn` не роняет сборку никогда — он читает переписку и печатает только в терминал, не записывая
|
|
115
|
+
ничего. А `--baseline` — осмотр, а не прогон: он выходит с нулём всегда, поэтому вместе с `--run`
|
|
116
|
+
или `--min` он теперь отказывает вслух, а не выдаёт конвейер, который не может покраснеть.
|
|
117
|
+
|
|
67
118
|
## Что это выглядит так
|
|
68
119
|
|
|
69
120
|
Чужой проект, три файла, ничего не настроено:
|
|
@@ -124,9 +175,13 @@ Issue» — ничего не постится сама, только текст
|
|
|
124
175
|
aqk: 1
|
|
125
176
|
entry: [AGENTS.md] # что агент читает первым
|
|
126
177
|
rules: .aqk/rules # где стандарты
|
|
178
|
+
docs: .aqk/docs # где методички (необязательно, это и есть умолчание)
|
|
179
|
+
lang: ru # язык вывода для ЭТОГО репозитория, поверх локали машины
|
|
127
180
|
gates: # что обязано пройти — командами, не словами
|
|
128
181
|
lint: "npm run lint"
|
|
129
182
|
secrets-not-in-code: "bash gates/secrets-not-in-code/check.sh ."
|
|
183
|
+
covers: # что уже держит объявленный гейт — в долг не пишется
|
|
184
|
+
lint: [no-print-in-prod, swallowed-error]
|
|
130
185
|
samples: gates # красный и зелёный образец каждой записи
|
|
131
186
|
ratchets: ratchets # реестры долга: список может только укорачиваться
|
|
132
187
|
lessons: incidents # где копятся уроки
|
|
@@ -178,6 +233,43 @@ flowchart LR
|
|
|
178
233
|
aqk doctor --run --min 1 # в конвейере: ошибка, если ниже AQK-1 ИЛИ упал хоть один гейт
|
|
179
234
|
```
|
|
180
235
|
|
|
236
|
+
### Как гейт доказывается — устройство `prove`
|
|
237
|
+
|
|
238
|
+
Ступень AQK-2 и значок держатся на одной команде, поэтому она описана здесь целиком: первый
|
|
239
|
+
чужой пользователь споткнулся об неё трижды, и все три раза виновата была эта страница.
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
aqk prove
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Для каждого гейта из `gates:` берутся его образцы — `<samples>/<имя>/red` и `/green` — и гейт
|
|
246
|
+
запускается по каждому. **Каталог подставляется на место ПОСЛЕДНЕГО слова команды:** рецепты
|
|
247
|
+
каталога пишутся как `… {dir}`, и при установке `{dir}` превращается в `.`. Обёртки снимаются
|
|
248
|
+
заранее: `ratchet.sh` (иначе реестр долга перепишется находками из образца) и `_native.sh`
|
|
249
|
+
(иначе фильтр спрячет ровно то, что образец обязан показать).
|
|
250
|
+
|
|
251
|
+
Вердикт у каждой записи один из трёх:
|
|
252
|
+
|
|
253
|
+
| Вердикт | Что значит |
|
|
254
|
+
|---|---|
|
|
255
|
+
| **доказан** | код ≠ 0 на `red/` и код 0 на `green/` |
|
|
256
|
+
| **не ловит** | промолчал на красном, либо покраснел на зелёном |
|
|
257
|
+
| **доказывать нечем** | и вот здесь четыре разные причины, и они называются вслух |
|
|
258
|
+
|
|
259
|
+
Причин «доказывать нечем» четыре: образцов нет · образцы написаны под другой рецепт
|
|
260
|
+
(`samples_for`), а в проекте стоит не он · команда не кончается каталогом — значит написана
|
|
261
|
+
руками, и подставлять некуда · **программы, названной в `requires:`, нет на машине.**
|
|
262
|
+
|
|
263
|
+
Последняя причина заведена 2026-09-09 и стоит отдельного слова. Переносимый рецепт бывает
|
|
264
|
+
обёрткой вокруг готового инструмента: первое слово команды тогда `bash`, и по нему не видно,
|
|
265
|
+
чего не хватает. Без программы обёртка краснеет на **обоих** образцах — и `prove` объявлял
|
|
266
|
+
исправный гейт сломанным, отбирая у проекта ступень за то, что на машине нет чужого
|
|
267
|
+
инструмента. Обвинение вместо диагноза; ровно тот же класс, что windows-пути.
|
|
268
|
+
|
|
269
|
+
Ступень берётся, когда **ни один доказуемый гейт не сломан И доказан хотя бы один**. Второе
|
|
270
|
+
условие обязательно: проект, у которого все гейты недоказуемы, не доказал ничего — именно так
|
|
271
|
+
выглядит подделка с тремя гейтами `true`.
|
|
272
|
+
|
|
181
273
|
## Значок
|
|
182
274
|
|
|
183
275
|
```bash
|
|
@@ -198,7 +290,7 @@ aqk badge --check # в конвейере: код 1 в тот день, ког
|
|
|
198
290
|
```yaml
|
|
199
291
|
repos:
|
|
200
292
|
- repo: https://github.com/arsen-ask-lx/Agent_Quality_Kit
|
|
201
|
-
rev: v0.
|
|
293
|
+
rev: v0.9.0
|
|
202
294
|
hooks:
|
|
203
295
|
- id: aqk # запускает объявленное; роняет коммит ниже AQK-1
|
|
204
296
|
# - id: aqk-doctor # только осмотр: уровень и чего не хватает, ничего не роняет
|
|
@@ -217,7 +309,7 @@ repos:
|
|
|
217
309
|
[](https://github.com/marketplace/actions/agent-quality-kit-aqk)
|
|
218
310
|
|
|
219
311
|
```yaml
|
|
220
|
-
- uses: arsen-ask-lx/Agent_Quality_Kit@v0.
|
|
312
|
+
- uses: arsen-ask-lx/Agent_Quality_Kit@v0.9.0
|
|
221
313
|
with:
|
|
222
314
|
min: 1 # сборка падает ниже AQK-1 или если упал любой объявленный гейт
|
|
223
315
|
```
|
|
@@ -229,6 +321,27 @@ repos:
|
|
|
229
321
|
- run: npx agent-quality-kit doctor --run --min 1
|
|
230
322
|
```
|
|
231
323
|
|
|
324
|
+
## Без Node вовсе
|
|
325
|
+
|
|
326
|
+
Проект на Python, Go или Rust, где Node никто не ставил и не поставит:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
docker build -t aqk . # из этого репозитория
|
|
330
|
+
docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/work" aqk doctor
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
С версии 0.9.0 образ выкладывается в реестр тем же прогоном, что и пакет, — тогда собирать не
|
|
334
|
+
нужно: `ghcr.io/arsen-ask-lx/aqk`. До этой метки образа в реестре нет, и здесь это сказано
|
|
335
|
+
прямо: команда, указывающая в никуда, хуже её отсутствия.
|
|
336
|
+
|
|
337
|
+
**Ключ `--user` не украшение.** Без него контейнер работает от root, и файлы, которые пишет
|
|
338
|
+
`init`, достаются root — человек не может править собственный манифест. Проверено 2026-09-09:
|
|
339
|
+
`.aqk.yml` и `AGENTS.md` вышли с владельцем `root:root`.
|
|
340
|
+
|
|
341
|
+
Образ на debian-slim намеренно, а не на alpine: гейты — это `sh`, `grep`, `awk`, `find`, а в
|
|
342
|
+
alpine это busybox, и его `awk` другой. Образ, в котором гейты ведут себя не так, как на машине
|
|
343
|
+
человека, хуже отсутствия образа: он даёт зелёное, которое ничего не значит.
|
|
344
|
+
|
|
232
345
|
## Поставить гейт
|
|
233
346
|
|
|
234
347
|
```bash
|
|
@@ -236,13 +349,55 @@ aqk find "печать в проде" # есть ли уже такой ге
|
|
|
236
349
|
aqk doctor # что применимо к этому репозиторию и чего нет
|
|
237
350
|
aqk add secrets-not-in-code # копирует проверку и образцы в проект, объявляет в манифесте
|
|
238
351
|
aqk doctor --run # запускает объявленные гейты и показывает результат
|
|
352
|
+
aqk doctor --run --since main # ...но только то, что внёс диф
|
|
239
353
|
aqk ratchet no-print-in-prod # старое — долг, новое не пускать
|
|
240
354
|
```
|
|
241
355
|
|
|
356
|
+
### Первый прогон на настоящем проекте
|
|
357
|
+
|
|
358
|
+
У сложившегося репозитория за плечами годы долга. Прогони все гейты по всему коду — получишь
|
|
359
|
+
стену красного, которую никто не читает, и инструмент выключат. `--since <ref>` сужает вывод до
|
|
360
|
+
файлов, которых коснулся диф:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
aqk doctor --run --since main # только то, что внесла эта ветка
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Три исхода, и все три названы вслух. Находки внутри дифа — красный, как обычно. Находки только
|
|
367
|
+
снаружи — зелёный, с числом того, что скрыто, а не молчаливое «всё чисто». А гейт, в выводе
|
|
368
|
+
которого путей нет вовсе (проверка сообщения коммита, проверка конфига конвейера), сузиться
|
|
369
|
+
**не может**: он остаётся красным и говорит почему. Назвать его зелёным потому, что сужать было
|
|
370
|
+
нечего, — ровно та тишина, ради устранения которой этот инструмент и написан.
|
|
371
|
+
|
|
242
372
|
Каждый `doctor --run` перезаписывает `.aqk/last-run.md` — короткий отчёт, что из объявленного
|
|
243
373
|
реально сработало и за сколько. Список гейтов в манифесте молчит о том, сколько из них живы
|
|
244
374
|
именно сейчас; отчёт — нет. Файл эфемерный, в `.gitignore` его стоит держать самому.
|
|
245
375
|
|
|
376
|
+
### Как ввести правило в живой проект
|
|
377
|
+
|
|
378
|
+
Три способа, и у каждого своя цена. Большая чистка откладывается навсегда, потому что она
|
|
379
|
+
большая. Храповик превращает старые нарушения в долг и блокирует новые — верно, когда правило
|
|
380
|
+
уже принято. А пока о правиле спорят, совещательный гейт показывает находки, не роняя прогон:
|
|
381
|
+
|
|
382
|
+
```yaml
|
|
383
|
+
advisory:
|
|
384
|
+
- complexity-limit
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Объявлением в манифесте, а не флагом. Флаг «не роняй ничего» понижает все проверки разом, не
|
|
388
|
+
виден в дифе и не назван в итоге — это тот самый `continue-on-error`, который мы сами красим.
|
|
389
|
+
|
|
390
|
+
**Совещательный помечается в КАЖДОМ прогоне, в том числе когда он зелёный:**
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
✔ complexity-limit (совещательный — уронить прогон не может) 0.4s · …
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Иначе гейт, который уронить сборку не может, по выводу неотличим от того, который может, и о
|
|
397
|
+
списке `advisory:` человек узнаёт только в день, когда гейт покраснел. Покрасневшие вдобавок
|
|
398
|
+
названы в сводке поимённо: совещательный гейт, о котором забыли, — это выключенная проверка.
|
|
399
|
+
|
|
400
|
+
|
|
246
401
|
## Поймал ошибку, которую не поймал сторож
|
|
247
402
|
|
|
248
403
|
```bash
|
|
@@ -304,22 +459,6 @@ Ruff, ESLint и gitleaks и так находят плохой код — AQK з
|
|
|
304
459
|
[`agents-lint`](https://github.com/giacomo/agents-lint) делает это лучше, другую — потому что
|
|
305
460
|
91 находка из 120 оказалась законным приёмом.
|
|
306
461
|
|
|
307
|
-
### Как ввести правило в живой проект
|
|
308
|
-
|
|
309
|
-
Три способа, и у каждого своя цена. Большая чистка откладывается навсегда, потому что она
|
|
310
|
-
большая. Храповик превращает старые нарушения в долг и блокирует новые — верно, когда правило
|
|
311
|
-
уже принято. А пока о правиле спорят, совещательный гейт показывает находки, не роняя прогон:
|
|
312
|
-
|
|
313
|
-
```yaml
|
|
314
|
-
advisory:
|
|
315
|
-
- complexity-limit
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
Объявлением в манифесте, а не флагом. Флаг «не роняй ничего» понижает все проверки разом, не
|
|
319
|
-
виден в дифе и не назван в итоге — это тот самый `continue-on-error`, который мы сами красим.
|
|
320
|
-
Список печатается **каждый** прогон: совещательный гейт, о котором забыли, — это выключенная
|
|
321
|
-
проверка.
|
|
322
|
-
|
|
323
462
|
## Методички одним файлом
|
|
324
463
|
|
|
325
464
|
```bash
|
|
@@ -347,8 +486,13 @@ aqk note "гейт краснел на правильном коде" # за
|
|
|
347
486
|
|
|
348
487
|
Версия 1, один автор. Сам комплект держит **AQK-3**: всё объявленное прогоняется конвейером при
|
|
349
488
|
каждом пуше, два реестра долга под храповиком — `node tool/program.mjs doctor --run --min 1`.
|
|
350
|
-
|
|
351
|
-
|
|
489
|
+
|
|
490
|
+
**Первый посторонний пользователь появился 2026-09-08** — прогнал комплект на своём проекте
|
|
491
|
+
(28 гейтов, AQK-1) и прислал разбор. Он же нашёл два дефекта, которых не видели девяносто с
|
|
492
|
+
лишним наших собственных проверок: оба живут только на Windows или только на чужой раскладке
|
|
493
|
+
каталогов (журнал, запись от 2026-09-08). Это ровно то, ради чего нужен посторонний, — но это
|
|
494
|
+
один отзыв, а не сложившееся пользование. Пока за инструментом не вернулись второй раз, о
|
|
495
|
+
работоспособности стандарта на чужих проектах говорить рано.
|
|
352
496
|
|
|
353
497
|
**Стандарт нельзя выпустить первым.** Спецификация раньше практики — это тридцать первый
|
|
354
498
|
заброшенный репозиторий с манифестом и нулём пользователей. Порядок обратный:
|
|
@@ -358,7 +502,7 @@ aqk note "гейт краснел на правильном коде" # за
|
|
|
358
502
|
| 1 | живём по этому на своих проектах | ⬜ измерено: у трёх своих проектов манифеста нет, уровень не заведён |
|
|
359
503
|
| 2 | `doctor` считает уровень | ✅ сделано |
|
|
360
504
|
| 3 | сложившееся записано как короткая спецификация | ✅ [`SPEC.md`](SPEC.md) |
|
|
361
|
-
| 4 | третий проект — **чужой** |
|
|
505
|
+
| 4 | третий проект — **чужой** | 🟡 один посторонний прогон и разбор, 2026-09-08; повторного пользования ещё нет |
|
|
362
506
|
| 5 | значок, сайт, разговор с людьми | ❌ только после четвёртого шага |
|
|
363
507
|
|
|
364
508
|
## Очередь работ
|
|
@@ -366,7 +510,7 @@ aqk note "гейт краснел на правильном коде" # за
|
|
|
366
510
|
Живёт в одном месте — [`PROJECT.md` §9](PROJECT.md). Список здесь не повторяется: два списка через месяц
|
|
367
511
|
расходятся, и непонятно, какой настоящий.
|
|
368
512
|
|
|
369
|
-
Чего нет:
|
|
370
|
-
чистой папке, но не по отдельности)
|
|
513
|
+
Чего нет: пользователя, вернувшегося за инструментом второй раз; покрытия команд, которые пишут
|
|
514
|
+
на диск (проверены прогоном на чистой папке, но не по отдельности).
|
|
371
515
|
|
|
372
516
|
MIT.
|
|
@@ -189,6 +189,20 @@ tags:
|
|
|
189
189
|
40. **У агента есть способ проверить себя**: запустить тесты, поднять приложение, прочитать логи,
|
|
190
190
|
посмотреть метрики. Без этого он вынужден заканчивать словами «готово», и это слово ничего не
|
|
191
191
|
стоит.
|
|
192
|
+
|
|
193
|
+
**Если у проекта есть интерфейс — сюда же браузер.** Агент, который не может открыть страницу,
|
|
194
|
+
судит о своей работе по тому, что собралось; «собралось» и «работает» — разные утверждения,
|
|
195
|
+
и первое он выдаёт за второе не по злому умыслу, а потому что другого у него нет. Подключается
|
|
196
|
+
MCP-сервером, и это межвендорный протокол: одинаково работает с Claude Code, Cursor, Codex.
|
|
197
|
+
Два первых лица, оба проверены по реестру npm 2026-09-08:
|
|
198
|
+
[`chrome-devtools-mcp`](https://github.com/ChromeDevTools/chrome-devtools-mcp) от Google —
|
|
199
|
+
Lighthouse, трассировка производительности, сеть, консоль, память;
|
|
200
|
+
[`@playwright/mcp`](https://github.com/microsoft/playwright-mcp) от Microsoft — прогон
|
|
201
|
+
сценариев в трёх движках. Задачи разные, выбирает человек.
|
|
202
|
+
|
|
203
|
+
**Версию закрепить.** Сервер запускается командой вида `npx -y пакет@1.9.0`; без точной
|
|
204
|
+
версии при каждом запуске приезжает новая — а этому серверу отдан браузер со всем, что в нём
|
|
205
|
+
открыто. Это проверяет запись `mcp-server-resolves`.
|
|
192
206
|
41. **Сообщение об ошибке — это подсказка агенту.** Инструкция в тексте отказа стоит дешевле, чем
|
|
193
207
|
любые объяснения в документации: она приходит ровно в тот момент, когда нужна.
|
|
194
208
|
42. **Правила живут в репозитории и версионируются** вместе с кодом. Правило в переписке не
|
|
@@ -197,6 +197,58 @@ npm install -g agnix && agnix --strict .
|
|
|
197
197
|
настройкам нашёл шесть таких хуков в четырёх репозиториях — среди них `typecheck && test` перед
|
|
198
198
|
коммитом, не запускавшийся ни разу. Это запись `hook-actually-fires`.
|
|
199
199
|
|
|
200
|
+
Тот же класс у MCP: объявленный сервер, который не поднимается, агенту не виден никак — у него просто нет этих инструментов. Запись `mcp-server-resolves` ловит две самые частые смерти без запуска: команды по абсолютному пути, которой больше нет, и версии, которая не закреплена и приезжает новая при каждом запуске.
|
|
201
|
+
|
|
202
|
+
## Поиск на большом репозитории: `tgrep`, и как им пользоваться правильно
|
|
203
|
+
|
|
204
|
+
Переносимые проверки каталога ищут через `grep`. На проекте до нескольких тысяч файлов это
|
|
205
|
+
десятки миллисекунд, и менять там нечего. **От десятка тысяч файлов картина другая.**
|
|
206
|
+
|
|
207
|
+
[`tgrep`](https://github.com/microsoft/tgrep) — Microsoft, MIT, Rust: строит триграммный индекс
|
|
208
|
+
и держит фоновый сервер, следящий за изменениями. Замер 2026-09-09 на настоящем проекте, один
|
|
209
|
+
и тот же набор файлов, одна и та же регулярка:
|
|
210
|
+
|
|
211
|
+
| файлов в проекте | `grep` | `tgrep` |
|
|
212
|
+
|---|---|---|
|
|
213
|
+
| 277 | **6 мс** | индекс строится дольше, чем идёт поиск |
|
|
214
|
+
| 1 737 | **39 мс** | 77 мс |
|
|
215
|
+
| 37 760 | 96 мс | **16 мс**, полнота полная |
|
|
216
|
+
|
|
217
|
+
Перелом между двумя и десятью тысячами файлов. Их собственные замеры — на 96 000, 388 000 и
|
|
218
|
+
504 000 файлов, где выигрыш доходит до пятидесяти раз; заявка честная и подтверждается.
|
|
219
|
+
|
|
220
|
+
### Две грабли, на которые мы наступили сами
|
|
221
|
+
|
|
222
|
+
**Первая: по умолчанию он не видит точечные каталоги.** Индекс строится по видимым файлам, и
|
|
223
|
+
`.claude/`, `.github/`, `.env.example` для него не существуют. На нашем замере это было 32
|
|
224
|
+
найденных файла вместо 55 — и узнали мы это только сверкой со списком `grep`, а не из вывода.
|
|
225
|
+
Лечится флагом **при индексации**, а не при поиске:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
tgrep index . --hidden # без --hidden точечные каталоги не попадут в индекс
|
|
229
|
+
tgrep serve . # демон следит за изменениями
|
|
230
|
+
tgrep "что ищем" . # мгновенно, полнота как у grep
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Вторая: `--hidden` при ПОИСКЕ отключает индекс.** Это написано в их документации, раздел
|
|
234
|
+
«Flags that bypass the index», и мы это пропустили: первый замер дал «7 секунд, медленнее
|
|
235
|
+
grep» — потому что мерили обход дерева, а не индекс. Флаг ставится один раз, на `index`.
|
|
236
|
+
|
|
237
|
+
### Почему он не годится арбитром гейта
|
|
238
|
+
|
|
239
|
+
Проверено опытом: секрет, записанный **после** индексации, при запросе к устаревшему индексу
|
|
240
|
+
не находится, и код возврата — «совпадений нет». Для гейта секретов это молчаливое зелёное на
|
|
241
|
+
самом опасном месте. С работающим `tgrep serve` находится сразу — но тогда условие правильности
|
|
242
|
+
гейта звучит как «на машине поднят фоновый процесс», а гейт обязан быть прав без предварительных
|
|
243
|
+
условий.
|
|
244
|
+
|
|
245
|
+
Плюс два расхождения, о которых стоит знать: **коды возврата как у ripgrep** (`0` — совпадение
|
|
246
|
+
найдено, у гейтов наоборот) и **файлы больше 64 МиБ пропускаются** по умолчанию.
|
|
247
|
+
|
|
248
|
+
Вывод простой: **инструмент для человека, а не для ворот.** Ищете руками по большому
|
|
249
|
+
репозиторию — ставьте. Проверяете код перед коммитом — `grep` честнее, потому что не зависит ни
|
|
250
|
+
от чего.
|
|
251
|
+
|
|
200
252
|
## А если проект не на Python?
|
|
201
253
|
|
|
202
254
|
Ничего не меняется. Запись каталога держит **одно намерение и несколько исполнителей**, и
|
|
@@ -226,6 +278,57 @@ npm install -g agnix && agnix --strict .
|
|
|
226
278
|
| подавление проверки без адреса | наш `gate-not-weakened` плюс `eslint-plugin-eslint-comments`, `flake8-noqa` |
|
|
227
279
|
| шаг конвейера, который не может провалиться | наш `ci-actually-fails`; у `checkwash` есть смежный `CI_WORKFLOW_TOUCHED` |
|
|
228
280
|
|
|
281
|
+
## Три сверки под три предложенные записи — 2026-09-09
|
|
282
|
+
|
|
283
|
+
Второй пользователь предложил три записи каталога (issue #46). Прежде чем писать код, проверено
|
|
284
|
+
снаружи, есть ли готовое. Ответ вышел **разный по всем трём** — записано здесь, чтобы поиск не
|
|
285
|
+
повторяли.
|
|
286
|
+
|
|
287
|
+
### Миграция, не попавшая в журнал инструмента
|
|
288
|
+
|
|
289
|
+
**Похоже, готовое есть, и запись остановлена до замера.**
|
|
290
|
+
|
|
291
|
+
| Инструмент | Что делает | Закрывает ли класс |
|
|
292
|
+
|---|---|---|
|
|
293
|
+
| `drizzle-kit check` | согласованность истории миграций: коллизии снимков, дубли `idx` в `_journal`, непоследовательные номера | **неизвестно** — про написанный руками `.sql` без записи в журнале в документации не сказано |
|
|
294
|
+
| `alembic check` | сравнивает МОДЕЛИ с миграциями: «есть ли изменения без ревизии» | нет, это другой вопрос |
|
|
295
|
+
|
|
296
|
+
Замер, который решает: положить руками `migrations/9999_test.sql`, в `_journal.json` не вписывать,
|
|
297
|
+
запустить `npx drizzle-kit check`. Красный — записи не надо вовсе, надо строка «поставь эту
|
|
298
|
+
команду в конвейер». Зелёный — запись законна и сразу с доказательством.
|
|
299
|
+
|
|
300
|
+
**Это тот случай, ради которого правило и написано:** одна команда решает, будет папка или строка.
|
|
301
|
+
|
|
302
|
+
### Команда сборки, заглушившая свой отказ
|
|
303
|
+
|
|
304
|
+
**Готового нет, и это проверено — причём показательно.**
|
|
305
|
+
|
|
306
|
+
Ближайшее — `shellcheck SC2312`, и оно про другое: маскировку кода возврата в подстановке
|
|
307
|
+
команды. Мало того, что не ловит `>/dev/null 2>&1` у сборки, — в собственном тексте правила
|
|
308
|
+
`|| true` предложен **как способ подавления**:
|
|
309
|
+
|
|
310
|
+
> Consider invoking this command separately to avoid masking its return value (or use `|| true`
|
|
311
|
+
> to ignore).
|
|
312
|
+
|
|
313
|
+
Источник: <https://www.shellcheck.net/wiki/SC2312>
|
|
314
|
+
|
|
315
|
+
То есть общепринятый линтер оболочки считает `|| true` намеренным приёмом — и он прав в своей
|
|
316
|
+
области. Наша запись про **место**: команда, выносящая вердикт, не имеет права молчать о своём
|
|
317
|
+
отказе. `Makefile`, `package.json`, скрипты развёртывания — там `|| true` частый гость, а сторожа
|
|
318
|
+
нет ни одного.
|
|
319
|
+
|
|
320
|
+
### Починка без арбитра
|
|
321
|
+
|
|
322
|
+
**Готовое есть, и его обязательно называть.** `danger-js` делает этот класс типовым правилом
|
|
323
|
+
(«app changes without tests»), есть и плагины. Источник: <https://danger.systems/js/>
|
|
324
|
+
|
|
325
|
+
Отличия настоящие, но их всего два: `danger-js` работает на уровне PR и требует GitHub плюс
|
|
326
|
+
`Dangerfile`. Запись каталога смотрела бы **коммит** и не была бы привязана к площадке —
|
|
327
|
+
прецедент есть, `commit-explains-itself` читает историю, а не дерево файлов.
|
|
328
|
+
|
|
329
|
+
Это ровно тот случай, когда своя запись законна, но раздел «готовый аналог» обязан назвать
|
|
330
|
+
чужой инструмент и сказать, **почему не он**.
|
|
331
|
+
|
|
229
332
|
## Если готового нет
|
|
230
333
|
|
|
231
334
|
Тогда свой гейт — и в его `README.md` пишется, **что именно проверено**: какой инструмент
|