@k0t0vich/meta-agents-template 0.1.0 → 0.1.1
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 +32 -29
- package/agents.md +10 -3
- package/package.json +4 -2
- package/src/sync.mjs +85 -0
- package/template/.meta-agents/config/roles.yaml +3 -1
- package/template/.meta-agents/config/system.yaml +31 -0
- package/template/.meta-agents/prompts/governance-watchdog.md +3 -0
- package/template/.meta-agents/prompts/reviewer-judge.md +2 -1
- package/template/.meta-agents/scripts/run-review-gate.mjs +120 -0
- package/template/.meta-agents/scripts/verify-commit-link.mjs +50 -0
- package/template/.meta-agents/scripts/verify-governance.mjs +74 -0
- package/template/README.md +12 -0
- package/template/agents.md +10 -3
- package/template/package.json +4 -1
- package/template/tracker-command-template.md +64 -6
- package/tracker-command-template.md +64 -6
package/README.md
CHANGED
|
@@ -72,10 +72,26 @@ my-project/
|
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
## Канонические команды
|
|
75
|
+
0. `VERIFY_GOVERNANCE_GATE`
|
|
75
76
|
1. `CREATE_TASK`
|
|
76
77
|
2. `SET_STATUS`
|
|
77
|
-
3. `
|
|
78
|
-
4. `
|
|
78
|
+
3. `RUN_REVIEW_GATE`
|
|
79
|
+
4. `COMMIT_BY_NAME`
|
|
80
|
+
5. `ASSIGN_SPRINT`
|
|
81
|
+
|
|
82
|
+
`VERIFY_GOVERNANCE_GATE` выполняет `Governance Watchdog Agent` перед любой операцией и блокирует выполнение при нарушении PRD/acceptance/user-confirmation правил.
|
|
83
|
+
`RUN_REVIEW_GATE` выполняет `Reviewer/Judge Agent` перед коммитом: выводит summary выполненного, критические замечания, потенциальные риски и итог `PASS/FAIL`.
|
|
84
|
+
|
|
85
|
+
## Self-bootstrap (для этого репозитория)
|
|
86
|
+
Чтобы сам шаблон работал по своим же правилам, запусти:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm run self:bootstrap
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Команда разворачивает шаблонные управляемые файлы в текущий репозиторий, создаёт стартовую задачу с PRD (`AGT-SELF-001`) и заполняет backlog/sprint/status-log.
|
|
93
|
+
|
|
94
|
+
Локальные рабочие артефакты `tasks/` и `.meta-agents/` добавлены в `.gitignore`, чтобы не засорять публикационный пакет.
|
|
79
95
|
|
|
80
96
|
## Жёсткие критерии приёмки
|
|
81
97
|
Задача принимается только если одновременно выполнены все условия:
|
|
@@ -86,41 +102,28 @@ my-project/
|
|
|
86
102
|
5. Пройдены обязательные `human` approvals.
|
|
87
103
|
6. Собран полный evidence-пакет.
|
|
88
104
|
7. Синхронизированы `task/status/sprint` в трекере.
|
|
105
|
+
8. Перед каждой командой пройден watchdog gate (`VERIFY_GOVERNANCE_GATE`).
|
|
106
|
+
9. Перед коммитом пройден review gate (`RUN_REVIEW_GATE`).
|
|
107
|
+
10. Каждый коммит связан с issue/task (`TASK-ID` и/или `#issue` в commit message).
|
|
89
108
|
|
|
90
109
|
Если хотя бы один пункт не выполнен, задача не принимается.
|
|
91
110
|
|
|
92
|
-
##
|
|
93
|
-
|
|
94
|
-
- `COMMIT_BY_NAME` — только после подтверждения пользователя;
|
|
95
|
-
- перевод задачи в `DONE` — только после подтверждения пользователя;
|
|
96
|
-
- без подтверждения максимум статуса: `READY`.
|
|
97
|
-
|
|
98
|
-
## Публикация через Trusted Publishing (рекомендуется)
|
|
99
|
-
В репозитории настроен workflow:
|
|
100
|
-
- [.github/workflows/publish.yml](./.github/workflows/publish.yml)
|
|
101
|
-
- Подробный регламент публикации: [PUBLISHING.md](./PUBLISHING.md)
|
|
102
|
-
|
|
103
|
-
Он публикует пакет по тегу `v*` или вручную через `workflow_dispatch` и использует OIDC (`id-token: write`) вместо long-lived npm токена.
|
|
104
|
-
|
|
105
|
-
Что нужно сделать в npm UI (один раз):
|
|
106
|
-
1. Открой `npmjs.com -> Packages -> @k0t0vich/meta-agents-template -> Settings -> Trusted publishing`.
|
|
107
|
-
2. Добавь trusted publisher типа `GitHub Actions` с полями:
|
|
108
|
-
- Organization/User: `k0t0vich`
|
|
109
|
-
- Repository: `meta-agents-template`
|
|
110
|
-
- Workflow filename: `publish.yml`
|
|
111
|
-
3. Сохрани настройки.
|
|
111
|
+
## Локальная проверка governance
|
|
112
|
+
В сгенерированном проекте доступна команда:
|
|
112
113
|
|
|
113
|
-
Как выпускать релиз:
|
|
114
114
|
```bash
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
npm run meta:verify
|
|
116
|
+
npm run meta:review
|
|
117
|
+
npm run meta:verify-link
|
|
117
118
|
```
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
Она проверяет наличие обязательных PRD-блоков в задачах (`Описание`, `Проверяемость`, `Что сделано`) и валидирует базовую процессную дисциплину.
|
|
120
121
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
-
|
|
122
|
+
## Правило диалога пользователя
|
|
123
|
+
Коммиты и закрытие задач выполняются только по явному подтверждению пользователя в текущем диалоге:
|
|
124
|
+
- `COMMIT_BY_NAME` — только после подтверждения пользователя;
|
|
125
|
+
- перевод задачи в `DONE` — только после подтверждения пользователя;
|
|
126
|
+
- без подтверждения максимум статуса: `READY`.
|
|
124
127
|
|
|
125
128
|
## Основные документы шаблона
|
|
126
129
|
- [agents.md](./agents.md)
|
package/agents.md
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
## 3) Роли агентов
|
|
23
23
|
- `Chief of Staff Agent`: оркестрация цепочки, приоритеты, блокеры, эскалации.
|
|
24
24
|
- `Agile Manager Agent`: операции по задачам/спринтам/статусам/коммитам через трекер.
|
|
25
|
+
- `Governance Watchdog Agent`: обязательный контроль PRD/критериев/разрешений перед каждой командой.
|
|
25
26
|
- `Product Manager Agent`: формулирует PRD и критерии приёмки.
|
|
26
27
|
- `Solution Architect Agent`: проектирует архитектуру и контракты компонентов.
|
|
27
28
|
- `Verifier Designer Agent`: проектирует модель валидации и evidence-план.
|
|
@@ -91,10 +92,12 @@ Name: <agent role>
|
|
|
91
92
|
Все рабочие операции проходят через `Agile Manager Agent` + `TrackerGateway`.
|
|
92
93
|
Операционные шаблоны команд: [tracker-command-template.md](./tracker-command-template.md).
|
|
93
94
|
|
|
95
|
+
0. `VERIFY_GOVERNANCE_GATE`
|
|
94
96
|
1. `CREATE_TASK`
|
|
95
97
|
2. `SET_STATUS`
|
|
96
|
-
3. `
|
|
97
|
-
4. `
|
|
98
|
+
3. `RUN_REVIEW_GATE`
|
|
99
|
+
4. `COMMIT_BY_NAME`
|
|
100
|
+
5. `ASSIGN_SPRINT`
|
|
98
101
|
|
|
99
102
|
## 10) Коммиты и закрытие задач: только по подтверждению пользователя
|
|
100
103
|
Запрещено выполнять автоматически:
|
|
@@ -102,9 +105,10 @@ Name: <agent role>
|
|
|
102
105
|
- перевод задачи в `DONE`.
|
|
103
106
|
|
|
104
107
|
Обязательное правило:
|
|
105
|
-
- `COMMIT_BY_NAME` выполняется только после явного подтверждения пользователя в текущем диалоге;
|
|
108
|
+
- `COMMIT_BY_NAME` выполняется только после `RUN_REVIEW_GATE: PASS` и явного подтверждения пользователя в текущем диалоге;
|
|
106
109
|
- `SET_STATUS -> DONE` выполняется только после явного подтверждения пользователя в текущем диалоге;
|
|
107
110
|
- без подтверждения пользователя максимум допустимого статуса: `READY`.
|
|
111
|
+
- сообщение коммита обязано содержать ссылку на задачу (`TASK-ID` и/или `#issue-number`).
|
|
108
112
|
|
|
109
113
|
## 11) Жёсткие критерии приёмки (все обязательны)
|
|
110
114
|
Задача принимается только если одновременно выполнены все условия:
|
|
@@ -117,6 +121,9 @@ Name: <agent role>
|
|
|
117
121
|
7. Синхронизированы `task/status/sprint` в трекере.
|
|
118
122
|
8. Если был коммит, есть явное подтверждение пользователя на коммит.
|
|
119
123
|
9. Если задача закрыта в `DONE`, есть явное подтверждение пользователя на закрытие.
|
|
124
|
+
10. Перед каждой командой пройден `VERIFY_GOVERNANCE_GATE` от `Governance Watchdog Agent`.
|
|
125
|
+
11. Перед коммитом пройден `RUN_REVIEW_GATE` от `Reviewer/Judge Agent`.
|
|
126
|
+
12. Коммит содержит ссылку на issue/task (`TASK-ID` или `#issue`).
|
|
120
127
|
|
|
121
128
|
Если хотя бы один критерий не выполнен, задача не принимается.
|
|
122
129
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k0t0vich/meta-agents-template",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Template system for verification-first agentic development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"meta-agents": "bin/meta-agents.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"start": "node bin/meta-agents.js --help"
|
|
10
|
+
"start": "node bin/meta-agents.js --help",
|
|
11
|
+
"self:sync": "node bin/meta-agents.js sync . --force",
|
|
12
|
+
"self:bootstrap": "npm run self:sync && node scripts/self-bootstrap.mjs"
|
|
11
13
|
},
|
|
12
14
|
"files": [
|
|
13
15
|
"README.md",
|
package/src/sync.mjs
CHANGED
|
@@ -10,6 +10,16 @@ const MANAGED_PATHS = [
|
|
|
10
10
|
"tasks/task-status-log.md",
|
|
11
11
|
];
|
|
12
12
|
|
|
13
|
+
const TEXT_EXTENSIONS = new Set([
|
|
14
|
+
".md",
|
|
15
|
+
".txt",
|
|
16
|
+
".json",
|
|
17
|
+
".yaml",
|
|
18
|
+
".yml",
|
|
19
|
+
".mjs",
|
|
20
|
+
".js",
|
|
21
|
+
]);
|
|
22
|
+
|
|
13
23
|
async function exists(p) {
|
|
14
24
|
try {
|
|
15
25
|
await fs.access(p);
|
|
@@ -19,10 +29,79 @@ async function exists(p) {
|
|
|
19
29
|
}
|
|
20
30
|
}
|
|
21
31
|
|
|
32
|
+
async function walkFiles(dir, list = []) {
|
|
33
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
34
|
+
for (const entry of entries) {
|
|
35
|
+
const entryPath = path.join(dir, entry.name);
|
|
36
|
+
if (entry.isDirectory()) {
|
|
37
|
+
await walkFiles(entryPath, list);
|
|
38
|
+
} else {
|
|
39
|
+
list.push(entryPath);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return list;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function shouldReplacePlaceholders(filePath) {
|
|
46
|
+
return TEXT_EXTENSIONS.has(path.extname(filePath));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function replaceInFile(filePath, values) {
|
|
50
|
+
if (!shouldReplacePlaceholders(filePath)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const input = await fs.readFile(filePath, "utf8");
|
|
54
|
+
let output = input;
|
|
55
|
+
for (const [key, value] of Object.entries(values)) {
|
|
56
|
+
output = output.replaceAll(`__${key}__`, value);
|
|
57
|
+
}
|
|
58
|
+
if (output !== input) {
|
|
59
|
+
await fs.writeFile(filePath, output, "utf8");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function replacePlaceholdersInManagedPaths(targetDir, managedPaths, values) {
|
|
64
|
+
for (const managedPath of managedPaths) {
|
|
65
|
+
const absolute = path.join(targetDir, managedPath);
|
|
66
|
+
if (!(await exists(absolute))) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const stat = await fs.stat(absolute);
|
|
71
|
+
if (stat.isDirectory()) {
|
|
72
|
+
const files = await walkFiles(absolute);
|
|
73
|
+
for (const file of files) {
|
|
74
|
+
await replaceInFile(file, values);
|
|
75
|
+
}
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await replaceInFile(absolute, values);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function readCurrentDefaultTracker(targetDir) {
|
|
84
|
+
const trackersPath = path.join(targetDir, ".meta-agents", "config", "trackers.yaml");
|
|
85
|
+
if (!(await exists(trackersPath))) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const input = await fs.readFile(trackersPath, "utf8");
|
|
89
|
+
const match = input.match(/default:\s*"?([a-zA-Z0-9_-]+)"?/);
|
|
90
|
+
if (!match || !match[1]) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const value = match[1];
|
|
94
|
+
if (value.startsWith("__") && value.endsWith("__")) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
|
|
22
100
|
export async function syncTemplate({ cwd, templateRoot, target, force }) {
|
|
23
101
|
const targetDir = path.resolve(cwd, target);
|
|
24
102
|
const updated = [];
|
|
25
103
|
const skipped = [];
|
|
104
|
+
const existingDefaultTracker = await readCurrentDefaultTracker(targetDir);
|
|
26
105
|
|
|
27
106
|
for (const managedPath of MANAGED_PATHS) {
|
|
28
107
|
const source = path.join(templateRoot, managedPath);
|
|
@@ -42,5 +121,11 @@ export async function syncTemplate({ cwd, templateRoot, target, force }) {
|
|
|
42
121
|
updated.push(managedPath);
|
|
43
122
|
}
|
|
44
123
|
|
|
124
|
+
const projectName = path.basename(targetDir);
|
|
125
|
+
await replacePlaceholdersInManagedPaths(targetDir, updated, {
|
|
126
|
+
PROJECT_NAME: projectName,
|
|
127
|
+
DEFAULT_TRACKER: existingDefaultTracker || "github",
|
|
128
|
+
});
|
|
129
|
+
|
|
45
130
|
return { targetDir, updated, skipped };
|
|
46
131
|
}
|
|
@@ -3,6 +3,8 @@ roles:
|
|
|
3
3
|
responsibility: "Оркестрация, блокеры, эскалации"
|
|
4
4
|
- name: "Agile Manager Agent"
|
|
5
5
|
responsibility: "CREATE_TASK/SET_STATUS/COMMIT_BY_NAME/ASSIGN_SPRINT"
|
|
6
|
+
- name: "Governance Watchdog Agent"
|
|
7
|
+
responsibility: "Обязательный preflight-gate: PRD/acceptance/user confirmation policy"
|
|
6
8
|
- name: "Product Manager Agent"
|
|
7
9
|
responsibility: "PRD и acceptance criteria"
|
|
8
10
|
- name: "Solution Architect Agent"
|
|
@@ -16,6 +18,6 @@ roles:
|
|
|
16
18
|
- name: "QA Agent"
|
|
17
19
|
responsibility: "Верификация и тестирование"
|
|
18
20
|
- name: "Reviewer/Judge Agent"
|
|
19
|
-
responsibility: "Независимая приёмка"
|
|
21
|
+
responsibility: "Независимая приёмка + обязательный pre-commit review gate"
|
|
20
22
|
- name: "Documentation Agent"
|
|
21
23
|
responsibility: "Синхронизация документации"
|
|
@@ -26,6 +26,34 @@ system:
|
|
|
26
26
|
- commit
|
|
27
27
|
- task_close_done
|
|
28
28
|
max_status_without_user_confirmation: READY
|
|
29
|
+
watchdog:
|
|
30
|
+
required: true
|
|
31
|
+
before_commands:
|
|
32
|
+
- VERIFY_GOVERNANCE_GATE
|
|
33
|
+
- CREATE_TASK
|
|
34
|
+
- SET_STATUS
|
|
35
|
+
- RUN_REVIEW_GATE
|
|
36
|
+
- COMMIT_BY_NAME
|
|
37
|
+
- ASSIGN_SPRINT
|
|
38
|
+
minimum_checks:
|
|
39
|
+
- prd_sections_complete
|
|
40
|
+
- acceptance_criteria_defined
|
|
41
|
+
- user_confirmation_policy_respected
|
|
42
|
+
review_gate:
|
|
43
|
+
required_before_commit: true
|
|
44
|
+
command: RUN_REVIEW_GATE
|
|
45
|
+
reporter_role: "Reviewer/Judge Agent"
|
|
46
|
+
required_sections:
|
|
47
|
+
- what_done_summary
|
|
48
|
+
- critical_findings
|
|
49
|
+
- potential_risks
|
|
50
|
+
- recommendation_pass_or_fail
|
|
51
|
+
block_on_critical: true
|
|
52
|
+
commit_linkage:
|
|
53
|
+
required: true
|
|
54
|
+
accepted_patterns:
|
|
55
|
+
- "TASK-ID"
|
|
56
|
+
- "#issue"
|
|
29
57
|
acceptance:
|
|
30
58
|
hard_criteria:
|
|
31
59
|
- prd_sections_complete
|
|
@@ -35,6 +63,9 @@ system:
|
|
|
35
63
|
- human_approvals_passed
|
|
36
64
|
- evidence_pack_complete
|
|
37
65
|
- tracker_sync_complete
|
|
66
|
+
- watchdog_gate_passed
|
|
67
|
+
- review_gate_passed
|
|
68
|
+
- commit_linked_to_issue
|
|
38
69
|
auto_select:
|
|
39
70
|
required: true
|
|
40
71
|
before_each_task: true
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
Role: Reviewer/Judge Agent
|
|
2
|
-
Goal: независимая приёмка по
|
|
2
|
+
Goal: независимая приёмка по критериям и обязательный pre-commit review gate.
|
|
3
|
+
Output format: что сделано, критические замечания, потенциальные риски, итог PASS/FAIL.
|
|
3
4
|
Output: accepted/rejected + findings.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
|
|
5
|
+
function git(args, allowFailure = false) {
|
|
6
|
+
try {
|
|
7
|
+
const output = execFileSync("git", args, { encoding: "utf8" });
|
|
8
|
+
return output.trim();
|
|
9
|
+
} catch (error) {
|
|
10
|
+
if (allowFailure) {
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function splitLines(value) {
|
|
18
|
+
if (!value) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
return value
|
|
22
|
+
.split("\n")
|
|
23
|
+
.map((line) => line.trim())
|
|
24
|
+
.filter(Boolean);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function matchTestFile(filePath) {
|
|
28
|
+
return /(^|\/)(tests?|__tests__)\//i.test(filePath) || /\.(test|spec)\.[cm]?[jt]sx?$/i.test(filePath);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function scanMarkers(files) {
|
|
32
|
+
const markers = [];
|
|
33
|
+
const pattern = /\b(TODO|FIXME|XXX|HACK)\b\s*[:\-]/g;
|
|
34
|
+
|
|
35
|
+
for (const file of files) {
|
|
36
|
+
try {
|
|
37
|
+
const content = await fs.readFile(path.resolve(process.cwd(), file), "utf8");
|
|
38
|
+
const lines = content.split("\n");
|
|
39
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
40
|
+
const line = lines[index];
|
|
41
|
+
if (pattern.test(line)) {
|
|
42
|
+
markers.push(`${file}:${index + 1} -> ${line.trim()}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} catch {
|
|
46
|
+
// Skip binary/unreadable files.
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return markers;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function main() {
|
|
54
|
+
const stagedFiles = splitLines(git(["diff", "--cached", "--name-only"], true));
|
|
55
|
+
const recentFiles = splitLines(git(["show", "--name-only", "--pretty=", "HEAD"], true));
|
|
56
|
+
const files = stagedFiles.length > 0 ? stagedFiles : recentFiles;
|
|
57
|
+
|
|
58
|
+
if (files.length === 0) {
|
|
59
|
+
console.log("Review Gate FAIL");
|
|
60
|
+
console.log("- reason: no staged or recent changes detected");
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const critical = [];
|
|
65
|
+
const risks = [];
|
|
66
|
+
|
|
67
|
+
const markers = await scanMarkers(files);
|
|
68
|
+
if (markers.length > 0) {
|
|
69
|
+
critical.push(...markers.slice(0, 20));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const sourceTouched = files.some((file) => file.startsWith("src/") || file.startsWith("template/"));
|
|
73
|
+
const testsTouched = files.some((file) => matchTestFile(file));
|
|
74
|
+
if (sourceTouched && !testsTouched) {
|
|
75
|
+
risks.push("Source/template changes detected without explicit test changes.");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log("# Review Gate Report");
|
|
79
|
+
console.log("");
|
|
80
|
+
console.log("## Что сделано");
|
|
81
|
+
for (const file of files) {
|
|
82
|
+
console.log(`- changed: ${file}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log("");
|
|
86
|
+
console.log("## Критические замечания");
|
|
87
|
+
if (critical.length === 0) {
|
|
88
|
+
console.log("- none");
|
|
89
|
+
} else {
|
|
90
|
+
for (const item of critical) {
|
|
91
|
+
console.log(`- ${item}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log("");
|
|
96
|
+
console.log("## Потенциальные риски");
|
|
97
|
+
if (risks.length === 0) {
|
|
98
|
+
console.log("- none");
|
|
99
|
+
} else {
|
|
100
|
+
for (const item of risks) {
|
|
101
|
+
console.log(`- ${item}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log("");
|
|
106
|
+
if (critical.length === 0) {
|
|
107
|
+
console.log("## Решение");
|
|
108
|
+
console.log("- PASS");
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log("## Решение");
|
|
113
|
+
console.log("- FAIL");
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
main().catch((error) => {
|
|
118
|
+
console.error(`Review Gate FAIL: ${error.message}`);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
function readLastCommitSubject(ref = "HEAD") {
|
|
4
|
+
const output = execFileSync("git", ["log", "-1", "--pretty=%s", ref], { encoding: "utf8" });
|
|
5
|
+
return output.trim();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function validateMessage(message) {
|
|
9
|
+
const hasIssueNumber = /#\d+\b/.test(message);
|
|
10
|
+
const hasTaskId = /\b[A-Z][A-Z0-9_]*-\d+\b/.test(message);
|
|
11
|
+
return hasIssueNumber || hasTaskId;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function parseArgs(argv) {
|
|
15
|
+
const args = { message: "", ref: "HEAD" };
|
|
16
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
17
|
+
if (argv[i] === "--message") {
|
|
18
|
+
args.message = argv[i + 1] || "";
|
|
19
|
+
i += 1;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (argv[i] === "--ref") {
|
|
23
|
+
args.ref = argv[i + 1] || "HEAD";
|
|
24
|
+
i += 1;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return args;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function main() {
|
|
32
|
+
const options = parseArgs(process.argv.slice(2));
|
|
33
|
+
const message = options.message || readLastCommitSubject(options.ref);
|
|
34
|
+
|
|
35
|
+
if (!message) {
|
|
36
|
+
console.error("Commit link FAIL: empty commit message.");
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!validateMessage(message)) {
|
|
41
|
+
console.error("Commit link FAIL: message must contain TASK-ID or #issue.");
|
|
42
|
+
console.error(`Message: ${message}`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log(`Commit link PASS: ${message}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
main();
|
|
50
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
|
|
5
|
+
const TASKS_DIR = path.resolve(process.cwd(), "tasks");
|
|
6
|
+
const EXCLUDED_FILES = new Set(["backlog.md", "sprint-1.md", "task-status-log.md"]);
|
|
7
|
+
|
|
8
|
+
const REQUIRED_PATTERNS = [
|
|
9
|
+
{ label: "PRD section: Описание", regex: /^###\s+Описание/m },
|
|
10
|
+
{ label: "PRD section: Проверяемость", regex: /^###\s+Проверяемость/m },
|
|
11
|
+
{ label: "PRD section: Что сделано", regex: /^###\s+Что сделано/m },
|
|
12
|
+
{ label: "Verifiability strict", regex: /^\s*-\s*strict:/m },
|
|
13
|
+
{ label: "Verifiability statistical", regex: /^\s*-\s*statistical:/m },
|
|
14
|
+
{ label: "Verifiability human", regex: /^\s*-\s*human:/m },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
async function listTaskFiles() {
|
|
18
|
+
const entries = await fs.readdir(TASKS_DIR, { withFileTypes: true });
|
|
19
|
+
return entries
|
|
20
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith(".md") && !EXCLUDED_FILES.has(entry.name))
|
|
21
|
+
.map((entry) => path.join(TASKS_DIR, entry.name));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function validateTask(filePath) {
|
|
25
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
26
|
+
const failed = [];
|
|
27
|
+
|
|
28
|
+
for (const pattern of REQUIRED_PATTERNS) {
|
|
29
|
+
if (!pattern.regex.test(content)) {
|
|
30
|
+
failed.push(pattern.label);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return failed;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function main() {
|
|
38
|
+
let taskFiles;
|
|
39
|
+
try {
|
|
40
|
+
taskFiles = await listTaskFiles();
|
|
41
|
+
} catch {
|
|
42
|
+
console.error("Governance FAIL: tasks directory not found.");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (taskFiles.length === 0) {
|
|
47
|
+
console.error("Governance FAIL: no task markdown files found in tasks/.");
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let hasErrors = false;
|
|
52
|
+
for (const filePath of taskFiles) {
|
|
53
|
+
const failed = await validateTask(filePath);
|
|
54
|
+
if (failed.length > 0) {
|
|
55
|
+
hasErrors = true;
|
|
56
|
+
console.error(`Governance FAIL: ${path.basename(filePath)}`);
|
|
57
|
+
for (const item of failed) {
|
|
58
|
+
console.error(` - missing: ${item}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (hasErrors) {
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log(`Governance PASS: checked ${taskFiles.length} task file(s).`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
main().catch((error) => {
|
|
71
|
+
console.error(`Governance FAIL: ${error.message}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
});
|
|
74
|
+
|
package/template/README.md
CHANGED
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
- `.meta-agents/`: конфигурация системы и шаблоны PRD/verification;
|
|
9
9
|
- `tasks/`: backlog/sprint/status-log.
|
|
10
10
|
|
|
11
|
+
Отдельно включён `Governance Watchdog Agent`:
|
|
12
|
+
- обязательный gate перед каждой командой;
|
|
13
|
+
- техническая проверка PRD-структуры через `npm run meta:verify`.
|
|
14
|
+
- обязательный review gate перед коммитом через `npm run meta:review`.
|
|
15
|
+
|
|
11
16
|
## Что спросит init
|
|
12
17
|
1. Git режим: `github`, `local` или `skip`.
|
|
13
18
|
2. Нужно ли создать GitHub-репозиторий сразу.
|
|
@@ -21,3 +26,10 @@
|
|
|
21
26
|
|
|
22
27
|
## Команды
|
|
23
28
|
Смотри `tracker-command-template.md`.
|
|
29
|
+
|
|
30
|
+
Дополнительно:
|
|
31
|
+
```bash
|
|
32
|
+
npm run meta:verify
|
|
33
|
+
npm run meta:review
|
|
34
|
+
npm run meta:verify-link
|
|
35
|
+
```
|
package/template/agents.md
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
## 3) Роли агентов
|
|
23
23
|
- `Chief of Staff Agent`: оркестрация цепочки, приоритеты, блокеры, эскалации.
|
|
24
24
|
- `Agile Manager Agent`: операции по задачам/спринтам/статусам/коммитам через трекер.
|
|
25
|
+
- `Governance Watchdog Agent`: обязательный контроль PRD/критериев/разрешений перед каждой командой.
|
|
25
26
|
- `Product Manager Agent`: формулирует PRD и критерии приёмки.
|
|
26
27
|
- `Solution Architect Agent`: проектирует архитектуру и контракты компонентов.
|
|
27
28
|
- `Verifier Designer Agent`: проектирует модель валидации и evidence-план.
|
|
@@ -91,10 +92,12 @@ Name: <agent role>
|
|
|
91
92
|
Все рабочие операции проходят через `Agile Manager Agent` + `TrackerGateway`.
|
|
92
93
|
Операционные шаблоны команд: [tracker-command-template.md](./tracker-command-template.md).
|
|
93
94
|
|
|
95
|
+
0. `VERIFY_GOVERNANCE_GATE`
|
|
94
96
|
1. `CREATE_TASK`
|
|
95
97
|
2. `SET_STATUS`
|
|
96
|
-
3. `
|
|
97
|
-
4. `
|
|
98
|
+
3. `RUN_REVIEW_GATE`
|
|
99
|
+
4. `COMMIT_BY_NAME`
|
|
100
|
+
5. `ASSIGN_SPRINT`
|
|
98
101
|
|
|
99
102
|
## 10) Коммиты и закрытие задач: только по подтверждению пользователя
|
|
100
103
|
Запрещено выполнять автоматически:
|
|
@@ -102,9 +105,10 @@ Name: <agent role>
|
|
|
102
105
|
- перевод задачи в `DONE`.
|
|
103
106
|
|
|
104
107
|
Обязательное правило:
|
|
105
|
-
- `COMMIT_BY_NAME` выполняется только после явного подтверждения пользователя в текущем диалоге;
|
|
108
|
+
- `COMMIT_BY_NAME` выполняется только после `RUN_REVIEW_GATE: PASS` и явного подтверждения пользователя в текущем диалоге;
|
|
106
109
|
- `SET_STATUS -> DONE` выполняется только после явного подтверждения пользователя в текущем диалоге;
|
|
107
110
|
- без подтверждения пользователя максимум допустимого статуса: `READY`.
|
|
111
|
+
- сообщение коммита обязано содержать ссылку на задачу (`TASK-ID` и/или `#issue-number`).
|
|
108
112
|
|
|
109
113
|
## 11) Жёсткие критерии приёмки (все обязательны)
|
|
110
114
|
Задача принимается только если одновременно выполнены все условия:
|
|
@@ -117,6 +121,9 @@ Name: <agent role>
|
|
|
117
121
|
7. Синхронизированы `task/status/sprint` в трекере.
|
|
118
122
|
8. Если был коммит, есть явное подтверждение пользователя на коммит.
|
|
119
123
|
9. Если задача закрыта в `DONE`, есть явное подтверждение пользователя на закрытие.
|
|
124
|
+
10. Перед каждой командой пройден `VERIFY_GOVERNANCE_GATE` от `Governance Watchdog Agent`.
|
|
125
|
+
11. Перед коммитом пройден `RUN_REVIEW_GATE` от `Reviewer/Judge Agent`.
|
|
126
|
+
12. Коммит содержит ссылку на issue/task (`TASK-ID` или `#issue`).
|
|
120
127
|
|
|
121
128
|
Если хотя бы один критерий не выполнен, задача не принимается.
|
|
122
129
|
|
package/template/package.json
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
|
-
"meta:status": "node .meta-agents/scripts/sync-status.mjs"
|
|
6
|
+
"meta:status": "node .meta-agents/scripts/sync-status.mjs",
|
|
7
|
+
"meta:verify": "node .meta-agents/scripts/verify-governance.mjs",
|
|
8
|
+
"meta:review": "node .meta-agents/scripts/run-review-gate.mjs",
|
|
9
|
+
"meta:verify-link": "node .meta-agents/scripts/verify-commit-link.mjs"
|
|
7
10
|
}
|
|
8
11
|
}
|
|
@@ -14,6 +14,25 @@ Name: <agent role>
|
|
|
14
14
|
|
|
15
15
|
Без этого префикса выполнение команды запрещено.
|
|
16
16
|
|
|
17
|
+
## 0.1) Обязательный governance gate
|
|
18
|
+
Перед любой командой сначала выполняется проверка:
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
[Agent Auto-Select]
|
|
22
|
+
Selected: Governance Watchdog Agent
|
|
23
|
+
Reason: Обязательная проверка соблюдения PRD и критериев приёмки перед операцией.
|
|
24
|
+
|
|
25
|
+
[Task Agent]
|
|
26
|
+
Name: Governance Watchdog Agent
|
|
27
|
+
|
|
28
|
+
Governance Watchdog Agent: verify governance gate,
|
|
29
|
+
task <TASK-ID>,
|
|
30
|
+
required checks "prd_sections_complete, acceptance_defined, user_confirmation_policy_respected",
|
|
31
|
+
result PASS
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Если `result != PASS`, команда не выполняется.
|
|
35
|
+
|
|
17
36
|
## 1) Ключевое правило подтверждения пользователя
|
|
18
37
|
Только по явному подтверждению пользователя в текущем диалоге разрешены:
|
|
19
38
|
- `COMMIT_BY_NAME`;
|
|
@@ -21,7 +40,42 @@ Name: <agent role>
|
|
|
21
40
|
|
|
22
41
|
Без подтверждения пользователя можно переводить задачу максимум в `READY`.
|
|
23
42
|
|
|
43
|
+
Дополнительно для коммита:
|
|
44
|
+
- `COMMIT_BY_NAME` разрешён только после `RUN_REVIEW_GATE` с результатом `PASS`;
|
|
45
|
+
- сообщение коммита обязательно содержит `TASK-ID` и/или `#issue-number`.
|
|
46
|
+
|
|
24
47
|
## 2) Канонические команды (через Agile Manager Agent)
|
|
48
|
+
### VERIFY_GOVERNANCE_GATE
|
|
49
|
+
```text
|
|
50
|
+
[Agent Auto-Select]
|
|
51
|
+
Selected: Governance Watchdog Agent
|
|
52
|
+
Reason: Нужна обязательная preflight-проверка процесса.
|
|
53
|
+
|
|
54
|
+
[Task Agent]
|
|
55
|
+
Name: Governance Watchdog Agent
|
|
56
|
+
|
|
57
|
+
Governance Watchdog Agent: verify governance gate,
|
|
58
|
+
task DEV-12,
|
|
59
|
+
checklist "PRD(Описание+Проверяемость), hard criteria, user confirmation policy",
|
|
60
|
+
result PASS
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### RUN_REVIEW_GATE (обязателен перед коммитом)
|
|
64
|
+
```text
|
|
65
|
+
[Agent Auto-Select]
|
|
66
|
+
Selected: Reviewer/Judge Agent
|
|
67
|
+
Reason: Нужен обязательный pre-commit review.
|
|
68
|
+
|
|
69
|
+
[Task Agent]
|
|
70
|
+
Name: Reviewer/Judge Agent
|
|
71
|
+
|
|
72
|
+
Reviewer/Judge Agent: run review gate,
|
|
73
|
+
task DEV-12,
|
|
74
|
+
checklist "what_done_summary, critical_findings, potential_risks, issue_link_presence",
|
|
75
|
+
result PASS,
|
|
76
|
+
report "posted to issue #12"
|
|
77
|
+
```
|
|
78
|
+
|
|
25
79
|
### CREATE_TASK
|
|
26
80
|
```text
|
|
27
81
|
[Agent Auto-Select]
|
|
@@ -72,6 +126,8 @@ Commit Approved: yes
|
|
|
72
126
|
Agile Manager Agent: commit by name,
|
|
73
127
|
tracker github,
|
|
74
128
|
task "API редирект офферов",
|
|
129
|
+
issue 12,
|
|
130
|
+
commit message "DEV-12 | API редирект офферов (#12)",
|
|
75
131
|
target status READY,
|
|
76
132
|
what done "добавлен endpoint, тесты, обработка ошибок"
|
|
77
133
|
```
|
|
@@ -130,9 +186,11 @@ sprint SPRINT-3
|
|
|
130
186
|
```
|
|
131
187
|
|
|
132
188
|
## 4) Минимальный операционный цикл
|
|
133
|
-
1. `
|
|
134
|
-
2. `
|
|
135
|
-
3.
|
|
136
|
-
4.
|
|
137
|
-
5. `
|
|
138
|
-
6. `
|
|
189
|
+
1. `VERIFY_GOVERNANCE_GATE`.
|
|
190
|
+
2. `CREATE_TASK`.
|
|
191
|
+
3. `SET_STATUS -> IN_PROGRESS`.
|
|
192
|
+
4. Реализация + evidence.
|
|
193
|
+
5. `RUN_REVIEW_GATE` (`PASS` обязателен).
|
|
194
|
+
6. `COMMIT_BY_NAME` только после review PASS и подтверждения пользователя.
|
|
195
|
+
7. `SET_STATUS -> READY`.
|
|
196
|
+
8. `SET_STATUS -> DONE` только после подтверждения пользователя.
|
|
@@ -14,6 +14,25 @@ Name: <agent role>
|
|
|
14
14
|
|
|
15
15
|
Без этого префикса выполнение команды запрещено.
|
|
16
16
|
|
|
17
|
+
## 0.1) Обязательный governance gate
|
|
18
|
+
Перед любой командой сначала выполняется проверка:
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
[Agent Auto-Select]
|
|
22
|
+
Selected: Governance Watchdog Agent
|
|
23
|
+
Reason: Обязательная проверка соблюдения PRD и критериев приёмки перед операцией.
|
|
24
|
+
|
|
25
|
+
[Task Agent]
|
|
26
|
+
Name: Governance Watchdog Agent
|
|
27
|
+
|
|
28
|
+
Governance Watchdog Agent: verify governance gate,
|
|
29
|
+
task <TASK-ID>,
|
|
30
|
+
required checks "prd_sections_complete, acceptance_defined, user_confirmation_policy_respected",
|
|
31
|
+
result PASS
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Если `result != PASS`, команда не выполняется.
|
|
35
|
+
|
|
17
36
|
## 1) Ключевое правило подтверждения пользователя
|
|
18
37
|
Только по явному подтверждению пользователя в текущем диалоге разрешены:
|
|
19
38
|
- `COMMIT_BY_NAME`;
|
|
@@ -21,7 +40,42 @@ Name: <agent role>
|
|
|
21
40
|
|
|
22
41
|
Без подтверждения пользователя можно переводить задачу максимум в `READY`.
|
|
23
42
|
|
|
43
|
+
Дополнительно для коммита:
|
|
44
|
+
- `COMMIT_BY_NAME` разрешён только после `RUN_REVIEW_GATE` с результатом `PASS`;
|
|
45
|
+
- сообщение коммита обязательно содержит `TASK-ID` и/или `#issue-number`.
|
|
46
|
+
|
|
24
47
|
## 2) Канонические команды (через Agile Manager Agent)
|
|
48
|
+
### VERIFY_GOVERNANCE_GATE
|
|
49
|
+
```text
|
|
50
|
+
[Agent Auto-Select]
|
|
51
|
+
Selected: Governance Watchdog Agent
|
|
52
|
+
Reason: Нужна обязательная preflight-проверка процесса.
|
|
53
|
+
|
|
54
|
+
[Task Agent]
|
|
55
|
+
Name: Governance Watchdog Agent
|
|
56
|
+
|
|
57
|
+
Governance Watchdog Agent: verify governance gate,
|
|
58
|
+
task DEV-12,
|
|
59
|
+
checklist "PRD(Описание+Проверяемость), hard criteria, user confirmation policy",
|
|
60
|
+
result PASS
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### RUN_REVIEW_GATE (обязателен перед коммитом)
|
|
64
|
+
```text
|
|
65
|
+
[Agent Auto-Select]
|
|
66
|
+
Selected: Reviewer/Judge Agent
|
|
67
|
+
Reason: Нужен обязательный pre-commit review.
|
|
68
|
+
|
|
69
|
+
[Task Agent]
|
|
70
|
+
Name: Reviewer/Judge Agent
|
|
71
|
+
|
|
72
|
+
Reviewer/Judge Agent: run review gate,
|
|
73
|
+
task DEV-12,
|
|
74
|
+
checklist "what_done_summary, critical_findings, potential_risks, issue_link_presence",
|
|
75
|
+
result PASS,
|
|
76
|
+
report "posted to issue #12"
|
|
77
|
+
```
|
|
78
|
+
|
|
25
79
|
### CREATE_TASK
|
|
26
80
|
```text
|
|
27
81
|
[Agent Auto-Select]
|
|
@@ -72,6 +126,8 @@ Commit Approved: yes
|
|
|
72
126
|
Agile Manager Agent: commit by name,
|
|
73
127
|
tracker github,
|
|
74
128
|
task "API редирект офферов",
|
|
129
|
+
issue 12,
|
|
130
|
+
commit message "DEV-12 | API редирект офферов (#12)",
|
|
75
131
|
target status READY,
|
|
76
132
|
what done "добавлен endpoint, тесты, обработка ошибок"
|
|
77
133
|
```
|
|
@@ -130,9 +186,11 @@ sprint SPRINT-3
|
|
|
130
186
|
```
|
|
131
187
|
|
|
132
188
|
## 4) Минимальный операционный цикл
|
|
133
|
-
1. `
|
|
134
|
-
2. `
|
|
135
|
-
3.
|
|
136
|
-
4.
|
|
137
|
-
5. `
|
|
138
|
-
6. `
|
|
189
|
+
1. `VERIFY_GOVERNANCE_GATE`.
|
|
190
|
+
2. `CREATE_TASK`.
|
|
191
|
+
3. `SET_STATUS -> IN_PROGRESS`.
|
|
192
|
+
4. Реализация + evidence.
|
|
193
|
+
5. `RUN_REVIEW_GATE` (`PASS` обязателен).
|
|
194
|
+
6. `COMMIT_BY_NAME` только после review PASS и подтверждения пользователя.
|
|
195
|
+
7. `SET_STATUS -> READY`.
|
|
196
|
+
8. `SET_STATUS -> DONE` только после подтверждения пользователя.
|