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 +109 -10
- package/README.ru.md +108 -10
- package/agents/en/context-lint.md +90 -0
- package/agents/en/orchestrator.md +1 -0
- package/agents/ru/context-lint.md +90 -0
- package/agents/ru/orchestrator.md +1 -0
- package/docs/en/context-efficiency.md +196 -0
- package/docs/ru/context-efficiency.md +196 -0
- package/index.ts +28 -6
- package/lib/commands.ts +148 -0
- package/lib/context-lint.ts +2482 -0
- package/lib/report-schema.ts +36 -0
- package/lib/tools.ts +135 -6
- package/package.json +1 -1
- package/schemas/context-lint-failure.v1.json +29 -0
- package/schemas/context-lint.v1.json +58 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Token-efficient AGENTS.md and SPEC.md
|
|
2
|
+
|
|
3
|
+
An instruction file is a budget of attention, not documentation. Every line is paid for: it participates in every session's context and competes with the task. The goal is the minimum set of testable rules that cannot be inferred from the code and are needed in most sessions.
|
|
4
|
+
|
|
5
|
+
## Budget
|
|
6
|
+
|
|
7
|
+
| File | Target | Ceiling |
|
|
8
|
+
|---|---:|---:|
|
|
9
|
+
| Global `AGENTS.md` | 25–40 lines / <500 tokens | 60 lines |
|
|
10
|
+
| Root `AGENTS.md` | 100–200 lines / 1–2k tokens | 200 lines |
|
|
11
|
+
| Nested `AGENTS.md` | 20–60 lines / <700 tokens | 100 lines |
|
|
12
|
+
| `SPEC.md` | 80–150 lines / ≤1.5k words | 2k words |
|
|
13
|
+
| `ADR` | 30–60 lines / <700 tokens | 100 lines |
|
|
14
|
+
|
|
15
|
+
`orch_uni_context_lint` applies one root budget (`max_lines`, 200 lines by default) and one SPEC word budget (`max_words`, 1500 by default — the target from the table; pass `max_words: 2000` for the ceiling). The per-level figures above are authoring guidance, not separate tool limits. The tool reports what it did not check (links outside the root, directories below depth 3, an unclosed fence) as INFO findings; a `pass` therefore never means "unverified".
|
|
16
|
+
|
|
17
|
+
Selection rule: if a line is not testable, is inferable from code/linters, or is needed in fewer than half of sessions — delete it or move it to a link.
|
|
18
|
+
|
|
19
|
+
## AGENTS.md: 12 rules
|
|
20
|
+
|
|
21
|
+
1. Commands first: install, build, test, one test, lint, run; with flags and a working directory.
|
|
22
|
+
2. Only the non-inferable: flags, traps, layer order, prohibitions, versions.
|
|
23
|
+
3. One instruction per line, imperative, testable.
|
|
24
|
+
4. Style belongs to the linter; do not restate the README or the language standard.
|
|
25
|
+
5. Explicit "Never" and "Ask first": secrets, `dist/`, prod, migrations, dependencies.
|
|
26
|
+
6. Precedence in the text: what overrides what; on a conflict, stop and ask.
|
|
27
|
+
7. One source of truth: `AGENTS.md` plus a symlink/import for `CLAUDE.md`.
|
|
28
|
+
8. Links instead of inline copies; inline only what is needed every time.
|
|
29
|
+
9. Add a rule after a repeated agent mistake, not "for the future".
|
|
30
|
+
10. Delete dead rules: they tax every request.
|
|
31
|
+
11. Stable content on top, dates/branches/tasks at the bottom (prefix cache).
|
|
32
|
+
12. Review the file as code; update it when tooling/CI changes.
|
|
33
|
+
|
|
34
|
+
## AGENTS.md template
|
|
35
|
+
|
|
36
|
+
```md
|
|
37
|
+
# AGENTS.md
|
|
38
|
+
|
|
39
|
+
## Precedence
|
|
40
|
+
1. The user's explicit instruction in the task.
|
|
41
|
+
2. `SPEC.md` of the active feature.
|
|
42
|
+
3. The nearest `AGENTS.md`.
|
|
43
|
+
4. This file.
|
|
44
|
+
5. The global `AGENTS.md`.
|
|
45
|
+
On a conflict, stop and ask.
|
|
46
|
+
|
|
47
|
+
## Commands
|
|
48
|
+
| Task | Command | Note |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| Install | `<...>` | `<version>` |
|
|
51
|
+
| Build | `<...>` | `<flag>` |
|
|
52
|
+
| Tests | `<...>` | `<limit>` |
|
|
53
|
+
| One test | `<...>` | `<name>` |
|
|
54
|
+
| Lint/types | `<...>` | |
|
|
55
|
+
| Run | `<...>` | `<port>` |
|
|
56
|
+
|
|
57
|
+
## Boundaries
|
|
58
|
+
- `<path>/` is generated; do not edit.
|
|
59
|
+
- `<path>/` is vendored; do not edit.
|
|
60
|
+
- New files go to `<path>`.
|
|
61
|
+
|
|
62
|
+
## Conventions
|
|
63
|
+
- <One testable rule per line.>
|
|
64
|
+
|
|
65
|
+
## Verification
|
|
66
|
+
`<analyze>` → `<lint>` → `<test>`.
|
|
67
|
+
Done = all commands green + `<DoD>`.
|
|
68
|
+
|
|
69
|
+
## Never / ask first
|
|
70
|
+
- Never: secrets, `dist/`, prod, applied migrations.
|
|
71
|
+
- Ask first: DB schema, public API, new dependencies, CI.
|
|
72
|
+
|
|
73
|
+
## Pointers
|
|
74
|
+
- `SPEC.md` — the feature contract.
|
|
75
|
+
- `docs/adr/` — decisions.
|
|
76
|
+
- `docs/pitfalls.md` — traps.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## SPEC.md: 12 rules
|
|
80
|
+
|
|
81
|
+
1. One feature per file, 1–3 pages; larger — split via a roadmap.
|
|
82
|
+
2. Stable IDs (`R1`, `AC1.1`); never renumber.
|
|
83
|
+
3. One requirement — one observable behavior.
|
|
84
|
+
4. EARS or Given/When/Then — consistently; MUST/SHOULD/MAY — sparingly.
|
|
85
|
+
5. No HOW: stack, files, classes belong in plan/design/ADR.
|
|
86
|
+
6. Contracts as links, not copies.
|
|
87
|
+
7. Non-goals: 3–7 items.
|
|
88
|
+
8. Invariants separate from acceptance criteria.
|
|
89
|
+
9. Tables for AC and traceability; prose for context only.
|
|
90
|
+
10. Frontmatter: `status`, `owner`, `version`, `supersedes`; no changelog in the body.
|
|
91
|
+
11. At most three open questions, each with an owner and a date; `TBD` elsewhere is forbidden.
|
|
92
|
+
12. DoD and metrics are measurable; "faster" without a number does not count.
|
|
93
|
+
|
|
94
|
+
## SPEC.md template
|
|
95
|
+
|
|
96
|
+
```md
|
|
97
|
+
---
|
|
98
|
+
id: SPEC-000
|
|
99
|
+
title: <name>
|
|
100
|
+
status: draft
|
|
101
|
+
owner: "@team"
|
|
102
|
+
version: 1.0.0
|
|
103
|
+
supersedes: —
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
# SPEC-000: <name>
|
|
107
|
+
|
|
108
|
+
## 1. Context and problem
|
|
109
|
+
<3–5 lines: who suffers, what hurts, why now.>
|
|
110
|
+
|
|
111
|
+
## 2. Goal and non-goals
|
|
112
|
+
**Goal:** <one sentence>.
|
|
113
|
+
**Non-goals:** <3–7 items we deliberately do not do>.
|
|
114
|
+
<!-- one item per line with `-` at 0–4 spaces; a wrapped paragraph is one item;
|
|
115
|
+
fenced, `<pre>` and bullets indented 5+ are code, not items. -->
|
|
116
|
+
|
|
117
|
+
## 3. Scenarios
|
|
118
|
+
| ID | Role | Goal | Value | Independent test |
|
|
119
|
+
|---|---|---|---|---|
|
|
120
|
+
| S1 | <...> | <...> | <...> | <...> |
|
|
121
|
+
|
|
122
|
+
## 4. Requirements (EARS)
|
|
123
|
+
- **R1** — WHEN <trigger>, THE SYSTEM SHALL <result>.
|
|
124
|
+
- **R2** — IF <condition>, THEN THE SYSTEM SHALL <...>.
|
|
125
|
+
|
|
126
|
+
## 5. Acceptance criteria
|
|
127
|
+
| AC | R | Given | When | Then | Test |
|
|
128
|
+
|---|---|---|---|---|---|
|
|
129
|
+
| AC1.1 | R1 | <...> | <...> | <...> | `test_...` |
|
|
130
|
+
|
|
131
|
+
## 6. Invariants and edge cases
|
|
132
|
+
- Invariant: <always true>.
|
|
133
|
+
- Empty/limit/concurrency/error: <...>.
|
|
134
|
+
|
|
135
|
+
## 7. Contracts
|
|
136
|
+
Links: `<openapi.yaml>`, `<schema.sql>`, `<types.ts>`.
|
|
137
|
+
|
|
138
|
+
## 8. Non-functional requirements
|
|
139
|
+
| Metric | Target | How we check |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| Latency p95 | <...> | <...> |
|
|
142
|
+
|
|
143
|
+
## 9. Success metrics
|
|
144
|
+
- **SC-1** — <number and how to check>.
|
|
145
|
+
|
|
146
|
+
## 10. Open questions
|
|
147
|
+
- **Q1** — <...>; owner: <...>; due <date>.
|
|
148
|
+
|
|
149
|
+
## 11. Traceability
|
|
150
|
+
| R | AC | Task | Test |
|
|
151
|
+
|---|---|---|---|
|
|
152
|
+
| R1 | AC1.1 | T1 | `test_...` |
|
|
153
|
+
|
|
154
|
+
## 12. Definition of Done
|
|
155
|
+
- [ ] AC closed.
|
|
156
|
+
- [ ] Tests green.
|
|
157
|
+
- [ ] Contracts and docs/ADR updated.
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Command /agents-md
|
|
161
|
+
|
|
162
|
+
1. Decide the mode: audit an existing file or draft from scratch.
|
|
163
|
+
2. For an audit: `orch_uni_context_lint` → `context-lint`; show the SGR and `closing_list`.
|
|
164
|
+
3. For a draft: collect facts and ask at most 8 questions; do not invent commands or paths.
|
|
165
|
+
4. Fill the template; stay within 150–200 lines.
|
|
166
|
+
5. Run the linter; show the diff and open questions.
|
|
167
|
+
6. Change the canonical file only after approval; apply fixes through `fix-runner`.
|
|
168
|
+
|
|
169
|
+
## Command /spec
|
|
170
|
+
|
|
171
|
+
1. Capture the brief and ask at most 5 clarifying questions.
|
|
172
|
+
2. Non-goals, priorities and metrics are owned by the owner; do not invent them.
|
|
173
|
+
3. Fill the template: EARS, AC with tests, invariants, traceability, DoD.
|
|
174
|
+
4. Run `orch_uni_context_lint` and `context-lint`; show the diff and questions.
|
|
175
|
+
5. Change the canonical file only after approval.
|
|
176
|
+
|
|
177
|
+
## Review
|
|
178
|
+
|
|
179
|
+
- [ ] `AGENTS.md` ≤200 lines, `SPEC.md` ≤1.5k words.
|
|
180
|
+
- [ ] Every line is testable.
|
|
181
|
+
- [ ] No duplicates with README/linter/CI.
|
|
182
|
+
- [ ] Precedence and boundaries are explicit.
|
|
183
|
+
- [ ] Every relative link exists.
|
|
184
|
+
- [ ] Every R has an AC, every AC has a test.
|
|
185
|
+
- [ ] Non-goals and DoD are present.
|
|
186
|
+
- [ ] A baseline on 10–20 tasks exists.
|
|
187
|
+
|
|
188
|
+
## Anti-patterns
|
|
189
|
+
|
|
190
|
+
| Anti-pattern | Why it is bad | What to do |
|
|
191
|
+
|---|---|---|
|
|
192
|
+
| Auto-generation "just in case" | −0.5…−2% success, +20–23% cost | Write manually, high-signal only |
|
|
193
|
+
| Restating README/architecture | Duplication, zero effect | Link to docs |
|
|
194
|
+
| Duplicating the linter | Tokens on what is already checked | Linter/CI |
|
|
195
|
+
| Generic phrases ("write clean code") | Not testable | Imperative + example |
|
|
196
|
+
| Conflicts between layers | The model chooses arbitrarily | Explicit precedence |
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Token-efficient AGENTS.md и SPEC.md
|
|
2
|
+
|
|
3
|
+
Файл инструкций — это бюджет внимания, а не документация. Оплачивается каждая строка: она участвует в контексте каждой сессии и конкурирует с задачей. Цель — минимум проверяемых правил, которые нельзя вывести из кода и которые нужны в большинстве сессий.
|
|
4
|
+
|
|
5
|
+
## Бюджет
|
|
6
|
+
|
|
7
|
+
| Файл | Цель | Потолок |
|
|
8
|
+
|---|---:|---:|
|
|
9
|
+
| Глобальный `AGENTS.md` | 25–40 строк / <500 токенов | 60 строк |
|
|
10
|
+
| Корневой `AGENTS.md` | 100–200 строк / 1–2k токенов | 200 строк |
|
|
11
|
+
| Вложенный `AGENTS.md` | 20–60 строк / <700 токенов | 100 строк |
|
|
12
|
+
| `SPEC.md` | 80–150 строк / ≤1,5k слов | 2k слов |
|
|
13
|
+
| `ADR` | 30–60 строк / <700 токенов | 100 строк |
|
|
14
|
+
|
|
15
|
+
`orch_uni_context_lint` применяет один бюджет корня (`max_lines`, по умолчанию 200 строк) и бюджет слов SPEC (`max_words`, по умолчанию 1500 — цель из таблицы; потолок 2k включается через `max_words: 2000`). Цифры по уровням выше — ориентир для автора, а не отдельные лимиты инструмента. Инструмент сообщает о том, что не проверял (ссылки вне корня, каталоги глубже глубины 3, незакрытый фенс), INFO-находками, поэтому `pass` никогда не означает «непроверено».
|
|
16
|
+
|
|
17
|
+
Правило отбора: если строка не проверяема, выводима из кода/линтера или нужна реже половины сессий — удалить либо вынести в ссылку.
|
|
18
|
+
|
|
19
|
+
## AGENTS.md: 12 правил
|
|
20
|
+
|
|
21
|
+
1. Команды — в начало: install, build, test, one test, lint, run; с флагами и рабочей директорией.
|
|
22
|
+
2. Только невыводимое: флаги, ловушки, порядок слоёв, запреты, версии.
|
|
23
|
+
3. Одна инструкция — одна строка, императив, проверяемо.
|
|
24
|
+
4. Стиль — линтеру; не пересказывать README и стандарт языка.
|
|
25
|
+
5. Явные «Never» и «Ask first»: секреты, `dist/`, prod, миграции, зависимости.
|
|
26
|
+
6. Приоритеты — в тексте: что переопределяет что; при конфликте — остановись и спроси.
|
|
27
|
+
7. Один источник правды: `AGENTS.md` + симлинк/импорт для `CLAUDE.md`.
|
|
28
|
+
8. Ссылки вместо инлайна; инлайнить только то, что нужно всегда.
|
|
29
|
+
9. Правило добавлять после повторной ошибки агента, а не «на будущее».
|
|
30
|
+
10. Мёртвое правило удалять: это налог на каждый запрос.
|
|
31
|
+
11. Стабильное — вверх, даты/ветки/задачи — вниз (prefix cache).
|
|
32
|
+
12. Ревьюить файл как код; менять при смене тулинга/CI.
|
|
33
|
+
|
|
34
|
+
## Шаблон AGENTS.md
|
|
35
|
+
|
|
36
|
+
```md
|
|
37
|
+
# AGENTS.md
|
|
38
|
+
|
|
39
|
+
## Приоритеты
|
|
40
|
+
1. Явное указание пользователя в задаче.
|
|
41
|
+
2. SPEC.md активной фичи.
|
|
42
|
+
3. Ближайший AGENTS.md.
|
|
43
|
+
4. Этот файл.
|
|
44
|
+
5. Глобальный AGENTS.md.
|
|
45
|
+
При конфликте — остановись и спроси.
|
|
46
|
+
|
|
47
|
+
## Команды
|
|
48
|
+
| Задача | Команда | Примечание |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| Установка | `<...>` | `<версия>` |
|
|
51
|
+
| Сборка | `<...>` | `<флаг>` |
|
|
52
|
+
| Тесты | `<...>` | `<лимит>` |
|
|
53
|
+
| Один тест | `<...>` | `<имя>` |
|
|
54
|
+
| Линт/типы | `<...>` | |
|
|
55
|
+
| Запуск | `<...>` | `<порт>` |
|
|
56
|
+
|
|
57
|
+
## Границы
|
|
58
|
+
- `<path>/` — сгенерировано, не редактировать.
|
|
59
|
+
- `<path>/` — вендорное, не редактировать.
|
|
60
|
+
- Новые файлы — в `<path>`.
|
|
61
|
+
|
|
62
|
+
## Конвенции
|
|
63
|
+
- <Одно проверяемое правило на строку.>
|
|
64
|
+
|
|
65
|
+
## Проверка
|
|
66
|
+
`<analyze>` → `<lint>` → `<test>`.
|
|
67
|
+
Готово = все команды зелёные + `<DoD>`.
|
|
68
|
+
|
|
69
|
+
## Никогда / сначала спроси
|
|
70
|
+
- Никогда: секреты, `dist/`, prod, применённые миграции.
|
|
71
|
+
- Сначала спроси: схема БД, публичный API, новые зависимости, CI.
|
|
72
|
+
|
|
73
|
+
## Указатели
|
|
74
|
+
- `SPEC.md` — контракт фичи.
|
|
75
|
+
- `docs/adr/` — решения.
|
|
76
|
+
- `docs/pitfalls.md` — ловушки.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## SPEC.md: 12 правил
|
|
80
|
+
|
|
81
|
+
1. Одна фича — один файл, 1–3 страницы; больше — split через roadmap.
|
|
82
|
+
2. Стабильные ID (`R1`, `AC1.1`), не перенумеровывать.
|
|
83
|
+
3. Одно требование — одно наблюдаемое поведение.
|
|
84
|
+
4. EARS или Given/When/Then — единообразно; MUST/SHOULD/MAY — редко.
|
|
85
|
+
5. Никакого HOW: стек, файлы, классы — в plan/design/ADR.
|
|
86
|
+
6. Контракты — ссылками, не копиями.
|
|
87
|
+
7. Non-goals — 3–7 пунктов.
|
|
88
|
+
8. Инварианты — отдельно от acceptance criteria.
|
|
89
|
+
9. Таблицы — для AC и трассировки; проза — для контекста.
|
|
90
|
+
10. Frontmatter: `status`, `owner`, `version`, `supersedes`; без changelog в теле.
|
|
91
|
+
11. Не более трёх открытых вопросов, у каждого owner и дата; `TBD` в других местах запрещён.
|
|
92
|
+
12. DoD и метрики — измеримые; «быстрее» без числа не считается.
|
|
93
|
+
|
|
94
|
+
## Шаблон SPEC.md
|
|
95
|
+
|
|
96
|
+
```md
|
|
97
|
+
---
|
|
98
|
+
id: SPEC-000
|
|
99
|
+
title: <название>
|
|
100
|
+
status: draft
|
|
101
|
+
owner: "@team"
|
|
102
|
+
version: 1.0.0
|
|
103
|
+
supersedes: —
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
# SPEC-000: <название>
|
|
107
|
+
|
|
108
|
+
## 1. Контекст и проблема
|
|
109
|
+
<3–5 строк: кто страдает, в чём боль, почему сейчас.>
|
|
110
|
+
|
|
111
|
+
## 2. Цель и non-goals
|
|
112
|
+
**Цель:** <одно предложение>.
|
|
113
|
+
**Non-goals:** <3–7 пунктов «сознательно не делаем»>.
|
|
114
|
+
<!-- один пункт на строку с `-` и отступом 0–4; перенесённый абзац — один пункт;
|
|
115
|
+
фенс, `<pre>` и bullet с отступом 5+ — код, не пункт. -->
|
|
116
|
+
|
|
117
|
+
## 3. Сценарии
|
|
118
|
+
| ID | Роль | Цель | Ценность | Независимый тест |
|
|
119
|
+
|---|---|---|---|---|
|
|
120
|
+
| S1 | <...> | <...> | <...> | <...> |
|
|
121
|
+
|
|
122
|
+
## 4. Требования (EARS)
|
|
123
|
+
- **R1** — WHEN <триггер>, THE SYSTEM SHALL <результат>.
|
|
124
|
+
- **R2** — IF <условие>, THEN THE SYSTEM SHALL <...>.
|
|
125
|
+
|
|
126
|
+
## 5. Acceptance criteria
|
|
127
|
+
| AC | R | Given | When | Then | Test |
|
|
128
|
+
|---|---|---|---|---|---|
|
|
129
|
+
| AC1.1 | R1 | <...> | <...> | <...> | `test_...` |
|
|
130
|
+
|
|
131
|
+
## 6. Инварианты и краевые случаи
|
|
132
|
+
- Инвариант: <всегда истинно>.
|
|
133
|
+
- Пусто/лимит/конкурентность/ошибка: <...>.
|
|
134
|
+
|
|
135
|
+
## 7. Контракты
|
|
136
|
+
Ссылки: `<openapi.yaml>`, `<schema.sql>`, `<types.ts>`.
|
|
137
|
+
|
|
138
|
+
## 8. Нефункциональные требования
|
|
139
|
+
| Метрика | Цель | Как проверяем |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| Latency p95 | <...> | <...> |
|
|
142
|
+
|
|
143
|
+
## 9. Метрики успеха
|
|
144
|
+
- **SC-1** — <число и способ проверки>.
|
|
145
|
+
|
|
146
|
+
## 10. Открытые вопросы
|
|
147
|
+
- **Q1** — <...>; owner: <...>; до <дата>.
|
|
148
|
+
|
|
149
|
+
## 11. Трассировка
|
|
150
|
+
| R | AC | Task | Test |
|
|
151
|
+
|---|---|---|---|
|
|
152
|
+
| R1 | AC1.1 | T1 | `test_...` |
|
|
153
|
+
|
|
154
|
+
## 12. Definition of Done
|
|
155
|
+
- [ ] AC закрыты.
|
|
156
|
+
- [ ] Тесты зелёные.
|
|
157
|
+
- [ ] Контракты и docs/ADR обновлены.
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Команда /agents-md
|
|
161
|
+
|
|
162
|
+
1. Определи режим: аудит существующего файла или черновик с нуля.
|
|
163
|
+
2. Для аудита: `orch_uni_context_lint` → `context-lint`; покажи SGR и `closing_list`.
|
|
164
|
+
3. Для черновика: собери факты и задай не более 8 вопросов; не выдумывай команды и пути.
|
|
165
|
+
4. Заполни шаблон; уложись в 150–200 строк.
|
|
166
|
+
5. Прогони линтер, покажи diff и открытые вопросы.
|
|
167
|
+
6. Канонический файл меняй только после подтверждения; правки — через `fix-runner`.
|
|
168
|
+
|
|
169
|
+
## Команда /spec
|
|
170
|
+
|
|
171
|
+
1. Зафиксируй бриф и задай не более 5 уточняющих вопросов.
|
|
172
|
+
2. Non-goals, приоритеты и метрики утверждает владелец; не придумывай их.
|
|
173
|
+
3. Заполни шаблон: EARS, AC с тестами, инварианты, трассировка, DoD.
|
|
174
|
+
4. Прогони `orch_uni_context_lint` и `context-lint`; покажи diff и вопросы.
|
|
175
|
+
5. Канонический файл меняй только после подтверждения.
|
|
176
|
+
|
|
177
|
+
## Ревью
|
|
178
|
+
|
|
179
|
+
- [ ] `AGENTS.md` ≤200 строк, `SPEC.md` ≤1,5k слов.
|
|
180
|
+
- [ ] Каждая строка проверяема.
|
|
181
|
+
- [ ] Нет дублей с README/линтером/CI.
|
|
182
|
+
- [ ] Приоритеты и границы прописаны.
|
|
183
|
+
- [ ] Все относительные ссылки существуют.
|
|
184
|
+
- [ ] У каждого R есть AC, у каждого AC есть тест.
|
|
185
|
+
- [ ] Non-goals и DoD на месте.
|
|
186
|
+
- [ ] Есть baseline на 10–20 задачах.
|
|
187
|
+
|
|
188
|
+
## Анти-паттерны
|
|
189
|
+
|
|
190
|
+
| Анти-паттерн | Почему плохо | Что делать |
|
|
191
|
+
|---|---|---|
|
|
192
|
+
| Автогенерация «на всякий случай» | −0,5…−2% успеха, +20–23% косты | Писать вручную, только высокосигнальное |
|
|
193
|
+
| Пересказ README/архитектуры | Дублирование, нулевой эффект | Ссылка на docs |
|
|
194
|
+
| Дублирование линтера | Токены на то, что и так проверяется | Линтер/CI |
|
|
195
|
+
| Общие фразы («пиши чисто») | Непроверяемо | Императив + пример |
|
|
196
|
+
| Противоречия между уровнями | Модель выбирает произвольно | Явные приоритеты |
|
package/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Registers the orchestrator agent kit — the `orchestrator` root agent with the
|
|
5
5
|
* built-in audit loop, the read-only audit subagents (`factcheck`,
|
|
6
6
|
* `empiric`, `invariant`, `arbiter`, `meta`,
|
|
7
|
-
* `redteam`), and the `fix-runner` writer subagent — plus the `audit-kit`
|
|
7
|
+
* `redteam`, `context-lint`), and the `fix-runner` writer subagent — plus the `audit-kit`
|
|
8
8
|
* document reference and the kit's deterministic `orch_uni_*` tools, straight from
|
|
9
9
|
* this TypeScript entry point.
|
|
10
10
|
*
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
* - The `audit-kit` reference is registered only if that name is free; it points
|
|
25
25
|
* at this package's `docs/` directory so sessions can read the process
|
|
26
26
|
* documents directly.
|
|
27
|
+
* - Slash commands (`/agents-md`, `/spec`) are registered through
|
|
28
|
+
* `ctx.command.transform`; their handlers inject a workflow prompt into the
|
|
29
|
+
* current session and never write files themselves.
|
|
27
30
|
*
|
|
28
31
|
* Models are configuration, not definition: the agent files carry no `model`,
|
|
29
32
|
* and the plugin applies models from its `plugins` entry options —
|
|
@@ -49,6 +52,7 @@ import path from "node:path"
|
|
|
49
52
|
import { fileURLToPath } from "node:url"
|
|
50
53
|
import type { Agent, Model, Plugin, Reference } from "@opencode/plugin"
|
|
51
54
|
import matter from "gray-matter"
|
|
55
|
+
import { registerKitCommands } from "./lib/commands"
|
|
52
56
|
import { registerAuditTools } from "./lib/tools"
|
|
53
57
|
|
|
54
58
|
/** Stable plugin id: diagnostics, enable/disable selectors, storage scope. */
|
|
@@ -114,10 +118,10 @@ function localeCandidates(): string[] {
|
|
|
114
118
|
const REFERENCE_DESCRIPTIONS: Record<Locale, string> = {
|
|
115
119
|
ru:
|
|
116
120
|
"Процессные документы комплекта оркестратора (аудиторский цикл): call-mechanics.md, " +
|
|
117
|
-
"process-ready-loop.md, root-runbook.md, instruction-other-session.md.",
|
|
121
|
+
"process-ready-loop.md, root-runbook.md, instruction-other-session.md, context-efficiency.md.",
|
|
118
122
|
en:
|
|
119
123
|
"Process documents of the orchestrator agent kit (audit loop): call-mechanics.md, " +
|
|
120
|
-
"process-ready-loop.md, root-runbook.md, instruction-other-session.md.",
|
|
124
|
+
"process-ready-loop.md, root-runbook.md, instruction-other-session.md, context-efficiency.md.",
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
/** Frontmatter keys this loader understands; anything else is reported and ignored. */
|
|
@@ -404,9 +408,27 @@ async function setup(ctx: Plugin.Context): Promise<Plugin.Cleanup | undefined> {
|
|
|
404
408
|
})
|
|
405
409
|
|
|
406
410
|
// Deterministic, read-only audit tools: `orch_uni_validate_report`,
|
|
407
|
-
// `orch_uni_snapshot`, `orch_uni_sessions` (see
|
|
408
|
-
// The
|
|
409
|
-
|
|
411
|
+
// `orch_uni_context_lint`, `orch_uni_snapshot`, `orch_uni_sessions` (see
|
|
412
|
+
// `lib/tools.ts` and README «Tools»). The tools cleanup only stops the
|
|
413
|
+
// background session-index subscription; the commands cleanup disposes the
|
|
414
|
+
// command transform registration. A failure after the tools are registered
|
|
415
|
+
// must abort that subscription too — otherwise a half-registered plugin leaks
|
|
416
|
+
// an event listener for the lifetime of the server.
|
|
417
|
+
const toolsCleanup = await registerAuditTools(ctx)
|
|
418
|
+
let commandsCleanup: Plugin.Cleanup
|
|
419
|
+
try {
|
|
420
|
+
commandsCleanup = await registerKitCommands(ctx, locale)
|
|
421
|
+
} catch (error) {
|
|
422
|
+
toolsCleanup()
|
|
423
|
+
throw error
|
|
424
|
+
}
|
|
425
|
+
return async () => {
|
|
426
|
+
try {
|
|
427
|
+
await commandsCleanup()
|
|
428
|
+
} finally {
|
|
429
|
+
toolsCleanup()
|
|
430
|
+
}
|
|
431
|
+
}
|
|
410
432
|
}
|
|
411
433
|
|
|
412
434
|
export default { id: PLUGIN_ID, setup } satisfies Plugin.Plugin
|
package/lib/commands.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash commands of the kit: `/agents-md` and `/spec`.
|
|
3
|
+
*
|
|
4
|
+
* Commands are prompts, not writers: `execute` injects a short workflow prompt
|
|
5
|
+
* into the current session, and the orchestrator runs it with the usual
|
|
6
|
+
* evidence/approval rules. The detailed templates and checklists live in
|
|
7
|
+
* `docs/<locale>/context-efficiency.md`.
|
|
8
|
+
*/
|
|
9
|
+
import type { Plugin } from "@opencode/plugin"
|
|
10
|
+
|
|
11
|
+
type CommandLocale = "ru" | "en"
|
|
12
|
+
|
|
13
|
+
/** Arguments typed after the slash command, without a duplicated command token. */
|
|
14
|
+
function commandArgs(text: string): string {
|
|
15
|
+
return text.replace(/^\s*\/(?:agents-md|spec)\b/i, "").trim()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const DESCRIPTIONS: Record<CommandLocale, { readonly agentsMd: string; readonly spec: string }> = {
|
|
19
|
+
ru: {
|
|
20
|
+
agentsMd: "Создать или проверить AGENTS.md по шаблону context-efficiency.md.",
|
|
21
|
+
spec: "Создать или проверить SPEC.md по шаблону context-efficiency.md.",
|
|
22
|
+
},
|
|
23
|
+
en: {
|
|
24
|
+
agentsMd: "Create or audit AGENTS.md using the context-efficiency.md template.",
|
|
25
|
+
spec: "Create or audit SPEC.md using the context-efficiency.md template.",
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function agentsMdPrompt(locale: CommandLocale, goal: string): string {
|
|
30
|
+
if (locale === "ru") {
|
|
31
|
+
const audit = /(?<![\p{L}\p{N}_])(?:аудит|проверь|проверить)(?![\p{L}\p{N}_])/iu.test(goal)
|
|
32
|
+
return [
|
|
33
|
+
"[Команда /agents-md]",
|
|
34
|
+
`Цель: ${goal}.`,
|
|
35
|
+
"",
|
|
36
|
+
"Работай по документу context-efficiency.md из reference audit-kit.",
|
|
37
|
+
audit
|
|
38
|
+
? "1. Это аудит: сначала вызови orch_uni_context_lint (если доступен), затем context-lint; покажи SGR и closing_list."
|
|
39
|
+
: "1. Это черновик: собери факты (стек, команды, границы, ловушки, never/ask, указатели); задай не более 8 вопросов.",
|
|
40
|
+
"2. Не выдумывай команды, пути и версии; всё непроверенное помечай.",
|
|
41
|
+
"3. Заполни шаблон AGENTS.md из context-efficiency.md; бюджет 150–200 строк.",
|
|
42
|
+
"4. Прогони context-lint, покажи diff и открытые вопросы.",
|
|
43
|
+
"5. Канонический AGENTS.md не меняй без подтверждения; правки — через fix-runner.",
|
|
44
|
+
].join("\n")
|
|
45
|
+
}
|
|
46
|
+
const audit = /\b(?:audit|review|check)\b/i.test(goal)
|
|
47
|
+
return [
|
|
48
|
+
"[Command /agents-md]",
|
|
49
|
+
`Goal: ${goal}.`,
|
|
50
|
+
"",
|
|
51
|
+
"Follow context-efficiency.md from the audit-kit reference.",
|
|
52
|
+
audit
|
|
53
|
+
? "1. This is an audit: run orch_uni_context_lint first (when available), then context-lint; show the SGR and closing_list."
|
|
54
|
+
: "1. This is a draft: collect facts (stack, commands, boundaries, traps, never/ask, pointers); ask at most 8 questions.",
|
|
55
|
+
"2. Do not invent commands, paths or versions; mark everything unverified.",
|
|
56
|
+
"3. Fill the AGENTS.md template from context-efficiency.md; keep the budget at 150–200 lines.",
|
|
57
|
+
"4. Run context-lint and show the diff plus open questions.",
|
|
58
|
+
"5. Do not change the canonical AGENTS.md without approval; apply fixes through fix-runner.",
|
|
59
|
+
].join("\n")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function specPrompt(locale: CommandLocale, brief: string): string {
|
|
63
|
+
if (locale === "ru") {
|
|
64
|
+
return [
|
|
65
|
+
"[Команда /spec]",
|
|
66
|
+
`Фича: ${brief}.`,
|
|
67
|
+
"",
|
|
68
|
+
"Работай по документу context-efficiency.md из reference audit-kit.",
|
|
69
|
+
"1. Задай не более 5 уточняющих вопросов; non-goals, приоритеты и метрики утверждает владелец.",
|
|
70
|
+
"2. Заполни шаблон SPEC.md: контекст, цель, non-goals 3–7, сценарии, R1..Rn (EARS), AC с тестами, инварианты, контракты ссылками, NFR, SC, открытые вопросы, трассировка, DoD.",
|
|
71
|
+
"3. Прогони orch_uni_context_lint (если доступен) и context-lint; покажи diff и открытые вопросы.",
|
|
72
|
+
"4. Канонический SPEC.md не меняй без подтверждения; правки — через fix-runner.",
|
|
73
|
+
].join("\n")
|
|
74
|
+
}
|
|
75
|
+
return [
|
|
76
|
+
"[Command /spec]",
|
|
77
|
+
`Feature: ${brief}.`,
|
|
78
|
+
"",
|
|
79
|
+
"Follow context-efficiency.md from the audit-kit reference.",
|
|
80
|
+
"1. Ask at most 5 clarifying questions; non-goals, priorities and success metrics are owned by the owner.",
|
|
81
|
+
"2. Fill the SPEC.md template: context, goal, 3–7 non-goals, scenarios, R1..Rn (EARS), AC with tests, invariants, contract links, NFRs, success metrics, open questions, traceability, DoD.",
|
|
82
|
+
"3. Run orch_uni_context_lint (when available) and context-lint; show the diff and open questions.",
|
|
83
|
+
"4. Do not change the canonical SPEC.md without approval; apply fixes through fix-runner.",
|
|
84
|
+
].join("\n")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Register `/agents-md` and `/spec`; the cleanup disposes the transform registration. */
|
|
88
|
+
export async function registerKitCommands(ctx: Plugin.Context, locale: CommandLocale): Promise<Plugin.Cleanup> {
|
|
89
|
+
// The command API is optional in a host build. A missing `list` was already
|
|
90
|
+
// tolerated; a missing `transform` used to throw out of `setup` and take every
|
|
91
|
+
// agent and tool with it, so it degrades to a warning plus a no-op cleanup.
|
|
92
|
+
const command = (ctx as Partial<Plugin.Context>).command
|
|
93
|
+
if (command === undefined || typeof command.transform !== "function") {
|
|
94
|
+
console.warn("orch-uni: this host has no command API; /agents-md and /spec are not registered")
|
|
95
|
+
return async () => {}
|
|
96
|
+
}
|
|
97
|
+
let existing = new Set<string>()
|
|
98
|
+
try {
|
|
99
|
+
const listed = await command.list()
|
|
100
|
+
existing = new Set(listed.data.map((item) => item.name))
|
|
101
|
+
} catch {
|
|
102
|
+
// No listing API: register; the host resolves a collision on its side.
|
|
103
|
+
}
|
|
104
|
+
const registration = await command.transform((editor) => {
|
|
105
|
+
if (!existing.has("agents-md")) {
|
|
106
|
+
editor.add({
|
|
107
|
+
name: "agents-md",
|
|
108
|
+
description: DESCRIPTIONS[locale].agentsMd,
|
|
109
|
+
execute: async (input) => {
|
|
110
|
+
await ctx.session.prompt({
|
|
111
|
+
sessionID: input.sessionID,
|
|
112
|
+
text: agentsMdPrompt(
|
|
113
|
+
locale,
|
|
114
|
+
commandArgs(input.prompt.text) || (locale === "ru" ? "текущий репозиторий" : "the current repository"),
|
|
115
|
+
),
|
|
116
|
+
...(input.prompt.files === undefined ? {} : { files: input.prompt.files }),
|
|
117
|
+
...(input.prompt.agents === undefined ? {} : { agents: input.prompt.agents }),
|
|
118
|
+
...(input.prompt.skills === undefined ? {} : { skills: input.prompt.skills }),
|
|
119
|
+
delivery: input.delivery,
|
|
120
|
+
})
|
|
121
|
+
},
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
if (!existing.has("spec")) {
|
|
125
|
+
editor.add({
|
|
126
|
+
name: "spec",
|
|
127
|
+
description: DESCRIPTIONS[locale].spec,
|
|
128
|
+
execute: async (input) => {
|
|
129
|
+
await ctx.session.prompt({
|
|
130
|
+
sessionID: input.sessionID,
|
|
131
|
+
text: specPrompt(
|
|
132
|
+
locale,
|
|
133
|
+
commandArgs(input.prompt.text) ||
|
|
134
|
+
(locale === "ru" ? "описание фичи не задано — спроси" : "no feature brief — ask for one"),
|
|
135
|
+
),
|
|
136
|
+
...(input.prompt.files === undefined ? {} : { files: input.prompt.files }),
|
|
137
|
+
...(input.prompt.agents === undefined ? {} : { agents: input.prompt.agents }),
|
|
138
|
+
...(input.prompt.skills === undefined ? {} : { skills: input.prompt.skills }),
|
|
139
|
+
delivery: input.delivery,
|
|
140
|
+
})
|
|
141
|
+
},
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
return async () => {
|
|
146
|
+
await registration.dispose()
|
|
147
|
+
}
|
|
148
|
+
}
|