@k0t0vich/meta-agents-template 0.1.0 → 0.1.2
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 +45 -29
- package/agents.md +33 -4
- package/package.json +5 -2
- package/src/sync.mjs +85 -0
- package/template/.meta-agents/config/roles.yaml +6 -2
- package/template/.meta-agents/config/system.yaml +86 -1
- package/template/.meta-agents/config/trackers.yaml +11 -0
- package/template/.meta-agents/prompts/agile-manager.md +2 -0
- package/template/.meta-agents/prompts/clarifier.md +1 -0
- package/template/.meta-agents/prompts/governance-watchdog.md +3 -0
- package/template/.meta-agents/prompts/publishing-agent.md +7 -0
- package/template/.meta-agents/prompts/reviewer-judge.md +5 -1
- package/template/.meta-agents/scripts/run-review-gate.mjs +151 -0
- package/template/.meta-agents/scripts/verify-commit-link.mjs +50 -0
- package/template/.meta-agents/scripts/verify-governance.mjs +74 -0
- package/template/.meta-agents/templates/agent-work-contract.md +2 -0
- package/template/.meta-agents/templates/task-template.md +3 -1
- package/template/README.md +21 -1
- package/template/agents.md +36 -4
- package/template/package.json +5 -1
- package/template/tracker-command-template.md +214 -8
- package/tracker-command-template.md +180 -7
package/README.md
CHANGED
|
@@ -56,6 +56,7 @@ my-project/
|
|
|
56
56
|
decomposer.md
|
|
57
57
|
reviewer-judge.md
|
|
58
58
|
agile-manager.md
|
|
59
|
+
publishing-agent.md
|
|
59
60
|
scripts/
|
|
60
61
|
init.mjs
|
|
61
62
|
sync-status.mjs
|
|
@@ -72,10 +73,30 @@ my-project/
|
|
|
72
73
|
```
|
|
73
74
|
|
|
74
75
|
## Канонические команды
|
|
76
|
+
0. `VERIFY_GOVERNANCE_GATE`
|
|
75
77
|
1. `CREATE_TASK`
|
|
76
78
|
2. `SET_STATUS`
|
|
77
|
-
3. `
|
|
78
|
-
4. `
|
|
79
|
+
3. `RUN_REVIEW_GATE`
|
|
80
|
+
4. `COMMIT_BY_NAME`
|
|
81
|
+
5. `ASSIGN_SPRINT`
|
|
82
|
+
6. `PREPARE_RELEASE_NOTE`
|
|
83
|
+
7. `MARK_TASKS_PUBLISH`
|
|
84
|
+
|
|
85
|
+
`VERIFY_GOVERNANCE_GATE` выполняет `Governance Watchdog Agent` перед любой операцией и блокирует выполнение при нарушении PRD/acceptance/user-confirmation правил.
|
|
86
|
+
`RUN_REVIEW_GATE` выполняет `Reviewer/Judge Agent` перед коммитом:
|
|
87
|
+
- сначала выводит summary выполненного, критические замечания, потенциальные риски и рекомендацию `PASS_CANDIDATE/FAIL`;
|
|
88
|
+
- финальный `PASS_CONFIRMED` допускается только после явного `Review Approved: yes` от пользователя.
|
|
89
|
+
|
|
90
|
+
## Self-bootstrap (для этого репозитория)
|
|
91
|
+
Чтобы сам шаблон работал по своим же правилам, запусти:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm run self:bootstrap
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Команда разворачивает шаблонные управляемые файлы в текущий репозиторий, создаёт стартовую задачу с PRD (`AGT-SELF-001`) и заполняет backlog/sprint/status-log.
|
|
98
|
+
|
|
99
|
+
Локальные рабочие артефакты `tasks/` и `.meta-agents/` добавлены в `.gitignore`, чтобы не засорять публикационный пакет.
|
|
79
100
|
|
|
80
101
|
## Жёсткие критерии приёмки
|
|
81
102
|
Задача принимается только если одновременно выполнены все условия:
|
|
@@ -86,41 +107,36 @@ my-project/
|
|
|
86
107
|
5. Пройдены обязательные `human` approvals.
|
|
87
108
|
6. Собран полный evidence-пакет.
|
|
88
109
|
7. Синхронизированы `task/status/sprint` в трекере.
|
|
110
|
+
8. Перед каждой командой пройден watchdog gate (`VERIFY_GOVERNANCE_GATE`).
|
|
111
|
+
9. Перед коммитом пройден review gate (`RUN_REVIEW_GATE`) с финальным `PASS_CONFIRMED`.
|
|
112
|
+
10. Есть отдельное явное подтверждение пользователя на прохождение review (`Review Approved: yes`).
|
|
113
|
+
11. Каждый коммит связан с issue/task (`TASK-ID` и/или `#issue` в commit message).
|
|
89
114
|
|
|
90
115
|
Если хотя бы один пункт не выполнен, задача не принимается.
|
|
91
116
|
|
|
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. Сохрани настройки.
|
|
117
|
+
## Локальная проверка governance
|
|
118
|
+
В сгенерированном проекте доступна команда:
|
|
112
119
|
|
|
113
|
-
Как выпускать релиз:
|
|
114
120
|
```bash
|
|
115
|
-
|
|
116
|
-
|
|
121
|
+
npm run meta:verify
|
|
122
|
+
npm run meta:review
|
|
123
|
+
npm run meta:review-approve
|
|
124
|
+
npm run meta:verify-link
|
|
117
125
|
```
|
|
118
126
|
|
|
119
|
-
|
|
127
|
+
Она проверяет наличие обязательных PRD-блоков в задачах (`Описание`, `Проверяемость`, `Что сделано`) и валидирует базовую процессную дисциплину.
|
|
120
128
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
-
|
|
129
|
+
## Правило диалога пользователя
|
|
130
|
+
Коммиты и закрытие задач выполняются только по явному подтверждению пользователя в текущем диалоге:
|
|
131
|
+
- `COMMIT_BY_NAME` — только после подтверждения пользователя;
|
|
132
|
+
- перевод задачи в `DONE` — только после подтверждения пользователя;
|
|
133
|
+
- в single-branch режиме статусный цикл: `TODO -> IN_PROGRESS -> REVIEW -> READY -> DONE` (для релизных задач дополнительно `-> PUBLISH`);
|
|
134
|
+
- без подтверждения максимум статуса: `REVIEW`;
|
|
135
|
+
- `READY` разрешён только после `RUN_REVIEW_GATE: PASS_CONFIRMED`.
|
|
136
|
+
- `READY` означает commit + push (в `main` или в ветку с открытым MR/PR);
|
|
137
|
+
- `DONE` означает интеграцию в `main` (direct commit или merged MR/PR);
|
|
138
|
+
- `PUBLISH` означает, что релиз опубликован и доступен в latest.
|
|
139
|
+
- для большой фичи (в режиме GitHub tracker) агент обязан предложить `feature issue` + `epic issue` и отдельную ветку.
|
|
124
140
|
|
|
125
141
|
## Основные документы шаблона
|
|
126
142
|
- [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,26 @@ Name: <agent role>
|
|
|
102
105
|
- перевод задачи в `DONE`.
|
|
103
106
|
|
|
104
107
|
Обязательное правило:
|
|
105
|
-
- `
|
|
108
|
+
- для single-branch режима статусный цикл задачи фиксируется как `TODO -> IN_PROGRESS -> REVIEW -> READY -> DONE` (для релизных задач дополнительно `-> PUBLISH`);
|
|
109
|
+
- `RUN_REVIEW_GATE` сначала формирует отчёт ревьювера и рекомендацию (`PASS_CANDIDATE`/`FAIL`);
|
|
110
|
+
- финальный `RUN_REVIEW_GATE: PASS_CONFIRMED` допускается только после явного подтверждения пользователя `Review Approved: yes`;
|
|
111
|
+
- `COMMIT_BY_NAME` выполняется только после `RUN_REVIEW_GATE: PASS_CONFIRMED` и отдельного явного подтверждения пользователя в текущем диалоге;
|
|
106
112
|
- `SET_STATUS -> DONE` выполняется только после явного подтверждения пользователя в текущем диалоге;
|
|
107
|
-
- без подтверждения пользователя максимум допустимого статуса: `
|
|
113
|
+
- без подтверждения пользователя максимум допустимого статуса: `REVIEW`.
|
|
114
|
+
- `SET_STATUS -> READY` разрешён только после `RUN_REVIEW_GATE: PASS_CONFIRMED`.
|
|
115
|
+
- сообщение коммита обязано содержать ссылку на задачу (`TASK-ID` и/или `#issue-number`).
|
|
116
|
+
- `READY` означает: коммит сделан и отправлен (`push`), при этом либо в `main`, либо в отдельной ветке с открытым MR/PR.
|
|
117
|
+
- `DONE` означает: изменения интегрированы в `main` (прямой коммит в `main` или MR/PR смержен).
|
|
118
|
+
- `PUBLISH` означает: релиз опубликован и доступен в последней версии пакета.
|
|
119
|
+
|
|
120
|
+
## 10.1) Правило для больших фич (GitHub tracker)
|
|
121
|
+
Если задача классифицирована как большая фича, система обязана предложить:
|
|
122
|
+
- создать `feature issue` (`type:feature`);
|
|
123
|
+
- создать `epic issue` (`type:epic`);
|
|
124
|
+
- выделить отдельную ветку разработки;
|
|
125
|
+
- связать feature с epic в GitHub issue (ссылка в body/comment/task list).
|
|
126
|
+
|
|
127
|
+
Для текущего этапа (только GitHub tracker) epic реализуется как обычный issue с label `type:epic`.
|
|
108
128
|
|
|
109
129
|
## 11) Жёсткие критерии приёмки (все обязательны)
|
|
110
130
|
Задача принимается только если одновременно выполнены все условия:
|
|
@@ -117,6 +137,15 @@ Name: <agent role>
|
|
|
117
137
|
7. Синхронизированы `task/status/sprint` в трекере.
|
|
118
138
|
8. Если был коммит, есть явное подтверждение пользователя на коммит.
|
|
119
139
|
9. Если задача закрыта в `DONE`, есть явное подтверждение пользователя на закрытие.
|
|
140
|
+
10. Перед каждой командой пройден `VERIFY_GOVERNANCE_GATE` от `Governance Watchdog Agent`.
|
|
141
|
+
11. Перед коммитом пройден `RUN_REVIEW_GATE` от `Reviewer/Judge Agent`.
|
|
142
|
+
12. Есть явное подтверждение пользователя на прохождение review (`Review Approved: yes`).
|
|
143
|
+
13. До review gate задача переведена в статус `REVIEW`.
|
|
144
|
+
14. Статус `READY` выставлен только после `RUN_REVIEW_GATE: PASS_CONFIRMED`.
|
|
145
|
+
15. Для статуса `READY` подтверждены `commit + push` и путь интеграции (`main` или открытый MR/PR).
|
|
146
|
+
16. Для статуса `DONE` подтверждена интеграция в `main` (direct commit или merged MR/PR).
|
|
147
|
+
17. Для статуса `PUBLISH` подтверждена публикация в последней версии.
|
|
148
|
+
18. Коммит содержит ссылку на issue/task (`TASK-ID` или `#issue`).
|
|
120
149
|
|
|
121
150
|
Если хотя бы один критерий не выполнен, задача не принимается.
|
|
122
151
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k0t0vich/meta-agents-template",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
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",
|
|
13
|
+
"release:smoke-local": "node scripts/post-publish-local-smoke.mjs"
|
|
11
14
|
},
|
|
12
15
|
"files": [
|
|
13
16
|
"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
|
}
|
|
@@ -2,7 +2,9 @@ roles:
|
|
|
2
2
|
- name: "Chief of Staff Agent"
|
|
3
3
|
responsibility: "Оркестрация, блокеры, эскалации"
|
|
4
4
|
- name: "Agile Manager Agent"
|
|
5
|
-
responsibility: "CREATE_TASK/SET_STATUS/COMMIT_BY_NAME/ASSIGN_SPRINT"
|
|
5
|
+
responsibility: "CREATE_TASK/SET_STATUS/COMMIT_BY_NAME/ASSIGN_SPRINT + epic/feature orchestration in GitHub tracker"
|
|
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,8 @@ roles:
|
|
|
16
18
|
- name: "QA Agent"
|
|
17
19
|
responsibility: "Верификация и тестирование"
|
|
18
20
|
- name: "Reviewer/Judge Agent"
|
|
19
|
-
responsibility: "Независимая приёмка"
|
|
21
|
+
responsibility: "Независимая приёмка + обязательный pre-commit review gate"
|
|
22
|
+
- name: "Publishing Agent"
|
|
23
|
+
responsibility: "Подготовка release notes, публикация релиза, перевод вошедших задач в PUBLISH"
|
|
20
24
|
- name: "Documentation Agent"
|
|
21
25
|
responsibility: "Синхронизация документации"
|
|
@@ -23,9 +23,84 @@ system:
|
|
|
23
23
|
offer_create_github_repo: true
|
|
24
24
|
governance:
|
|
25
25
|
user_confirmation_required_for:
|
|
26
|
+
- review_gate_pass
|
|
26
27
|
- commit
|
|
27
28
|
- task_close_done
|
|
28
|
-
|
|
29
|
+
- release_publish
|
|
30
|
+
max_status_without_user_confirmation: REVIEW
|
|
31
|
+
status_lifecycle:
|
|
32
|
+
mode: single_branch
|
|
33
|
+
sequence:
|
|
34
|
+
- TODO
|
|
35
|
+
- IN_PROGRESS
|
|
36
|
+
- REVIEW
|
|
37
|
+
- READY
|
|
38
|
+
- DONE
|
|
39
|
+
- PUBLISH
|
|
40
|
+
rules:
|
|
41
|
+
- ready_only_after_review_pass_confirmed
|
|
42
|
+
- done_only_after_user_confirmation
|
|
43
|
+
- publish_only_after_done
|
|
44
|
+
github_status_labels:
|
|
45
|
+
- TODO
|
|
46
|
+
- IN_PROGRESS
|
|
47
|
+
- REVIEW
|
|
48
|
+
- READY
|
|
49
|
+
- BLOCKED
|
|
50
|
+
- DONE
|
|
51
|
+
- PUBLISH
|
|
52
|
+
semantics:
|
|
53
|
+
READY: "Commit created and pushed; either main branch commit or feature branch with open MR/PR."
|
|
54
|
+
DONE: "Changes integrated to main (direct commit on main or MR/PR merged)."
|
|
55
|
+
PUBLISH: "Released and available in latest published package version."
|
|
56
|
+
epic_policy:
|
|
57
|
+
github_only: true
|
|
58
|
+
large_feature_requires_epic: true
|
|
59
|
+
required_actions:
|
|
60
|
+
- propose_feature_issue
|
|
61
|
+
- propose_epic_issue
|
|
62
|
+
- create_dedicated_branch
|
|
63
|
+
- link_feature_to_epic
|
|
64
|
+
watchdog:
|
|
65
|
+
required: true
|
|
66
|
+
before_commands:
|
|
67
|
+
- VERIFY_GOVERNANCE_GATE
|
|
68
|
+
- CREATE_TASK
|
|
69
|
+
- SET_STATUS
|
|
70
|
+
- RUN_REVIEW_GATE
|
|
71
|
+
- COMMIT_BY_NAME
|
|
72
|
+
- ASSIGN_SPRINT
|
|
73
|
+
- PREPARE_RELEASE_NOTE
|
|
74
|
+
- MARK_TASKS_PUBLISH
|
|
75
|
+
minimum_checks:
|
|
76
|
+
- prd_sections_complete
|
|
77
|
+
- acceptance_criteria_defined
|
|
78
|
+
- user_confirmation_policy_respected
|
|
79
|
+
review_gate:
|
|
80
|
+
required_before_commit: true
|
|
81
|
+
command: RUN_REVIEW_GATE
|
|
82
|
+
reporter_role: "Reviewer/Judge Agent"
|
|
83
|
+
required_user_acknowledgement: true
|
|
84
|
+
recommendation_statuses:
|
|
85
|
+
- PASS_CANDIDATE
|
|
86
|
+
- FAIL
|
|
87
|
+
final_status: PASS_CONFIRMED
|
|
88
|
+
required_sections:
|
|
89
|
+
- what_done_summary
|
|
90
|
+
- critical_findings
|
|
91
|
+
- potential_risks
|
|
92
|
+
- recommendation_pass_or_fail
|
|
93
|
+
block_on_critical: true
|
|
94
|
+
commit_linkage:
|
|
95
|
+
required: true
|
|
96
|
+
accepted_patterns:
|
|
97
|
+
- "TASK-ID"
|
|
98
|
+
- "#issue"
|
|
99
|
+
publish_flow:
|
|
100
|
+
release_note_required: true
|
|
101
|
+
release_note_must_include_tasks: true
|
|
102
|
+
mark_included_tasks_publish: true
|
|
103
|
+
publish_status_label: PUBLISH
|
|
29
104
|
acceptance:
|
|
30
105
|
hard_criteria:
|
|
31
106
|
- prd_sections_complete
|
|
@@ -35,6 +110,16 @@ system:
|
|
|
35
110
|
- human_approvals_passed
|
|
36
111
|
- evidence_pack_complete
|
|
37
112
|
- tracker_sync_complete
|
|
113
|
+
- watchdog_gate_passed
|
|
114
|
+
- review_gate_passed
|
|
115
|
+
- review_user_acknowledged
|
|
116
|
+
- ready_has_commit_and_push
|
|
117
|
+
- done_integrated_to_main
|
|
118
|
+
- release_note_created
|
|
119
|
+
- release_note_includes_tasks
|
|
120
|
+
- release_tasks_marked_publish
|
|
121
|
+
- publish_released_latest
|
|
122
|
+
- commit_linked_to_issue
|
|
38
123
|
auto_select:
|
|
39
124
|
required: true
|
|
40
125
|
before_each_task: true
|
|
@@ -4,6 +4,17 @@ tracker_gateway:
|
|
|
4
4
|
github:
|
|
5
5
|
mode: "issues_projects"
|
|
6
6
|
enabled: true
|
|
7
|
+
status_labels:
|
|
8
|
+
- TODO
|
|
9
|
+
- IN_PROGRESS
|
|
10
|
+
- REVIEW
|
|
11
|
+
- READY
|
|
12
|
+
- BLOCKED
|
|
13
|
+
- DONE
|
|
14
|
+
- PUBLISH
|
|
15
|
+
hierarchy_labels:
|
|
16
|
+
epic: "type:epic"
|
|
17
|
+
feature: "type:feature"
|
|
7
18
|
mcp:
|
|
8
19
|
mode: "external_tracker_via_mcp"
|
|
9
20
|
enabled: true
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
Role: Agile Manager Agent
|
|
2
2
|
Goal: управлять задачами и статусами через TrackerGateway.
|
|
3
3
|
Commands: CREATE_TASK, SET_STATUS, COMMIT_BY_NAME, ASSIGN_SPRINT.
|
|
4
|
+
Status semantics: READY = commit+push; DONE = integrated to main; PUBLISH = published in latest version.
|
|
5
|
+
Rule: для большой фичи в GitHub tracker сначала предложить связку `feature issue` + `epic issue` и выделенную ветку.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
Role: Clarifier Agent
|
|
2
2
|
Goal: выявить цель, ограничения, неоднозначности и критерии успеха.
|
|
3
|
+
Rule: если задача классифицируется как большая фича, обязательно предложить создать `feature issue` и `epic issue` в GitHub tracker, а также отдельную ветку.
|
|
3
4
|
Output: PRD Step с заполненными "Описание" и "Проверяемость".
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Role: Publishing Agent
|
|
2
|
+
Goal: подготовить релиз, зафиксировать release notes и перевести вошедшие задачи в статус PUBLISH.
|
|
3
|
+
Rule:
|
|
4
|
+
- перед публикацией создать release note со списком issue/tasks, вошедших в релиз;
|
|
5
|
+
- после подтверждённой публикации обновить статусы всех вошедших задач на `PUBLISH` в GitHub tracker;
|
|
6
|
+
- для каждого релиза оставлять ссылку на release note и версию.
|
|
7
|
+
Output: release note path + список задач + подтверждение обновления статусов.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
Role: Reviewer/Judge Agent
|
|
2
|
-
Goal: независимая приёмка по
|
|
2
|
+
Goal: независимая приёмка по критериям и обязательный pre-commit review gate.
|
|
3
|
+
Output format: что сделано, критические замечания, потенциальные риски, рекомендация PASS_CANDIDATE/FAIL.
|
|
4
|
+
Rule: финальный PASS_CONFIRMED только после явного `Review Approved: yes` от пользователя.
|
|
5
|
+
Status rule: перед review gate задача должна быть в статусе `REVIEW`; статус `READY` выставляется только после `PASS_CONFIRMED`.
|
|
6
|
+
Delivery rule: `READY` требует commit+push; `DONE` требует интеграцию в `main`; `PUBLISH` только после фактической публикации.
|
|
3
7
|
Output: accepted/rejected + findings.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
|
|
5
|
+
function parseArgs(argv) {
|
|
6
|
+
const options = {
|
|
7
|
+
approve: false,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
11
|
+
const arg = argv[index];
|
|
12
|
+
if (arg === "--approve") {
|
|
13
|
+
const value = (argv[index + 1] || "").trim().toLowerCase();
|
|
14
|
+
options.approve = value === "yes" || value === "true" || value === "1";
|
|
15
|
+
index += 1;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return options;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function git(args, allowFailure = false) {
|
|
23
|
+
try {
|
|
24
|
+
const output = execFileSync("git", args, { encoding: "utf8" });
|
|
25
|
+
return output.trim();
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if (allowFailure) {
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function splitLines(value) {
|
|
35
|
+
if (!value) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return value
|
|
39
|
+
.split("\n")
|
|
40
|
+
.map((line) => line.trim())
|
|
41
|
+
.filter(Boolean);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function matchTestFile(filePath) {
|
|
45
|
+
return /(^|\/)(tests?|__tests__)\//i.test(filePath) || /\.(test|spec)\.[cm]?[jt]sx?$/i.test(filePath);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function scanMarkers(files) {
|
|
49
|
+
const markers = [];
|
|
50
|
+
// Match common marker formats while ignoring status arrows in workflow lines.
|
|
51
|
+
const pattern = /\b(TODO|FIXME|XXX|HACK)\b\s*(?::|-(?!>))/;
|
|
52
|
+
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
try {
|
|
55
|
+
const content = await fs.readFile(path.resolve(process.cwd(), file), "utf8");
|
|
56
|
+
const lines = content.split("\n");
|
|
57
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
58
|
+
const line = lines[index];
|
|
59
|
+
if (pattern.test(line)) {
|
|
60
|
+
markers.push(`${file}:${index + 1} -> ${line.trim()}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch {
|
|
64
|
+
// Skip binary/unreadable files.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return markers;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function main() {
|
|
72
|
+
const options = parseArgs(process.argv.slice(2));
|
|
73
|
+
const stagedFiles = splitLines(git(["diff", "--cached", "--name-only"], true));
|
|
74
|
+
const recentFiles = splitLines(git(["show", "--name-only", "--pretty=", "HEAD"], true));
|
|
75
|
+
const files = stagedFiles.length > 0 ? stagedFiles : recentFiles;
|
|
76
|
+
|
|
77
|
+
if (files.length === 0) {
|
|
78
|
+
console.log("Review Gate FAIL");
|
|
79
|
+
console.log("- reason: no staged or recent changes detected");
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const critical = [];
|
|
84
|
+
const risks = [];
|
|
85
|
+
|
|
86
|
+
const markers = await scanMarkers(files);
|
|
87
|
+
if (markers.length > 0) {
|
|
88
|
+
critical.push(...markers.slice(0, 20));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const sourceTouched = files.some((file) => file.startsWith("src/") || file.startsWith("template/"));
|
|
92
|
+
const testsTouched = files.some((file) => matchTestFile(file));
|
|
93
|
+
if (sourceTouched && !testsTouched) {
|
|
94
|
+
risks.push("Source/template changes detected without explicit test changes.");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log("# Review Gate Report");
|
|
98
|
+
console.log("");
|
|
99
|
+
console.log("## Что сделано");
|
|
100
|
+
for (const file of files) {
|
|
101
|
+
console.log(`- changed: ${file}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log("");
|
|
105
|
+
console.log("## Критические замечания");
|
|
106
|
+
if (critical.length === 0) {
|
|
107
|
+
console.log("- none");
|
|
108
|
+
} else {
|
|
109
|
+
for (const item of critical) {
|
|
110
|
+
console.log(`- ${item}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log("");
|
|
115
|
+
console.log("## Потенциальные риски");
|
|
116
|
+
if (risks.length === 0) {
|
|
117
|
+
console.log("- none");
|
|
118
|
+
} else {
|
|
119
|
+
for (const item of risks) {
|
|
120
|
+
console.log(`- ${item}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log("");
|
|
125
|
+
console.log("## Рекомендация ревьювера");
|
|
126
|
+
console.log(critical.length === 0 ? "- PASS_CANDIDATE" : "- FAIL");
|
|
127
|
+
|
|
128
|
+
if (critical.length > 0) {
|
|
129
|
+
console.log("");
|
|
130
|
+
console.log("## Решение");
|
|
131
|
+
console.log("- FAIL");
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
console.log("");
|
|
136
|
+
if (!options.approve) {
|
|
137
|
+
console.log("## Решение");
|
|
138
|
+
console.log("- PENDING_USER_CONFIRMATION");
|
|
139
|
+
console.log("- Требуется явное подтверждение пользователя: Review Approved = yes");
|
|
140
|
+
process.exit(2);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
console.log("## Решение");
|
|
144
|
+
console.log("- PASS_CONFIRMED");
|
|
145
|
+
process.exit(0);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
main().catch((error) => {
|
|
149
|
+
console.error(`Review Gate FAIL: ${error.message}`);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
});
|