opencode-orchestrator-uni 0.3.1 → 0.4.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 CHANGED
@@ -8,13 +8,18 @@ ships the **orchestrator agent kit**:
8
8
  - `orchestrator` — the root orchestrator (primary agent) with the audit loop as a
9
9
  built-in mode;
10
10
  - read-only audit subagents — `factcheck`, `empiric`, `invariant`,
11
- `arbiter`, `meta`, `redteam`;
11
+ `arbiter`, `meta`, `redteam`, `context-lint`;
12
12
  - `fix-runner` — the only writing subagent (applies the "to close" list);
13
13
  - the kit's process documents, exposed as the **`audit-kit` reference**
14
14
  (`call-mechanics.md`, `process-ready-loop.md`, `root-runbook.md`,
15
- `instruction-other-session.md`);
16
- - three deterministic, read-only tools — `orch_uni_validate_report`, `orch_uni_snapshot`,
17
- `orch_uni_sessions` (see [Tools](#tools)).
15
+ `instruction-other-session.md`, `context-efficiency.md`);
16
+ - four deterministic, read-only tools — `orch_uni_validate_report`, `orch_uni_context_lint`,
17
+ `orch_uni_snapshot`, `orch_uni_sessions` (see [Tools](#tools));
18
+ - two slash commands — `/agents-md` and `/spec` (see [Commands](#commands)).
19
+
20
+ Read-only audit agents are enforced by `edit: deny` plus the prompt ban; their shell
21
+ permission stays allowed so they can run verification commands (an accepted risk, no
22
+ permission is relaxed).
18
23
 
19
24
  The package is loaded directly from TypeScript: `exports` points at
20
25
  [`index.ts`](./index.ts). There is **no build step and no `dist/`** — OpenCode's
@@ -34,31 +39,47 @@ On setup (`ctx.agent.transform` / `ctx.reference.transform`):
34
39
  | `arbiter` | `subagent` | Read-only: resolves disputed findings only |
35
40
  | `meta` | `subagent` | Read-only: meta-audit of reports (pass/fail gate) |
36
41
  | `redteam` | `subagent` | Read-only: acceptance red team (release gates) |
42
+ | `context-lint` | `subagent` | Read-only: audits AGENTS.md/SPEC.md for token efficiency |
37
43
  | `fix-runner` | `subagent` | Writer: applies the fix list and proves closure |
38
44
 
39
45
  All agents ship **without a model**: models are deployment configuration (see
40
46
  [Models](#models)). Definitions live in [`agents/`](./agents) as plain Markdown agent
41
47
  files and are parsed at setup time — the files are the single source of truth.
42
48
 
49
+ "Read-only" here means `edit` is denied and the prompt forbids writes; `shell` stays
50
+ allowed so an auditor can run the verification commands it needs (accepted risk
51
+ I-M15). The audit loop treats that as a contract, not as a sandbox.
52
+
43
53
  The `audit-kit` reference points at this package's per-locale `docs/<locale>/`
44
54
  directory (see [Locale](#locale)). OpenCode lists it in session context as an
45
55
  additional local directory, so the orchestrator (and any other agent) can read
46
56
  the process documents directly, for example `<reference path>/call-mechanics.md`.
47
57
 
48
- The plugin also registers three deterministic, **read-only** tools in the `orch_uni`
49
- namespace — see [Tools](#tools).
58
+ The plugin also registers four deterministic, **read-only** tools in the `orch_uni`
59
+ namespace and two slash commands — see [Tools](#tools) and [Commands](#commands).
60
+
61
+ ## Commands
62
+
63
+ | Command | What it does |
64
+ | --- | --- |
65
+ | `/agents-md` | Injects the AGENTS.md audit/draft workflow: `context-efficiency.md` template, `orch_uni_context_lint`, `context-lint`, approval before writing. |
66
+ | `/spec` | Injects the SPEC.md workflow: brief, clarifying questions, EARS/AC/traceability, `orch_uni_context_lint`, `context-lint`, approval before writing. |
67
+
68
+ A command is a prompt, not a writer: its handler injects a workflow prompt into the
69
+ current session. The orchestrator then follows the usual evidence and approval rules.
50
70
 
51
71
  ## Tools
52
72
 
53
73
  | Effective name | Read-only | What it does |
54
74
  | ------------------------ | --------- | ----------------------------------------------------------------------------- |
55
75
  | `orch_uni_validate_report` | yes | Extract the SGR JSON block of a report, resolve its schema, validate it |
76
+ | `orch_uni_context_lint` | yes | Deterministic audit of AGENTS.md/SPEC.md: budget, vague phrases, links, sections |
56
77
  | `orch_uni_snapshot` | yes | Deterministic revision of a directory tree (per-file sha256 + aggregate hash) |
57
78
  | `orch_uni_sessions` | yes | Child sessions of a session: agent, model, cost, tokens, time |
58
79
 
59
80
  Every tool answers with a JSON text body. Failures are **typed codes** inside the body
60
81
  (`E_INPUT`, `E_NO_JSON`, …) instead of thrown tool errors, so an agent can branch on the
61
- code without parsing prose. None of the three writes to the workspace, the session store
82
+ code without parsing prose. None of the four writes to the workspace, the session store
62
83
  or the configuration.
63
84
 
64
85
  ### `orch_uni_validate_report`
@@ -98,12 +119,90 @@ invariant that is `violated` without a counterexample, an uncovered mandatory
98
119
  `lines_checked` line, `meta`'s `verdict` diverging from its `gate`, and
99
120
  `redteam`'s `closing_list`/`verdict` invariants.
100
121
 
101
- The seven schemas ship as `schemas/*.json` and are derived **strictly** from the SGR
122
+ The schemas ship as `schemas/*.json` and are derived **strictly** from the SGR
102
123
  sections of `agents/*.md`, which stay the source of truth: the test suite parses every
103
124
  agent's SGR template and fails when a prompt field or enum value is not accepted by its
104
- schema. Schemas set `additionalProperties` permissively — agents may add fields of their
125
+ schema. `context-lint-failure/v1` is the typed failure envelope of
126
+ `orch_uni_context_lint` — it has no agent template and is never a report. Schemas set
127
+ `additionalProperties` permissively — agents may add fields of their
105
128
  own (`verdict_label`, `check`, …).
106
129
 
130
+ ### `orch_uni_context_lint`
131
+
132
+ ```jsonc
133
+ { "path": "AGENTS.md" } // file or directory, relative to the location
134
+ { "path": ".", "max_lines": 150, "max_tokens": 2000 }
135
+ { "path": ".", "max_words": 2000 } // SPEC word budget; default 1500 (target), ceiling 2000
136
+ { "path": ".", "max_file_bytes": 500000, "max_files": 100, "max_findings": 50, "max_total_findings": 500 }
137
+ ```
138
+
139
+ Deterministic, read-only audit of `AGENTS.md`, `SPEC.md` and `CLAUDE.md`. It returns
140
+ `{ schema: "context-lint/v1", ok: true, verdict, closing_list, files, summary, truncated? }`;
141
+ each finding carries `id`, `severity`, `kind`, `evidence`, `detail` and `fix`. Checks:
142
+ line/token/word budget, distinct vague phrases, duplicate lines, broken relative links,
143
+ placeholders, dates/versions in the first three lines, required sections and AC test
144
+ columns. Links and explicit targets are confined by their **real** path: a symlink or
145
+ junction that resolves outside the root is skipped, and such a target is refused
146
+ (`E_OUT_OF_ROOT`). Code fences, inline code and HTML comments are masked, so a sample is
147
+ never a rule: structural checks (commands, boundaries, verification) read the full mask,
148
+ while requirements, AC ids and non-goals read the fence mask. Link targets are
149
+ streamed from the line scanner one at a time (no candidate array), so memory does
150
+ not grow with the number of links; checks are capped per file at 50 000
151
+ candidates, the signal is checked per line and every 100 candidates, and the
152
+ link caches keep at most 5 000 entries, so an abort wins; 2001 links are checked
153
+ normally, 50 000 valid links still pass, and the 50 001st candidate makes the list
154
+ incomplete (`truncated: true` plus a MAJOR `link candidates truncated` marker in
155
+ `closing_list`), so a capped run can never pass. Broken
156
+ links have no separate per-file cap: the finding caps bound the output and report the
157
+ overflow. A line is scanned however long it is: the link scanner and the placeholder regex
158
+ are linear, so a 4100-character line is checked like any other and a broken link or
159
+ placeholder on it is the real finding, not a marker. Duplicate lines have no inner cap.
160
+ UNC/network targets are never probed. Measured (bun 1.4.2, Windows, fresh
161
+ process): 50 001 broken links with `max_findings: 2` → ~1.4 s and ~67 MB peak
162
+ RSS; 50k plain lines → ~0.14 s / ~65 MB; a 2 MB single line with links →
163
+ ~3.1 s / ~116 MB (~41 MB without links). Masking reuses a line as-is when it
164
+ has no backtick and no `<pre>`/`<code>`/`<!--`, so it never copies a line
165
+ character by character, and a 2 MB single line stays capped at 50 000
166
+ candidates instead of materializing every link.
167
+ Limits: ≤ 2 MB per file, ≤ 500 files per scan. `max_findings` (per file) is N per
168
+ severity: up to N MAJOR and N MINOR/INFO are kept, and any excess is replaced by one
169
+ marker (MAJOR when a MAJOR was dropped, otherwise INFO); a MAJOR marker stays in
170
+ `closing_list`. `max_total_findings` (global, default 1000) keeps MAJOR
171
+ findings first; when MAJOR overflow, `max_total` findings plus one MAJOR `truncated`
172
+ marker are kept. A capped list sets `truncated: true` instead of hiding findings.
173
+ Markers are additional to `max_findings` and do not consume its budget: a capped
174
+ link-candidate list and a capped findings list report one marker each in the same run, so
175
+ `max_findings: 2` over 20 001 broken links yields 2 kept findings plus 2 markers. Cap
176
+ markers point at `file:1` in `evidence`.
177
+ Non-goals are counted as top-level items: a wrapped paragraph is one item, inline
178
+ `;`/`,`/`and`/`и` split only at the top level (not inside `(…)`, `[…]`, backticks of any
179
+ width or `<code>`), and a bullet at 0–4 spaces under the label is an item — fenced,
180
+ `<pre>` and deeper-indented code is not.
181
+ Placeholders are `<...>` (three or more dots) and `TODO`/`TBD`/`FIXME`; `<DoD>` and
182
+ `<name>` are markup.
183
+ `max_lines` is the single 200-line root budget the tool applies: the 60/200/100
184
+ per-level figures in [`docs/`](./docs) are authoring guidance, not separate tool limits.
185
+ `max_words` defaults to the 1500-word SPEC target; pass `max_words: 2000` to enforce the
186
+ documented ceiling instead.
187
+ Typed failures: `E_INPUT`, `E_NOT_FOUND`, `E_NO_FILES`, `E_IO`, `E_ABORTED`,
188
+ `E_LIMIT_FILE`, `E_LIMIT_FILES`, `E_OUT_OF_ROOT`.
189
+ A failure is a typed payload `{schema:"context-lint-failure/v1", ok:false, code, message, path?, bytes?, files?, max?}`
190
+ that validates only against `context-lint-failure/v1`; a report is
191
+ `{schema:"context-lint/v1", ok, verdict, closing_list, files, summary, truncated?}` and every file carries `lines`,
192
+ `words`, `chars` and `tokens_est` (tokens are estimated as Cyrillic/3 + the rest/4). A directory
193
+ target is scanned to depth 3, and `max_files` refuses early: the walk stops at the first file above
194
+ the limit. Nothing is dropped silently: a directory below the depth limit, a link or junction that
195
+ resolves outside the workspace root, and an unclosed fence, `<pre>` or HTML comment are INFO
196
+ findings, so a `pass` never hides an unchecked region. An unclosed `<code>` is a
197
+ line-local mask: it hides the rest of its line and is not reported (only fence,
198
+ `<pre>` and HTML comments span lines and get an INFO marker). An abort is observed
199
+ between files, every 2048 lines of a line-oriented check and at each gate, so the
200
+ worst-case latency is one mask pass over a file capped by `max_file_bytes` (tens of
201
+ milliseconds per 2 MB), not the whole scan. Commands count only inside code, a Task table
202
+ or a Commands section, an HTML comment such as `<!-- npm install -->` is not a command, and `make`
203
+ needs a target, so prose such as "Make sure …" is not a command. A scan started at the root also
204
+ picks up fixture trees such as `eval/`; pass an explicit path for the canonical files.
205
+
107
206
  ### `orch_uni_snapshot`
108
207
 
109
208
  ```jsonc
@@ -309,7 +408,7 @@ npm run lint:fix # biome check --write . (applies safe fixes)
309
408
 
310
409
  The `check:locales` and `verify:kit` scripts need a git checkout of the kit — the npm package ships no `tools/` directory, so in an installed package they are unavailable (`stand: unavailable` plus your own reproducible checks).
311
410
 
312
- `npm test` scans only `./test/` — the shipped suite (93 tests in 8 files, up from
411
+ `npm test` scans only `./test/` — the shipped suite (289 tests in 9 files, up from
313
412
  72 in 5 before the identifier guards). A bare `bun test` from the repository root is red by
314
413
  design: the positional argument of `bun test` is a path substring filter, so the
315
414
  bare command also picks up the intentionally failing fixtures under `eval/cases/`
package/README.ru.md CHANGED
@@ -8,13 +8,18 @@
8
8
  - `orchestrator` — root-оркестратор (основной агент) со встроенным режимом
9
9
  аудиторского цикла;
10
10
  - read-only субагенты аудита — `factcheck`, `empiric`, `invariant`,
11
- `arbiter`, `meta`, `redteam`;
11
+ `arbiter`, `meta`, `redteam`, `context-lint`;
12
12
  - `fix-runner` — единственный пишущий субагент (применяет список «к закрытию»);
13
13
  - процессные документы комплекта, доступные как **reference `audit-kit`**
14
14
  (`call-mechanics.md`, `process-ready-loop.md`, `root-runbook.md`,
15
- `instruction-other-session.md`);
16
- - три детерминированных read-only инструмента — `orch_uni_validate_report`,
17
- `orch_uni_snapshot`, `orch_uni_sessions` (см. [Инструменты](#инструменты)).
15
+ `instruction-other-session.md`, `context-efficiency.md`);
16
+ - четыре детерминированных read-only инструмента — `orch_uni_validate_report`,
17
+ `orch_uni_context_lint`, `orch_uni_snapshot`, `orch_uni_sessions`
18
+ (см. [Инструменты](#инструменты));
19
+ - две слэш-команды — `/agents-md` и `/spec` (см. [Команды](#команды)).
20
+
21
+ Read-only аудиторы держатся на `edit: deny` плюс запрете в промпте; shell-разрешение
22
+ остаётся, чтобы запускать проверки (принятый риск, ни одно разрешение не ослаблено).
18
23
 
19
24
  Пакет загружается напрямую из TypeScript: `exports` указывает на
20
25
  [`index.ts`](./index.ts). **Шага сборки и каталога `dist/` нет** — Bun-овый
@@ -34,6 +39,7 @@
34
39
  | `arbiter` | `subagent` | Read-only: разбирает только спорные находки |
35
40
  | `meta` | `subagent` | Read-only: мета-аудит отчётов (гейт pass/fail) |
36
41
  | `redteam` | `subagent` | Read-only: приёмочный ред-тим (релизные ворота) |
42
+ | `context-lint` | `subagent` | Read-only: аудит AGENTS.md/SPEC.md на token-эффективность |
37
43
  | `fix-runner` | `subagent` | Пишущий: применяет список правок и доказывает закрытие |
38
44
 
39
45
  Все агенты поставляются **без модели**: модели — это конфигурация развёртывания
@@ -41,26 +47,43 @@
41
47
  Markdown-файлы агентов и парсятся при setup — файлы являются единственным
42
48
  источником истины.
43
49
 
50
+ «Read-only» здесь означает: `edit` запрещён и промпт запрещает запись; `shell`
51
+ остаётся разрешён, чтобы аудитор мог выполнить нужные проверки (принятый риск
52
+ I-M15). Аудиторский цикл считает это контрактом, а не песочницей.
53
+
44
54
  Reference `audit-kit` указывает на per-locale каталог `docs/<locale>/` пакета
45
55
  (см. [Локаль](#локаль)). OpenCode перечисляет его в контексте сессии как
46
56
  дополнительный локальный каталог, поэтому оркестратор (и любой другой агент)
47
57
  может читать процессные документы напрямую, например
48
58
  `<reference path>/call-mechanics.md`.
49
59
 
50
- Плагин также регистрирует три детерминированных **read-only** инструмента в
51
- пространстве имён `orch_uni` — см. [Инструменты](#инструменты).
60
+ Плагин также регистрирует четыре детерминированных **read-only** инструмента в
61
+ пространстве имён `orch_uni` и две слэш-команды — см. [Инструменты](#инструменты)
62
+ и [Команды](#команды).
63
+
64
+ ## Команды
65
+
66
+ | Команда | Что делает |
67
+ | --- | --- |
68
+ | `/agents-md` | Вставляет workflow аудита/черновика AGENTS.md: шаблон `context-efficiency.md`, `orch_uni_context_lint`, `context-lint`, подтверждение перед записью. |
69
+ | `/spec` | Вставляет workflow SPEC.md: бриф, уточняющие вопросы, EARS/AC/трассировка, `orch_uni_context_lint`, `context-lint`, подтверждение перед записью. |
70
+
71
+ Команда — это промпт, а не писатель: обработчик вставляет workflow-промпт в
72
+ текущую сессию. Дальше оркестратор работает по обычным правилам evidence и
73
+ подтверждения.
52
74
 
53
75
  ## Инструменты
54
76
 
55
77
  | Имя | Read-only | Что делает |
56
78
  | -------------------------- | --------- | ----------------------------------------------------------------------------- |
57
79
  | `orch_uni_validate_report` | да | Достаёт SGR JSON-блок отчёта, разрешает его схему, валидирует |
80
+ | `orch_uni_context_lint` | да | Детерминированный аудит AGENTS.md/SPEC.md: бюджет, vague, ссылки, секции |
58
81
  | `orch_uni_snapshot` | да | Детерминированная ревизия дерева каталогов (sha256 на файл + агрегатный хэш) |
59
82
  | `orch_uni_sessions` | да | Дочерние сессии сессии: агент, модель, стоимость, токены, время |
60
83
 
61
84
  Каждый инструмент отвечает JSON-текстом. Ошибки — **типизированные коды** внутри
62
85
  тела (`E_INPUT`, `E_NO_JSON`, …), а не исключения, чтобы агент мог ветвиться по
63
- коду, не разбирая прозу. Ни один из трёх ничего не пишет в воркспейс, хранилище
86
+ коду, не разбирая прозу. Ни один из четырёх ничего не пишет в воркспейс, хранилище
64
87
  сессий или конфигурацию.
65
88
 
66
89
  ### `orch_uni_validate_report`
@@ -99,12 +122,87 @@ claim'а `empiric` с `method` = `run|measure|compare_base`, элементы `s
99
122
  непокрытая обязательная строка `lines_checked`, расхождение `verdict` и `gate` у
100
123
  `meta`, инварианты `closing_list`/`verdict` у `redteam`.
101
124
 
102
- Семь схем лежат в `schemas/*.json` и выведены **строго** из SGR-секций
125
+ Схемы лежат в `schemas/*.json` и выведены **строго** из SGR-секций
103
126
  `agents/*.md`, которые остаются источником истины: тестовый набор парсит
104
127
  SGR-шаблон каждого агента и падает, когда поле промпта или значение enum не
105
- принимается его схемой. Схемы разрешают `additionalProperties` — агенты могут
128
+ принимается его схемой. `context-lint-failure/v1` — типизированный конверт ошибки
129
+ `orch_uni_context_lint`: у него нет шаблона агента, и отчётом он не является. Схемы
130
+ разрешают `additionalProperties` — агенты могут
106
131
  добавлять свои поля (`verdict_label`, `check`, …).
107
132
 
133
+ ### `orch_uni_context_lint`
134
+
135
+ ```jsonc
136
+ { "path": "AGENTS.md" } // файл или каталог, относительно локации
137
+ { "path": ".", "max_lines": 150, "max_tokens": 2000 }
138
+ { "path": ".", "max_words": 2000 } // бюджет слов SPEC; по умолчанию 1500 (цель), потолок 2000
139
+ { "path": ".", "max_file_bytes": 500000, "max_files": 100, "max_findings": 50, "max_total_findings": 500 }
140
+ ```
141
+
142
+ Детерминированный read-only аудит `AGENTS.md`, `SPEC.md` и `CLAUDE.md`. Возвращает
143
+ `{ schema: "context-lint/v1", ok: true, verdict, closing_list, files, summary, truncated? }`;
144
+ каждая находка несёт `id`, `severity`, `kind`, `evidence`, `detail` и `fix`. Проверки:
145
+ бюджет строк/токенов/слов, различные vague-фразы, дубли строк, битые относительные ссылки,
146
+ плейсхолдеры, даты/версии в первых трёх строках, обязательные секции и колонка Test
147
+ у AC. Ссылки и явные цели ограничены **реальным** путём: symlink/junction, ведущий за
148
+ пределы корня, пропускается, а такая цель отклоняется (`E_OUT_OF_ROOT`). Код-фенсы,
149
+ inline-код и HTML-комментарии маскируются: пример не считается правилом — структурные
150
+ проверки (команды, границы, проверка) читают полную маску, а требования, AC-id и
151
+ non-goals — маску фенсов. Цели ссылок передаются из построчного сканера по одной
152
+ (массива кандидатов нет), поэтому память не растёт с числом ссылок; проверки ограничены
153
+ на файл 50 000 кандидатами, сигнал проверяется на каждой строке и каждые 100 кандидатов,
154
+ а кэши ссылок держат не более 5 000 записей, поэтому abort срабатывает; 2001 ссылка
155
+ проверяется обычным образом, 50 000 валидных ссылок дают pass, а 50 001-й кандидат делает
156
+ список неполным (`truncated: true` плюс MAJOR-маркер `link candidates truncated` в
157
+ `closing_list`), он не может дать pass.
158
+ Отдельного потолка на
159
+ битые ссылки нет: вывод ограничивают общие лимиты находок, а переполнение помечается.
160
+ Строка сканируется любой длины: сканер ссылок и регулярное выражение плейсхолдеров линейны,
161
+ поэтому 4100-символьная строка проверяется как любая другая, а битая ссылка или
162
+ плейсхолдер на ней — настоящая находка, а не маркер. Внутреннего потолка дублей нет. Цели
163
+ UNC/сетевые пути никогда не пробуются. Замер (bun 1.4.2, Windows, свежий процесс):
164
+ 50 001 битая ссылка с `max_findings: 2` → ~1,4 с и ~67 МБ пикового RSS; 50 тыс.
165
+ обычных строк → ~0,14 с / ~65 МБ; одна строка 2 МБ со ссылками → ~3,1 с / ~116 МБ
166
+ (~41 МБ без ссылок). Маскирование переиспользует строку как есть, если в ней нет
167
+ backtick и `<pre>`/`<code>`/`<!--`, поэтому не копирует строку посимвольно, а строка
168
+ в 2 МБ остаётся ограниченной 50 000 кандидатами, а не материализует все ссылки.
169
+ Лимиты: ≤ 2 МБ на файл, ≤ 500 файлов за прогон. `max_findings` (на файл) — это N на
170
+ severity: сохраняются до N MAJOR и N MINOR/INFO, излишек заменяется одним маркером
171
+ (MAJOR, если выпал MAJOR, иначе INFO); MAJOR-маркер остаётся в `closing_list`.
172
+ `max_total_findings` (глобально, по умолчанию 1000)
173
+ сохраняет сначала MAJOR; при переполнении MAJOR остаются `max_total` находок плюс один
174
+ MAJOR-маркер `truncated`. Усечённый список помечается `truncated: true`, а не скрывается.
175
+ Маркеры дополнительны к `max_findings` и не расходуют его бюджет: маркер усечённых
176
+ кандидатов-ссылок и маркер усечённых находок дают по маркеру в одном прогоне, поэтому
177
+ `max_findings: 2` на 20 001 битой ссылке даёт 2 сохранённые находки плюс 2 маркера. Маркеры
178
+ указывают на `file:1` в `evidence`.
179
+ Non-goals считаются как элементы верхнего уровня: перенесённый абзац — один элемент,
180
+ inline `;`/`,`/`and`/`и` делят только верхний уровень (не внутри `(…)`, `[…]`, бэктиков
181
+ любой длины или `<code>`), а bullet с отступом 0–4 пробела под лейблом — элемент; фенсы,
182
+ `<pre>` и код с большим отступом — нет.
183
+ Плейсхолдеры — `<...>` (три и более точки) и `TODO`/`TBD`/`FIXME`; `<DoD>` и `<name>` —
184
+ разметка.
185
+ `max_lines` — единственный бюджет корня (200 строк), который применяет инструмент;
186
+ цифры 60/200/100 по уровням в [`docs/`](./docs) — ориентир для авторов, а не отдельные
187
+ лимиты инструмента. `max_words` по умолчанию равен цели 1500 слов SPEC; передайте
188
+ `max_words: 2000`, чтобы применять документированный потолок. Типизированные ошибки: `E_INPUT`, `E_NOT_FOUND`, `E_NO_FILES`,
189
+ `E_IO`, `E_ABORTED`, `E_LIMIT_FILE`, `E_LIMIT_FILES`, `E_OUT_OF_ROOT`.
190
+ Ошибка — типизированный payload `{schema:"context-lint-failure/v1", ok:false, code, message, path?, bytes?, files?, max?}`,
191
+ который валидируется только по `context-lint-failure/v1`; отчёт —
192
+ `{schema:"context-lint/v1", ok, verdict, closing_list, files, summary, truncated?}`, и каждый файл несёт `lines`,
193
+ `words`, `chars` и `tokens_est` (токены оцениваются как кириллица/3 + прочее/4). Каталог
194
+ сканируется до глубины 3, а `max_files` отказывает рано: обход останавливается на первом файле
195
+ выше лимита. Ничего не пропадает молча: каталог ниже лимита глубины, ссылка или junction вне
196
+ корня workspace и незакрытые fence, `<pre>` или HTML-комментарий дают INFO-находки, поэтому `pass`
197
+ не скрывает непроверенную область. Незакрытый `<code>` — строчная маска: он скрывает
198
+ остаток своей строки и не репортится (INFO дают только fence, `<pre>` и HTML-комментарий,
199
+ которые тянутся через строки). Отмена наблюдается между файлами, каждые 2048 строк
200
+ построчной проверки и в каждом гейте, поэтому худшая латентность — один проход маски по
201
+ файлу под `max_file_bytes` (десятки мс на 2 МБ), а не весь скан. Команды считаются только в коде, таблице задач или секции
202
+ Commands, HTML-комментарий вроде `<!-- npm install -->` командой не является, а `make` требует
203
+ цели, поэтому проза «Make sure …» — не команда. Скан от корня подхватывает и фикстуры вроде
204
+ `eval/`; передайте явный путь, если нужны только канонические файлы.
205
+
108
206
  ### `orch_uni_snapshot`
109
207
 
110
208
  ```jsonc
@@ -316,7 +414,7 @@ npm run lint:fix # biome check --write . (применяет безопас
316
414
 
317
415
  Команды `check:locales` и `verify:kit` требуют git-чекаута комплекта — в npm-пакете каталог `tools/` не поставляется, поэтому в установленном пакете они недоступны (`stand: unavailable` и собственные воспроизводимые проверки).
318
416
 
319
- `npm test` сканирует только `./test/` — поставляемый набор (93 теста в 8 файлах;
417
+ `npm test` сканирует только `./test/` — поставляемый набор (289 тестов в 9 файлах;
320
418
  до стражей идентификаторов было 72 в 5). Голый `bun test` из корня репозитория
321
419
  красный по замыслу: позиционный аргумент `bun test` — это фильтр-подстрока пути,
322
420
  поэтому голая команда подхватывает и специально падающие фикстуры в
@@ -0,0 +1,90 @@
1
+ ---
2
+ description: "Read-only auditor of AGENTS.md/SPEC.md/CLAUDE.md: token budget, testability, duplicates, links, SPEC completeness. Report — SGR + closing_list."
3
+ mode: subagent
4
+ permissions:
5
+ - action: edit
6
+ resource: "*"
7
+ effect: deny
8
+ - action: shell
9
+ resource: "*"
10
+ effect: allow
11
+ ---
12
+
13
+ You are the read-only auditor of instruction files for AI agents: `AGENTS.md`, `SPEC.md`, `CLAUDE.md`. You check token efficiency and quality; you change nothing.
14
+
15
+ INPUT: the path to the repository or files is in the call prompt; when absent, use the current directory. Find the target files in the root and up to 3 directory levels below it, excluding `node_modules`, `.git`, `.ae`, `dist`, `build`, `target`, `vendor`. A scan started at the root also picks up fixture trees such as `eval/`; pass an explicit path when only the canonical files matter.
16
+
17
+ MEASURE: for each file, count lines, words, characters, an estimated token count (`Cyrillic/3 + the rest/4`), and the number of headings, tables and lists. Use read-only commands only (`find`, `wc`, `grep`, `test -e`); do not run builds, tests, migrations or deploys.
18
+
19
+ When the `orch_uni_context_lint` tool is available, run it on the target path first; use its findings as the deterministic base, then add the semantic checks (conflicts, testability, SPEC intent).
20
+
21
+ Tool codes: `E_NO_FILES` → verdict=fail with one `files` entry with `path: "-"`, `kind: "other"` and finding `CTX-000`; `E_LIMIT_FILE` / `E_LIMIT_FILES` / `E_OUT_OF_ROOT` → verdict=fail with `CTX-000` (kind=unverified_command or other), the code and path from the error in evidence. A failure is not a report: it declares `schema: "context-lint-failure/v1"` and validates only against that schema (`{ok: false, code, message, path?, bytes?, files?, max?}`). `truncated: true` means the finding list was capped: MINOR/INFO may be missing, and when MAJOR overflow a MAJOR `truncated` marker stays in `closing_list` — say so in `summary`.
22
+
23
+ Nothing is skipped silently: a link target that resolves outside the workspace root, a directory below depth 3, a junction skipped by the walk, and an unclosed fence, `<pre>` or HTML comment are reported as INFO findings (`was not checked`, `was skipped`, `depth limit 3`, `the rest of the file is masked`), so a pass never hides an unverified region. An unclosed `<code>` is the exception: it masks the rest of its own line only and is not reported; an abort is observed between files, every 2048 lines of a line-oriented check and at each gate.
24
+
25
+ Caps → `truncated`: link candidates → MAJOR marker; per-file/global findings → one marker (MAJOR if a MAJOR was dropped, else INFO); duplicate lines have no inner cap. Every line is scanned in full: there is no long-line cap or marker. `max_files` refuses early — the walk stops at the first file above the limit instead of expanding the whole tree. Every cap sets `truncated: true` and is named in `summary`.
26
+
27
+ AGENTS.md — check:
28
+ 1. Budget: >200 lines or >2500 tokens — MAJOR; 150–200 lines — MINOR.
29
+ 2. Commands: install/build/test/one test/lint/run are present, with flags and a working directory; a command counts only inside code, a Task table or a Commands section, an HTML comment is not a command (`<!-- npm install -->` does not count), and `make` needs a target (`make build`), so prose such as "Make sure …" is not a command; restating the obvious (`npm test`) — MINOR.
30
+ 3. Boundaries: generated/vendor/prod/secrets/migrations — otherwise MINOR.
31
+ 4. Precedence and scope — otherwise MINOR.
32
+ 5. Vague phrases: clean, best practices, robust, "carefully", "properly", "optimally" — MINOR; three or more distinct terms — MAJOR (the tool counts distinct terms).
33
+ 6. Duplicate lines of ≥40 characters; restating README/linter — MINOR.
34
+ 7. Relative links and paths exist — otherwise MAJOR.
35
+ 8. Placeholders `<...>`, `TODO`, `TBD`, `FIXME` — MAJOR.
36
+ 9. A date/version in the first three lines (breaks the prefix cache) — MINOR.
37
+ 10. Every line is testable: a command, a boundary prohibition, an invariant or a link — otherwise MINOR.
38
+
39
+ SPEC.md — check:
40
+ 1. Non-goals: 3–7 items — otherwise MAJOR.
41
+ 2. Requirements R1..Rn: one observable behavior per requirement; "and" chains — MINOR.
42
+ 3. Every R has an AC, every AC has a Test — otherwise MAJOR.
43
+ 4. AC are measurable (a number or an observable result); "fast/convenient/reliable" without a metric — MAJOR.
44
+ 5. Invariants and edge cases — otherwise MINOR.
45
+ 6. Traceability R→AC→task→test — otherwise MINOR.
46
+ 7. At most three open questions, each with an owner and a date; `TODO`/`TBD` outside the block — MAJOR.
47
+ 8. Frontmatter: status/owner/version — otherwise MINOR.
48
+ 9. No HOW (stack, files, classes) in requirements — otherwise MINOR.
49
+ 10. Contracts are links, not copies — otherwise MINOR.
50
+
51
+ CROSS-CUTTING CHECKS:
52
+ - An "always/never" or precedence conflict between files — MAJOR.
53
+ - Duplicates between AGENTS.md and SPEC.md — MINOR.
54
+ - No target files — verdict=fail, one `files` entry with `path: "-"`, `kind: "other"` and finding `CTX-000`, kind=missing_section.
55
+ - Every finding: id `CTX-NNN`, severity, kind, evidence `file:line`, detail, fix.
56
+ - verdict=fail on any MAJOR; `closing_list` = the ids of all MAJOR findings. verdict=pass only when there is no MAJOR.
57
+
58
+ FORMAT (SGR): a summary (up to 10 lines) + json:
59
+ {
60
+ "schema": "context-lint/v1",
61
+ "ok": true,
62
+ "verdict": "pass | fail",
63
+ "closing_list": [],
64
+ "truncated": false,
65
+ "files": [
66
+ {
67
+ "path": "AGENTS.md",
68
+ "kind": "agents | spec | claude | other",
69
+ "lines": 0,
70
+ "words": 0,
71
+ "chars": 0,
72
+ "tokens_est": 0,
73
+ "findings": [
74
+ {
75
+ "id": "CTX-001",
76
+ "severity": "MAJOR | MINOR | INFO",
77
+ "kind": "budget | vague | duplicate | broken_link | missing_section | conflict | unverified_command | other",
78
+ "evidence": "AGENTS.md:42",
79
+ "detail": "...",
80
+ "fix": "..."
81
+ }
82
+ ]
83
+ }
84
+ ],
85
+ "summary": "..."
86
+ }
87
+
88
+ Before submitting, validate the JSON as text through `orch_uni_validate_report` and make it `valid=true`; return the report as text in the answer — do not create files.
89
+
90
+ LIMITS: read-only (edit deny + the prompt ban); shell is allowed for verification only; do not edit files; do not run builds/tests/migrations/deploys; the report is in English, without fluff. Placeholders are only `<...>` (three or more dots) and `TODO`/`TBD`/`FIXME`; `<DoD>` and `<name>` are not placeholders.
@@ -19,6 +19,7 @@ GENERAL CYCLE:
19
19
  4. Delegate to subagents:
20
20
  - research on code — `explore`; on topics and data — `general`;
21
21
  - verification of a change/plan/release — the audit loop (see the mode below);
22
+ - audit of instruction files (AGENTS.md, SPEC.md, CLAUDE.md) — `context-lint` (read-only, SGR + closing_list);
22
23
  - implementation — yourself (small) or `fix-runner` (fixes per the "to close" list), large tasks — `general`;
23
24
  - launch parallel tasks in one block (background) and do not poll — the notifications will arrive on their own.
24
25
  5. Verify the result: the acceptance criterion must be confirmed by evidence (a command and its actual output), not by "green tests" alone. Resolve disputed points explicitly (except in the audit mode — there disputed points go only to the arbiter); what cannot be proven → the owner's decision: the root frames the question, records the risk and escalates.
@@ -0,0 +1,90 @@
1
+ ---
2
+ description: "Read-only аудитор AGENTS.md/SPEC.md/CLAUDE.md: бюджет токенов, проверяемость, дубли, ссылки, полнота SPEC. Отчёт — SGR + closing_list."
3
+ mode: subagent
4
+ permissions:
5
+ - action: edit
6
+ resource: "*"
7
+ effect: deny
8
+ - action: shell
9
+ resource: "*"
10
+ effect: allow
11
+ ---
12
+
13
+ Ты — read-only аудитор файлов инструкций для AI-агентов: `AGENTS.md`, `SPEC.md`, `CLAUDE.md`. Проверяешь token-эффективность и качество; ничего не меняешь.
14
+
15
+ ВХОД: путь к репозиторию или файлам — в промпте вызова; если не задан — текущий каталог. Найди целевые файлы в корне и на 3 уровня каталогов ниже, исключая `node_modules`, `.git`, `.ae`, `dist`, `build`, `target`, `vendor`. Скан от корня подхватывает и фикстуры вроде `eval/`; передай явный путь, если нужны только канонические файлы.
16
+
17
+ ЗАМЕР: для каждого файла посчитай строки, слова, символы, оценку токенов (`кириллица/3 + прочее/4`), число заголовков, таблиц и списков. Используй только чтение (`find`, `wc`, `grep`, `test -e`); сборку, тесты, миграции и деплой не запускай.
18
+
19
+ Если доступен инструмент `orch_uni_context_lint`, сначала вызови его по целевому пути; используй его findings как детерминированную базу, затем добавь семантические проверки (конфликты, тестируемость, intent SPEC).
20
+
21
+ Коды инструмента: `E_NO_FILES` → verdict=fail, один элемент `files` с `path: "-"`, `kind: "other"` и finding `CTX-000`; `E_LIMIT_FILE` / `E_LIMIT_FILES` / `E_OUT_OF_ROOT` → verdict=fail с `CTX-000` (kind=unverified_command или other), в evidence — код и путь из ошибки. Ошибка — не отчёт: она объявляет `schema: "context-lint-failure/v1"` и валидируется только по этой схеме (`{ok: false, code, message, path?, bytes?, files?, max?}`). `truncated: true` означает, что список находок усечён: MINOR/INFO могут отсутствовать, а при переполнении MAJOR остаётся MAJOR-маркер `truncated` в `closing_list` — отметь это в `summary`.
22
+
23
+ Ничего не пропускается молча: цель ссылки вне корня workspace, каталог глубже лимита 3, пропущенный обходом junction и незакрытые fence, `<pre>` или HTML-комментарий отдаются INFO-находками (`was not checked`, `was skipped`, `depth limit 3`, `the rest of the file is masked`), поэтому pass не скрывает непроверенную область. Исключение — незакрытый `<code>`: он маскирует только остаток своей строки и не репортится; отмена наблюдается между файлами, каждые 2048 строк построчной проверки и в каждом гейте.
24
+
25
+ Потолки → `truncated`: кандидаты-ссылки → MAJOR-маркер; находки на файл/глобально → один маркер (MAJOR, если выпал MAJOR, иначе INFO); у дублей внутреннего потолка нет. Все строки сканируются целиком: потолка и маркера длинной строки нет. `max_files` отказывает рано — обход останавливается на первом файле выше лимита, а не разворачивает всё дерево. Любой потолок ставит `truncated: true` и называется в `summary`.
26
+
27
+ AGENTS.md — проверь:
28
+ 1. Бюджет: >200 строк или >2500 токенов — MAJOR; 150–200 строк — MINOR.
29
+ 2. Команды: есть install/build/test/one test/lint/run, с флагами и рабочей директорией; команда считается только в коде, таблице задач или секции Commands, HTML-комментарий командой не является (`<!-- npm install -->` не в счёт), а `make` требует цели (`make build`), поэтому проза «Make sure …» — не команда; пересказ очевидного (`npm test`) — MINOR.
30
+ 3. Границы: generated/vendor/prod/secrets/migrations — иначе MINOR.
31
+ 4. Приоритеты и область действия — иначе MINOR.
32
+ 5. Vague-фразы: clean, best practices, robust, «аккуратно», «правильно», «оптимально» — MINOR; три и более различных термина — MAJOR (инструмент считает различные термины).
33
+ 6. Дубли строк длиной ≥40 символов; пересказ README/линтера — MINOR.
34
+ 7. Относительные ссылки и пути существуют — иначе MAJOR.
35
+ 8. Плейсхолдеры `<...>`, `TODO`, `TBD`, `FIXME` — MAJOR.
36
+ 9. Дата/версия в первых трёх строках (ломает prefix cache) — MINOR.
37
+ 10. Каждая строка проверяема: команда, запрет с границей, инвариант или ссылка — иначе MINOR.
38
+
39
+ SPEC.md — проверь:
40
+ 1. Non-goals: 3–7 пунктов — иначе MAJOR.
41
+ 2. Требования R1..Rn: одно наблюдаемое поведение на требование; «and»-цепочки — MINOR.
42
+ 3. У каждого R есть AC, у каждого AC есть Test — иначе MAJOR.
43
+ 4. AC измеримы (число или наблюдаемый результат); «быстро/удобно/надёжно» без метрики — MAJOR.
44
+ 5. Инварианты и краевые случаи — иначе MINOR.
45
+ 6. Трассировка R→AC→task→test — иначе MINOR.
46
+ 7. Не более трёх открытых вопросов, у каждого owner и дата; `TODO`/`TBD` вне блока — MAJOR.
47
+ 8. Frontmatter: status/owner/version — иначе MINOR.
48
+ 9. Нет HOW (стек, файлы, классы) в требованиях — иначе MINOR.
49
+ 10. Контракты — ссылками, не копиями — иначе MINOR.
50
+
51
+ ОБЩИЕ ПРОВЕРКИ:
52
+ - Конфликт «always/never» или приоритетов между файлами — MAJOR.
53
+ - Дубли между AGENTS.md и SPEC.md — MINOR.
54
+ - Целевых файлов нет — verdict=fail, один элемент `files` с `path: "-"`, `kind: "other"` и finding `CTX-000`, kind=missing_section.
55
+ - Каждое finding: id `CTX-NNN`, severity, kind, evidence `file:line`, detail, fix.
56
+ - verdict=fail при любом MAJOR; `closing_list` = id всех MAJOR. verdict=pass только если MAJOR нет.
57
+
58
+ ФОРМАТ (SGR): резюме (до 10 строк) + json:
59
+ {
60
+ "schema": "context-lint/v1",
61
+ "ok": true,
62
+ "verdict": "pass | fail",
63
+ "closing_list": [],
64
+ "truncated": false,
65
+ "files": [
66
+ {
67
+ "path": "AGENTS.md",
68
+ "kind": "agents | spec | claude | other",
69
+ "lines": 0,
70
+ "words": 0,
71
+ "chars": 0,
72
+ "tokens_est": 0,
73
+ "findings": [
74
+ {
75
+ "id": "CTX-001",
76
+ "severity": "MAJOR | MINOR | INFO",
77
+ "kind": "budget | vague | duplicate | broken_link | missing_section | conflict | unverified_command | other",
78
+ "evidence": "AGENTS.md:42",
79
+ "detail": "...",
80
+ "fix": "..."
81
+ }
82
+ ]
83
+ }
84
+ ],
85
+ "summary": "..."
86
+ }
87
+
88
+ Перед сдачей проверь JSON текстом через `orch_uni_validate_report` и добейся `valid=true`; отчёт возвращай текстом в ответе — файлы не создавай.
89
+
90
+ ОГРАНИЧЕНИЯ: read-only (edit deny + запрет в промпте); shell разрешён только для проверок; не запускать сборку/тесты/миграции/деплой; отчёт по-русски, без воды. Плейсхолдеры — только `<...>` (три и более точки) и `TODO`/`TBD`/`FIXME`; `<DoD>`, `<название>` — не плейсхолдеры.
@@ -19,6 +19,7 @@ permissions:
19
19
  4. Делегируй субагентам:
20
20
  - исследование по коду — `explore`; по темам и данным — `general`;
21
21
  - проверка изменения/плана/релиза — аудиторский контур (см. режим ниже);
22
+ - аудит инструкций (AGENTS.md, SPEC.md, CLAUDE.md) — `context-lint` (read-only, SGR + closing_list);
22
23
  - реализация — сам (мелкое) или `fix-runner` (правки по списку «к закрытию»), крупные задачи — `general`;
23
24
  - параллельные задачи запускай в одном блоке (background) и не опрашивай — уведомления придут сами.
24
25
  5. Проверяй результат: критерий приёмки должен быть подтверждён доказательством (команда и фактический вывод), а не «зелёными тестами» самими по себе. Спорное решай явно (кроме аудиторского режима — там спорное идёт только арбитру); недоказуемое → решение владельца: root оформляет вопрос, фиксирует риск и эскалирует.