@k0t0vich/meta-agents-template 0.1.11 → 0.1.12
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/CHANGELOG.md +15 -0
- package/package.json +1 -1
- package/template/.meta-agents/config/system.yaml +29 -0
- package/template/.meta-agents/prompts/agile-manager.md +3 -0
- package/template/.meta-agents/prompts/clarifier.md +2 -0
- package/template/.meta-agents/prompts/governance-watchdog.md +2 -0
- package/template/.meta-agents/prompts/reviewer-judge.md +1 -0
- package/template/.meta-agents/prompts/verifier-designer.md +1 -0
- package/template/.meta-agents/scripts/tracker/github.mjs +121 -11
- package/template/.meta-agents/scripts/tracker-gateway.mjs +31 -1
- package/template/.meta-agents/scripts/verify-governance.mjs +215 -11
- package/template/.meta-agents/scripts/verify-implementation-gate.mjs +32 -9
- package/template/.meta-agents/templates/agent-work-contract.md +4 -0
- package/template/.meta-agents/templates/evidence-pack.md +4 -0
- package/template/.meta-agents/templates/prd-step.md +9 -0
- package/template/.meta-agents/templates/task-template.md +14 -1
- package/template/.meta-agents/templates/verification-plan.md +16 -5
- package/template/agents.md +30 -1
- package/template/tracker-command-template.md +35 -19
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this package are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.1.12 - 2026-03-20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Added hard docs-first law in canonical rules: no code before PRD + architecture + verification matrix.
|
|
9
|
+
- Added explicit scope-control rule: if dialogue exits current task scope, agent must propose creating a task or finishing current one before coding.
|
|
10
|
+
- Added mandatory verification matrix fields for task artifacts: `tests_unit`, `tests_system`, `tests_e2e_playwright`, `external_analysis`.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Upgraded `meta:ops` runtime flow to execute governance verification before operational commands.
|
|
14
|
+
- Expanded GitHub issue body validation for `SET_STATUS -> IN_PROGRESS` and implementation gate to require `Architecture`, `Verification Plan`, and extended verification rows.
|
|
15
|
+
- Updated governance prompts and templates to enforce docs-first execution discipline.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Eliminated policy/runtime gap where code-stage commands could start without task-scoped docs-first validation.
|
|
19
|
+
|
|
5
20
|
## 0.1.11 - 2026-03-20
|
|
6
21
|
|
|
7
22
|
### Added
|
package/package.json
CHANGED
|
@@ -62,6 +62,23 @@ system:
|
|
|
62
62
|
- local
|
|
63
63
|
- custom
|
|
64
64
|
require_provider_consistency: true
|
|
65
|
+
coding_law:
|
|
66
|
+
no_code_before_prd_and_verification: true
|
|
67
|
+
required_before_coding:
|
|
68
|
+
- prd_description_complete
|
|
69
|
+
- architecture_documented
|
|
70
|
+
- verification_matrix_complete
|
|
71
|
+
- tests_unit_defined
|
|
72
|
+
- tests_system_defined
|
|
73
|
+
- tests_e2e_playwright_defined
|
|
74
|
+
- external_analysis_defined
|
|
75
|
+
- implementation_gate_passed
|
|
76
|
+
dialogue_scope_control:
|
|
77
|
+
enabled: true
|
|
78
|
+
if_request_out_of_scope:
|
|
79
|
+
- propose_create_task
|
|
80
|
+
- or_finish_current_task
|
|
81
|
+
code_actions_blocked_until_scope_resolved: true
|
|
65
82
|
user_confirmation_required_for:
|
|
66
83
|
- review_gate_pass
|
|
67
84
|
- mr_review_gate_pass
|
|
@@ -173,8 +190,13 @@ system:
|
|
|
173
190
|
- MARK_TASKS_PUBLISH
|
|
174
191
|
minimum_checks:
|
|
175
192
|
- prd_sections_complete
|
|
193
|
+
- architecture_documented
|
|
194
|
+
- verification_matrix_complete
|
|
195
|
+
- tests_unit_system_playwright_defined
|
|
196
|
+
- external_analysis_defined
|
|
176
197
|
- acceptance_criteria_defined
|
|
177
198
|
- user_confirmation_policy_respected
|
|
199
|
+
- no_code_before_prd
|
|
178
200
|
review_gate:
|
|
179
201
|
required_before_commit: true
|
|
180
202
|
command: RUN_REVIEW_GATE
|
|
@@ -220,12 +242,19 @@ system:
|
|
|
220
242
|
acceptance:
|
|
221
243
|
hard_criteria:
|
|
222
244
|
- prd_sections_complete
|
|
245
|
+
- architecture_documented_before_coding
|
|
223
246
|
- auto_select_prefix_present
|
|
224
247
|
- strict_checks_passed
|
|
225
248
|
- statistical_thresholds_met
|
|
226
249
|
- human_approvals_passed
|
|
250
|
+
- verification_matrix_contains_unit_tests
|
|
251
|
+
- verification_matrix_contains_system_tests
|
|
252
|
+
- verification_matrix_contains_e2e_playwright
|
|
253
|
+
- external_agent_analysis_completed_for_key_tasks
|
|
254
|
+
- no_code_changes_before_implementation_gate_pass
|
|
227
255
|
- evidence_pack_complete
|
|
228
256
|
- tracker_sync_complete
|
|
257
|
+
- out_of_scope_dialogue_requires_task_decision
|
|
229
258
|
- branch_routing_dialog_completed
|
|
230
259
|
- implementation_gate_passed
|
|
231
260
|
- branch_routing_e2e_verified
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Role: Agile Manager Agent
|
|
2
2
|
Goal: управлять задачами и статусами через TrackerGateway.
|
|
3
3
|
Commands: CREATE_TASK, SET_STATUS, COMMIT_BY_NAME, ASSIGN_SPRINT.
|
|
4
|
+
Law: не начинать кодовые изменения до PASS по docs-first gate (`PRD + Architecture + Verification Plan + tests_unit/tests_system/tests_e2e_playwright/external_analysis`).
|
|
4
5
|
Status semantics: READY = commit+push on feature/release/hotfix + open PR; DONE = integrated to main + back-merge to develop (release/hotfix); PUBLISH = published in latest version.
|
|
5
6
|
Git Flow Lite rule: использовать `feature/* -> develop`, `release/* -> main` + back-merge, `hotfix/* -> main` + back-merge.
|
|
6
7
|
Rule: для большой фичи в GitHub tracker сначала предложить связку `feature issue` + `epic issue` и выделенную ветку.
|
|
@@ -25,3 +26,5 @@ Task ref naming rule:
|
|
|
25
26
|
Pre-merge rule:
|
|
26
27
|
- после commit+push и открытия PR обязательно выполнить `RUN_MR_REVIEW_GATE`;
|
|
27
28
|
- merge допускается только после `RUN_MR_REVIEW_GATE: PASS_CONFIRMED` и явного `MR Review Approved: yes` от пользователя.
|
|
29
|
+
Scope rule:
|
|
30
|
+
- если запрос уходит за границы текущей задачи, сначала предложить `CREATE_TASK` или завершение текущей задачи; до решения не переходить к коду.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
Role: Clarifier Agent
|
|
2
2
|
Goal: выявить цель, ограничения, неоднозначности и критерии успеха.
|
|
3
|
+
Law: никаких кодовых изменений до заполнения PRD, архитектуры и verification matrix (`tests_unit`, `tests_system`, `tests_e2e_playwright`, `external_analysis`).
|
|
3
4
|
Rule: если задача классифицируется как большая фича, обязательно предложить создать `feature issue` и `epic issue` в GitHub tracker, а также отдельную ветку.
|
|
4
5
|
Git rule: для задач реализации в Git Flow Lite по умолчанию выбирать `feature/<task-or-issue-id>-<slug>` (или `codex/feature/...`) от `develop`.
|
|
5
6
|
Task granularity rule: если задача атомарная и относится к текущей feature-ветке, это фиксируется как `Task Type: atomic`, иначе создаётся отдельная рабочая ветка.
|
|
7
|
+
Scope rule: если запрос вышел за рамки текущей задачи, сначала предложить завести новую задачу или завершить текущую; не переходить к коду до решения.
|
|
6
8
|
Output: PRD Step с заполненными "Описание" и "Проверяемость".
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
Role: Governance Watchdog Agent
|
|
2
2
|
Goal: блокировать выполнение команды, если не выполнены PRD/acceptance/user-confirmation требования.
|
|
3
3
|
Rule: без PASS от governance gate команда не исполняется.
|
|
4
|
+
Rule: перед началом кодирования обязателен docs-first PASS (`PRD + Architecture + Verification Plan + tests_unit/tests_system/tests_e2e_playwright/external_analysis`).
|
|
5
|
+
Rule: если запрос вышел за рамки текущей задачи, агент обязан остановить кодовые действия и предложить `CREATE_TASK` или завершение текущей задачи.
|
|
@@ -2,6 +2,7 @@ Role: Reviewer/Judge Agent
|
|
|
2
2
|
Goal: независимая приёмка по критериям и обязательный pre-commit review gate.
|
|
3
3
|
Output format: что сделано, критические замечания, потенциальные риски, рекомендация PASS_CANDIDATE/FAIL.
|
|
4
4
|
Rule: финальный PASS_CONFIRMED только после явного `Review Approved: yes` от пользователя.
|
|
5
|
+
Rule: review обязан подтвердить docs-first дисциплину: код не начат до `PRD + Architecture + Verification Plan + tests_unit/tests_system/tests_e2e_playwright/external_analysis`.
|
|
5
6
|
Handoff rule: после pre-commit PASS_CONFIRMED задача передаётся в `MR Review Agent` для pre-merge gate.
|
|
6
7
|
Status rule: перед review gate задача должна быть в статусе `REVIEW`; статус `READY` выставляется только после `PASS_CONFIRMED`.
|
|
7
8
|
Delivery rule: `READY` требует commit+push на `feature/*|release/*|hotfix/*` (или `codex/*` эквиваленты) и PR в целевую ветку; `DONE` требует интеграцию в `main` и back-merge в `develop` для `release/*|hotfix/*`; `PUBLISH` только после фактической публикации.
|
|
@@ -3,6 +3,17 @@ import process from "node:process";
|
|
|
3
3
|
|
|
4
4
|
const STATUS_LABELS = ["TODO", "IN_PROGRESS", "REVIEW", "READY", "BLOCKED", "DONE", "PUBLISH"];
|
|
5
5
|
const REQUIRED_PRD_HEADINGS = ["### Описание", "### Проверяемость", "### Что сделано"];
|
|
6
|
+
const REQUIRED_DOCUMENT_HEADINGS = ["## Architecture", "## Verification Plan"];
|
|
7
|
+
const REQUIRED_VERIFIABILITY_ROWS = [
|
|
8
|
+
{ key: "strict", label: "strict" },
|
|
9
|
+
{ key: "statistical", label: "statistical" },
|
|
10
|
+
{ key: "human", label: "human" },
|
|
11
|
+
{ key: "architecture", label: "architecture" },
|
|
12
|
+
{ key: "tests_unit", label: "tests_unit" },
|
|
13
|
+
{ key: "tests_system", label: "tests_system" },
|
|
14
|
+
{ key: "tests_e2e_playwright", label: "tests_e2e_playwright" },
|
|
15
|
+
{ key: "external_analysis", label: "external_analysis" },
|
|
16
|
+
];
|
|
6
17
|
const STATUS_COLORS = {
|
|
7
18
|
IN_PROGRESS: "FBCA04",
|
|
8
19
|
REVIEW: "5319E7",
|
|
@@ -195,6 +206,11 @@ function buildVerifiability(payload = {}) {
|
|
|
195
206
|
let strict = "";
|
|
196
207
|
let statistical = "";
|
|
197
208
|
let human = "";
|
|
209
|
+
let architecture = "";
|
|
210
|
+
let testsUnit = "";
|
|
211
|
+
let testsSystem = "";
|
|
212
|
+
let testsE2EPlaywright = "";
|
|
213
|
+
let externalAnalysis = "";
|
|
198
214
|
|
|
199
215
|
if (structured && typeof structured === "object" && !Array.isArray(structured)) {
|
|
200
216
|
strict = pickFirstNonEmpty(structured.strict, payload.strict, payload.verificationStrict);
|
|
@@ -204,6 +220,39 @@ function buildVerifiability(payload = {}) {
|
|
|
204
220
|
payload.verificationStatistical,
|
|
205
221
|
);
|
|
206
222
|
human = pickFirstNonEmpty(structured.human, payload.human, payload.verificationHuman);
|
|
223
|
+
architecture = pickFirstNonEmpty(
|
|
224
|
+
structured.architecture,
|
|
225
|
+
payload.architecture,
|
|
226
|
+
payload.verificationArchitecture,
|
|
227
|
+
);
|
|
228
|
+
testsUnit = pickFirstNonEmpty(
|
|
229
|
+
structured.tests_unit,
|
|
230
|
+
structured.testsUnit,
|
|
231
|
+
payload.tests_unit,
|
|
232
|
+
payload.testsUnit,
|
|
233
|
+
payload.verificationTestsUnit,
|
|
234
|
+
);
|
|
235
|
+
testsSystem = pickFirstNonEmpty(
|
|
236
|
+
structured.tests_system,
|
|
237
|
+
structured.testsSystem,
|
|
238
|
+
payload.tests_system,
|
|
239
|
+
payload.testsSystem,
|
|
240
|
+
payload.verificationTestsSystem,
|
|
241
|
+
);
|
|
242
|
+
testsE2EPlaywright = pickFirstNonEmpty(
|
|
243
|
+
structured.tests_e2e_playwright,
|
|
244
|
+
structured.testsE2EPlaywright,
|
|
245
|
+
payload.tests_e2e_playwright,
|
|
246
|
+
payload.testsE2EPlaywright,
|
|
247
|
+
payload.verificationTestsE2EPlaywright,
|
|
248
|
+
);
|
|
249
|
+
externalAnalysis = pickFirstNonEmpty(
|
|
250
|
+
structured.external_analysis,
|
|
251
|
+
structured.externalAnalysis,
|
|
252
|
+
payload.external_analysis,
|
|
253
|
+
payload.externalAnalysis,
|
|
254
|
+
payload.verificationExternalAnalysis,
|
|
255
|
+
);
|
|
207
256
|
} else {
|
|
208
257
|
const flat = pickFirstNonEmpty(payload.verifiability, payload.verification);
|
|
209
258
|
strict = pickFirstNonEmpty(
|
|
@@ -221,12 +270,48 @@ function buildVerifiability(payload = {}) {
|
|
|
221
270
|
payload.verificationHuman,
|
|
222
271
|
parsePrefixedValue(flat, "human"),
|
|
223
272
|
);
|
|
273
|
+
architecture = pickFirstNonEmpty(
|
|
274
|
+
payload.architecture,
|
|
275
|
+
payload.verificationArchitecture,
|
|
276
|
+
parsePrefixedValue(flat, "architecture"),
|
|
277
|
+
);
|
|
278
|
+
testsUnit = pickFirstNonEmpty(
|
|
279
|
+
payload.tests_unit,
|
|
280
|
+
payload.testsUnit,
|
|
281
|
+
payload.verificationTestsUnit,
|
|
282
|
+
parsePrefixedValue(flat, "tests_unit"),
|
|
283
|
+
);
|
|
284
|
+
testsSystem = pickFirstNonEmpty(
|
|
285
|
+
payload.tests_system,
|
|
286
|
+
payload.testsSystem,
|
|
287
|
+
payload.verificationTestsSystem,
|
|
288
|
+
parsePrefixedValue(flat, "tests_system"),
|
|
289
|
+
);
|
|
290
|
+
testsE2EPlaywright = pickFirstNonEmpty(
|
|
291
|
+
payload.tests_e2e_playwright,
|
|
292
|
+
payload.testsE2EPlaywright,
|
|
293
|
+
payload.verificationTestsE2EPlaywright,
|
|
294
|
+
parsePrefixedValue(flat, "tests_e2e_playwright"),
|
|
295
|
+
);
|
|
296
|
+
externalAnalysis = pickFirstNonEmpty(
|
|
297
|
+
payload.external_analysis,
|
|
298
|
+
payload.externalAnalysis,
|
|
299
|
+
payload.verificationExternalAnalysis,
|
|
300
|
+
parsePrefixedValue(flat, "external_analysis"),
|
|
301
|
+
);
|
|
224
302
|
}
|
|
225
303
|
|
|
226
304
|
return {
|
|
227
305
|
strict: strict || "schema/types/invariants defined",
|
|
228
306
|
statistical: statistical || "N/A (provide measurable threshold if metric is applicable)",
|
|
229
307
|
human: human || "manual review and acceptance by task owner",
|
|
308
|
+
architecture: architecture || "component contracts and constraints documented before coding",
|
|
309
|
+
tests_unit: testsUnit || "unit tests required for changed logic",
|
|
310
|
+
tests_system: testsSystem || "system/integration tests required for key flows",
|
|
311
|
+
tests_e2e_playwright:
|
|
312
|
+
testsE2EPlaywright || "Playwright e2e scenario required for critical user path",
|
|
313
|
+
external_analysis:
|
|
314
|
+
externalAnalysis || "independent analysis by another agent role for key decisions",
|
|
230
315
|
};
|
|
231
316
|
}
|
|
232
317
|
|
|
@@ -239,19 +324,20 @@ function validateVerifiabilitySection(body) {
|
|
|
239
324
|
};
|
|
240
325
|
}
|
|
241
326
|
|
|
242
|
-
const hasStrict = /(^|\n)\s*-\s*strict\s*:/i.test(section);
|
|
243
|
-
const hasStatistical = /(^|\n)\s*-\s*statistical\s*:/i.test(section);
|
|
244
|
-
const hasHuman = /(^|\n)\s*-\s*human\s*:/i.test(section);
|
|
245
327
|
const reasons = [];
|
|
246
328
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
329
|
+
for (const row of REQUIRED_VERIFIABILITY_ROWS) {
|
|
330
|
+
const match = section.match(
|
|
331
|
+
new RegExp(`(^|\\n)\\s*-\\s*${row.key}\\s*:\\s*(.+)$`, "im"),
|
|
332
|
+
);
|
|
333
|
+
if (!match) {
|
|
334
|
+
reasons.push(`missing '${row.key}:' row in verifiability`);
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
const value = toNonEmptyString(match[2]);
|
|
338
|
+
if (!value) {
|
|
339
|
+
reasons.push(`row '${row.key}:' must not be empty`);
|
|
340
|
+
}
|
|
255
341
|
}
|
|
256
342
|
|
|
257
343
|
const statisticalMatch = section.match(/(^|\n)\s*-\s*statistical\s*:\s*(.+)$/im);
|
|
@@ -278,6 +364,11 @@ function validateIssueBodyForInProgress(body) {
|
|
|
278
364
|
reasons.push(`missing required PRD heading '${heading}'`);
|
|
279
365
|
}
|
|
280
366
|
}
|
|
367
|
+
for (const heading of REQUIRED_DOCUMENT_HEADINGS) {
|
|
368
|
+
if (!String(body || "").includes(heading)) {
|
|
369
|
+
reasons.push(`missing required document heading '${heading}'`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
281
372
|
|
|
282
373
|
const verifiabilityCheck = validateVerifiabilitySection(body);
|
|
283
374
|
if (!verifiabilityCheck.ok) {
|
|
@@ -359,6 +450,14 @@ function renderCreateTaskBody(payload, labels) {
|
|
|
359
450
|
"заполнить описание задачи",
|
|
360
451
|
);
|
|
361
452
|
const verifiability = buildVerifiability(payload);
|
|
453
|
+
const architecture = renderBulletedValue(
|
|
454
|
+
payload.architecture,
|
|
455
|
+
"описать архитектуру, контракты компонентов и ограничения до начала кодирования",
|
|
456
|
+
);
|
|
457
|
+
const verificationPlan = renderBulletedValue(
|
|
458
|
+
payload.verificationPlan,
|
|
459
|
+
"описать детальный план проверок (unit/system/e2e_playwright/external_analysis)",
|
|
460
|
+
);
|
|
362
461
|
const doneBlock = renderBulletedValue(
|
|
363
462
|
payload.done,
|
|
364
463
|
"[ ] Не начато",
|
|
@@ -386,10 +485,21 @@ function renderCreateTaskBody(payload, labels) {
|
|
|
386
485
|
`- strict: ${verifiability.strict}`,
|
|
387
486
|
`- statistical: ${verifiability.statistical}`,
|
|
388
487
|
`- human: ${verifiability.human}`,
|
|
488
|
+
`- architecture: ${verifiability.architecture}`,
|
|
489
|
+
`- tests_unit: ${verifiability.tests_unit}`,
|
|
490
|
+
`- tests_system: ${verifiability.tests_system}`,
|
|
491
|
+
`- tests_e2e_playwright: ${verifiability.tests_e2e_playwright}`,
|
|
492
|
+
`- external_analysis: ${verifiability.external_analysis}`,
|
|
389
493
|
"",
|
|
390
494
|
"### Что сделано",
|
|
391
495
|
doneBlock,
|
|
392
496
|
"",
|
|
497
|
+
"## Architecture",
|
|
498
|
+
architecture,
|
|
499
|
+
"",
|
|
500
|
+
"## Verification Plan",
|
|
501
|
+
verificationPlan,
|
|
502
|
+
"",
|
|
393
503
|
"## Metadata",
|
|
394
504
|
...metadata,
|
|
395
505
|
].join("\n");
|
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import { resolveTrackerForCommand } from "./tracker/provider-lock.mjs";
|
|
6
6
|
|
|
7
7
|
const COMMAND_MAP = {
|
|
8
|
+
VERIFY_GOVERNANCE_GATE: "__verifyGovernanceGate",
|
|
8
9
|
VERIFY_IMPLEMENTATION_GATE: "__verifyImplementationGate",
|
|
9
10
|
CREATE_TASK: "createTask",
|
|
10
11
|
PREPARE_TASK_BRANCH: "__prepareTaskBranch",
|
|
@@ -44,7 +45,7 @@ function printHelp() {
|
|
|
44
45
|
console.log("");
|
|
45
46
|
console.log("Usage:");
|
|
46
47
|
console.log(
|
|
47
|
-
" npm run meta:ops -- --command VERIFY_IMPLEMENTATION_GATE|CREATE_TASK|PREPARE_TASK_BRANCH|RUN_MR_REVIEW_GATE|SET_STATUS|COMMIT_BY_NAME|ASSIGN_SPRINT [--tracker github|mcp|local|custom] [--payload '{\"k\":\"v\"}']",
|
|
48
|
+
" npm run meta:ops -- --command VERIFY_GOVERNANCE_GATE|VERIFY_IMPLEMENTATION_GATE|CREATE_TASK|PREPARE_TASK_BRANCH|RUN_MR_REVIEW_GATE|SET_STATUS|COMMIT_BY_NAME|ASSIGN_SPRINT [--tracker github|mcp|local|custom] [--payload '{\"k\":\"v\"}']",
|
|
48
49
|
);
|
|
49
50
|
console.log("");
|
|
50
51
|
console.log("Rules:");
|
|
@@ -124,6 +125,21 @@ function runImplementationGate(payload, trackerProvider) {
|
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
|
|
128
|
+
function runGovernanceGate(payload, trackerProvider, command) {
|
|
129
|
+
const args = [scriptPath("verify-governance.mjs"), "--tracker", trackerProvider, "--command", command];
|
|
130
|
+
if (payload.task) {
|
|
131
|
+
args.push("--task", String(payload.task));
|
|
132
|
+
}
|
|
133
|
+
if (payload.validateLocalCache) {
|
|
134
|
+
args.push("--validate-local-cache");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const output = runNodeScript(args);
|
|
138
|
+
if (output.trim()) {
|
|
139
|
+
console.log(output.trim());
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
127
143
|
function parseArgs(argv) {
|
|
128
144
|
const options = {
|
|
129
145
|
command: "",
|
|
@@ -204,6 +220,20 @@ async function main() {
|
|
|
204
220
|
requestedTracker: options.tracker,
|
|
205
221
|
cwd: process.cwd(),
|
|
206
222
|
});
|
|
223
|
+
const governanceTaskRef =
|
|
224
|
+
payload.task || payload.issue || payload.taskId || payload.id || payload.pr || "";
|
|
225
|
+
const governanceCommand =
|
|
226
|
+
options.command === "SET_STATUS" && String(payload.status || "").toUpperCase() === "IN_PROGRESS"
|
|
227
|
+
? "VERIFY_IMPLEMENTATION_GATE"
|
|
228
|
+
: options.command;
|
|
229
|
+
|
|
230
|
+
if (adapterMethod === "__verifyGovernanceGate") {
|
|
231
|
+
runGovernanceGate({ task: governanceTaskRef, validateLocalCache: payload.validateLocalCache }, trackerProvider, governanceCommand);
|
|
232
|
+
console.log(`TrackerGateway PASS: ${options.command} via tracker '${trackerProvider}'.`);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
runGovernanceGate({ task: governanceTaskRef, validateLocalCache: payload.validateLocalCache }, trackerProvider, governanceCommand);
|
|
207
237
|
|
|
208
238
|
if (adapterMethod === "__prepareTaskBranch") {
|
|
209
239
|
runTaskBranchRouter(payload);
|
|
@@ -1,20 +1,190 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
|
-
import {
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
|
+
import { resolveTrackerForCommand } from "./tracker/provider-lock.mjs";
|
|
5
6
|
|
|
6
7
|
const TASKS_DIR = path.resolve(process.cwd(), "tasks");
|
|
7
8
|
const EXCLUDED_FILES = new Set(["backlog.md", "sprint-1.md", "task-status-log.md"]);
|
|
9
|
+
const COMMANDS_REQUIRE_TASK_CONTEXT = new Set([
|
|
10
|
+
"PREPARE_TASK_BRANCH",
|
|
11
|
+
"VERIFY_IMPLEMENTATION_GATE",
|
|
12
|
+
"RUN_REVIEW_GATE",
|
|
13
|
+
"RUN_MR_REVIEW_GATE",
|
|
14
|
+
"COMMIT_BY_NAME",
|
|
15
|
+
]);
|
|
8
16
|
|
|
9
17
|
const REQUIRED_PATTERNS = [
|
|
10
18
|
{ label: "PRD section: Описание", regex: /^###\s+Описание/m },
|
|
11
19
|
{ label: "PRD section: Проверяемость", regex: /^###\s+Проверяемость/m },
|
|
12
20
|
{ label: "PRD section: Что сделано", regex: /^###\s+Что сделано/m },
|
|
21
|
+
{ label: "Document section: Architecture", regex: /^##\s+Architecture/m },
|
|
22
|
+
{ label: "Document section: Verification Plan", regex: /^##\s+Verification Plan/m },
|
|
13
23
|
{ label: "Verifiability strict", regex: /^\s*-\s*strict:/m },
|
|
14
24
|
{ label: "Verifiability statistical", regex: /^\s*-\s*statistical:/m },
|
|
15
25
|
{ label: "Verifiability human", regex: /^\s*-\s*human:/m },
|
|
26
|
+
{ label: "Verifiability architecture", regex: /^\s*-\s*architecture:/m },
|
|
27
|
+
{ label: "Verifiability tests_unit", regex: /^\s*-\s*tests_unit:/m },
|
|
28
|
+
{ label: "Verifiability tests_system", regex: /^\s*-\s*tests_system:/m },
|
|
29
|
+
{ label: "Verifiability tests_e2e_playwright", regex: /^\s*-\s*tests_e2e_playwright:/m },
|
|
30
|
+
{ label: "Verifiability external_analysis", regex: /^\s*-\s*external_analysis:/m },
|
|
16
31
|
];
|
|
17
32
|
|
|
33
|
+
const REQUIRED_PRD_HEADINGS = ["### Описание", "### Проверяемость", "### Что сделано"];
|
|
34
|
+
const REQUIRED_DOCUMENT_HEADINGS = ["## Architecture", "## Verification Plan"];
|
|
35
|
+
const REQUIRED_VERIFIABILITY_ROWS = [
|
|
36
|
+
"strict",
|
|
37
|
+
"statistical",
|
|
38
|
+
"human",
|
|
39
|
+
"architecture",
|
|
40
|
+
"tests_unit",
|
|
41
|
+
"tests_system",
|
|
42
|
+
"tests_e2e_playwright",
|
|
43
|
+
"external_analysis",
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
function parseArgs(argv) {
|
|
47
|
+
const options = {
|
|
48
|
+
validateLocalCache: false,
|
|
49
|
+
tracker: "",
|
|
50
|
+
command: "",
|
|
51
|
+
task: "",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
55
|
+
const arg = argv[i];
|
|
56
|
+
if (arg === "--validate-local-cache") {
|
|
57
|
+
options.validateLocalCache = true;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (arg === "--tracker") {
|
|
61
|
+
options.tracker = (argv[i + 1] || "").trim().toLowerCase();
|
|
62
|
+
i += 1;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (arg === "--command") {
|
|
66
|
+
options.command = (argv[i + 1] || "").trim().toUpperCase();
|
|
67
|
+
i += 1;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (arg === "--task") {
|
|
71
|
+
options.task = (argv[i + 1] || "").trim();
|
|
72
|
+
i += 1;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return options;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function parseIssueNumber(value) {
|
|
80
|
+
const source = String(value || "").trim();
|
|
81
|
+
if (!source) {
|
|
82
|
+
return "";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const direct = source.match(/^#?(\d+)$/);
|
|
86
|
+
if (direct) {
|
|
87
|
+
return direct[1];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const issueToken = source.match(/(?:^|[\/\s])issue-(\d+)(?:-|$|\s)/i);
|
|
91
|
+
if (issueToken) {
|
|
92
|
+
return issueToken[1];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const githubUrl = source.match(/\/issues\/(\d+)(?:$|[/?#])/i);
|
|
96
|
+
if (githubUrl) {
|
|
97
|
+
return githubUrl[1];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const ref = source.match(/#(\d+)/);
|
|
101
|
+
if (ref) {
|
|
102
|
+
return ref[1];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function run(command, args, allowFailure = false) {
|
|
109
|
+
try {
|
|
110
|
+
return execFileSync(command, args, {
|
|
111
|
+
cwd: process.cwd(),
|
|
112
|
+
encoding: "utf8",
|
|
113
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
114
|
+
}).trim();
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (allowFailure) {
|
|
117
|
+
return "";
|
|
118
|
+
}
|
|
119
|
+
const stderr = String(error?.stderr || "").trim();
|
|
120
|
+
const stdout = String(error?.stdout || "").trim();
|
|
121
|
+
throw new Error(`${command} ${args.join(" ")} failed: ${stderr || stdout || error.message}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function readJson(command, args, allowFailure = false) {
|
|
126
|
+
const raw = run(command, args, allowFailure);
|
|
127
|
+
if (!raw) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return JSON.parse(raw);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function ensureGhReady() {
|
|
134
|
+
run("gh", ["--version"], false);
|
|
135
|
+
const auth = run("gh", ["auth", "status"], true);
|
|
136
|
+
if (!auth) {
|
|
137
|
+
throw new Error("gh is not authenticated. Run 'gh auth login' first.");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function extractSection(content, heading) {
|
|
142
|
+
const source = String(content || "");
|
|
143
|
+
if (!source || !heading) {
|
|
144
|
+
return "";
|
|
145
|
+
}
|
|
146
|
+
const escapedHeading = heading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
147
|
+
const regex = new RegExp(`${escapedHeading}\\s*\\n([\\s\\S]*?)(?:\\n###\\s+|$)`, "i");
|
|
148
|
+
const match = source.match(regex);
|
|
149
|
+
return (match?.[1] || "").trim();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function validateIssueBody(content) {
|
|
153
|
+
const reasons = [];
|
|
154
|
+
for (const heading of REQUIRED_PRD_HEADINGS) {
|
|
155
|
+
if (!String(content || "").includes(heading)) {
|
|
156
|
+
reasons.push(`missing required PRD heading '${heading}'`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
for (const heading of REQUIRED_DOCUMENT_HEADINGS) {
|
|
160
|
+
if (!String(content || "").includes(heading)) {
|
|
161
|
+
reasons.push(`missing required document heading '${heading}'`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const section = extractSection(content, "### Проверяемость");
|
|
166
|
+
if (!section) {
|
|
167
|
+
reasons.push("missing section '### Проверяемость'");
|
|
168
|
+
return reasons;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for (const key of REQUIRED_VERIFIABILITY_ROWS) {
|
|
172
|
+
const match = section.match(
|
|
173
|
+
new RegExp(`(^|\\n)\\s*-\\s*${key}\\s*:\\s*(.+)$`, "im"),
|
|
174
|
+
);
|
|
175
|
+
if (!match) {
|
|
176
|
+
reasons.push(`missing '${key}:' row in verifiability`);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const value = String(match[2] || "").trim();
|
|
180
|
+
if (!value) {
|
|
181
|
+
reasons.push(`row '${key}:' must not be empty`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return reasons;
|
|
186
|
+
}
|
|
187
|
+
|
|
18
188
|
async function listTaskFiles() {
|
|
19
189
|
try {
|
|
20
190
|
const entries = await fs.readdir(TASKS_DIR, { withFileTypes: true });
|
|
@@ -39,22 +209,56 @@ async function validateTask(filePath) {
|
|
|
39
209
|
return failed;
|
|
40
210
|
}
|
|
41
211
|
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
212
|
+
function validateGithubTask(taskRef) {
|
|
213
|
+
const issueNumber = parseIssueNumber(taskRef);
|
|
214
|
+
if (!issueNumber) {
|
|
215
|
+
throw new Error("missing/invalid --task for governance command that requires task context");
|
|
216
|
+
}
|
|
45
217
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
218
|
+
ensureGhReady();
|
|
219
|
+
const issueData = readJson("gh", [
|
|
220
|
+
"issue",
|
|
221
|
+
"view",
|
|
222
|
+
issueNumber,
|
|
223
|
+
"--json",
|
|
224
|
+
"number,title,body,url",
|
|
225
|
+
]);
|
|
226
|
+
const reasons = validateIssueBody(issueData?.body || "");
|
|
227
|
+
if (reasons.length > 0) {
|
|
228
|
+
throw new Error(`issue #${issueNumber} governance FAIL: ${reasons.join("; ")}`);
|
|
52
229
|
}
|
|
53
230
|
|
|
231
|
+
return issueData;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function main() {
|
|
235
|
+
const options = parseArgs(process.argv.slice(2));
|
|
236
|
+
const trackerProvider = resolveTrackerForCommand({
|
|
237
|
+
requestedTracker: options.tracker,
|
|
238
|
+
cwd: process.cwd(),
|
|
239
|
+
});
|
|
240
|
+
|
|
54
241
|
const taskFiles = await listTaskFiles();
|
|
55
|
-
const localTasksRequired = trackerProvider === "local" || validateLocalCache;
|
|
242
|
+
const localTasksRequired = trackerProvider === "local" || options.validateLocalCache;
|
|
243
|
+
const commandRequiresTask = COMMANDS_REQUIRE_TASK_CONTEXT.has(options.command);
|
|
244
|
+
|
|
245
|
+
if (commandRequiresTask && !options.task) {
|
|
246
|
+
console.error(
|
|
247
|
+
`Governance FAIL: command '${options.command}' requires explicit --task for docs-first validation.`,
|
|
248
|
+
);
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
56
251
|
|
|
57
252
|
if (!localTasksRequired) {
|
|
253
|
+
if (trackerProvider === "github" && commandRequiresTask) {
|
|
254
|
+
const issueData = validateGithubTask(options.task);
|
|
255
|
+
const issueNumber = String(issueData?.number || parseIssueNumber(options.task));
|
|
256
|
+
console.log(
|
|
257
|
+
`Governance PASS: docs-first check passed for issue #${issueNumber} (command ${options.command}).`,
|
|
258
|
+
);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
58
262
|
const localCount = taskFiles ? taskFiles.length : 0;
|
|
59
263
|
console.log(
|
|
60
264
|
`Governance PASS: tracker provider '${trackerProvider}' is external; local task validation skipped (${localCount} file(s) in tasks/).`,
|
|
@@ -4,6 +4,17 @@ import { resolveTrackerForCommand } from "./tracker/provider-lock.mjs";
|
|
|
4
4
|
|
|
5
5
|
const STATUS_LABELS = ["TODO", "IN_PROGRESS", "REVIEW", "READY", "BLOCKED", "DONE", "PUBLISH"];
|
|
6
6
|
const REQUIRED_PRD_HEADINGS = ["### Описание", "### Проверяемость", "### Что сделано"];
|
|
7
|
+
const REQUIRED_DOCUMENT_HEADINGS = ["## Architecture", "## Verification Plan"];
|
|
8
|
+
const REQUIRED_VERIFIABILITY_ROWS = [
|
|
9
|
+
"strict",
|
|
10
|
+
"statistical",
|
|
11
|
+
"human",
|
|
12
|
+
"architecture",
|
|
13
|
+
"tests_unit",
|
|
14
|
+
"tests_system",
|
|
15
|
+
"tests_e2e_playwright",
|
|
16
|
+
"external_analysis",
|
|
17
|
+
];
|
|
7
18
|
const IMPLEMENTATION_BRANCH_TYPES = new Set(["feature", "release", "hotfix"]);
|
|
8
19
|
|
|
9
20
|
function run(command, args, allowFailure = false) {
|
|
@@ -165,6 +176,11 @@ function validateIssueBody(issueBody) {
|
|
|
165
176
|
blockers.push(`missing required PRD heading '${heading}'`);
|
|
166
177
|
}
|
|
167
178
|
}
|
|
179
|
+
for (const heading of REQUIRED_DOCUMENT_HEADINGS) {
|
|
180
|
+
if (!String(issueBody || "").includes(heading)) {
|
|
181
|
+
blockers.push(`missing required document heading '${heading}'`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
168
184
|
|
|
169
185
|
const verifiability = extractSection(issueBody, "### Проверяемость");
|
|
170
186
|
if (!verifiability) {
|
|
@@ -172,14 +188,18 @@ function validateIssueBody(issueBody) {
|
|
|
172
188
|
return blockers;
|
|
173
189
|
}
|
|
174
190
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
191
|
+
for (const key of REQUIRED_VERIFIABILITY_ROWS) {
|
|
192
|
+
const match = verifiability.match(
|
|
193
|
+
new RegExp(`(^|\\n)\\s*-\\s*${key}\\s*:\\s*(.+)$`, "im"),
|
|
194
|
+
);
|
|
195
|
+
if (!match) {
|
|
196
|
+
blockers.push(`missing '${key}:' row in verifiability`);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const value = String(match[2] || "").trim();
|
|
200
|
+
if (!value) {
|
|
201
|
+
blockers.push(`row '${key}:' must not be empty`);
|
|
202
|
+
}
|
|
183
203
|
}
|
|
184
204
|
|
|
185
205
|
const statisticalMatch = verifiability.match(/(^|\n)\s*-\s*statistical\s*:\s*(.+)$/im);
|
|
@@ -223,6 +243,9 @@ function buildNextSteps({ issueNumber, branchType, branchTaskRef }) {
|
|
|
223
243
|
steps.push(
|
|
224
244
|
`Ensure task is IN_PROGRESS: npm run meta:ops -- --command SET_STATUS --payload '{\"task\":\"#${issueNumber}\",\"status\":\"IN_PROGRESS\"}'`,
|
|
225
245
|
);
|
|
246
|
+
steps.push(
|
|
247
|
+
"Complete docs-first gate: PRD + Architecture + Verification Plan + tests matrix (unit/system/e2e_playwright) + external analysis.",
|
|
248
|
+
);
|
|
226
249
|
steps.push(
|
|
227
250
|
`Run branch preflight: npm run meta:task-start -- --task \"#${issueNumber}\" --slug <slug> --kind feature`,
|
|
228
251
|
);
|
|
@@ -251,7 +274,7 @@ function printHuman(report) {
|
|
|
251
274
|
console.log("## Checks");
|
|
252
275
|
console.log(`- issue: ${report.issue.number ? `#${report.issue.number}` : "not detected"}`);
|
|
253
276
|
console.log(`- issue status: ${report.issue.status || "not detected"}`);
|
|
254
|
-
console.log(`- prd/
|
|
277
|
+
console.log(`- prd/architecture/verification matrix: ${report.prdOk ? "PASS" : "FAIL"}`);
|
|
255
278
|
console.log(`- branch alignment: ${report.branchAligned ? "PASS" : "FAIL"}`);
|
|
256
279
|
|
|
257
280
|
console.log("");
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
- Required Outputs:
|
|
9
9
|
- Required Evidence:
|
|
10
10
|
- Acceptance Criteria:
|
|
11
|
+
- Coding Start Gate (PASS required before any code edits):
|
|
12
|
+
- PRD Description complete
|
|
13
|
+
- Architecture documented
|
|
14
|
+
- Verification matrix complete (unit/system/e2e_playwright/external_analysis)
|
|
11
15
|
- Failure/Escalation Rules:
|
|
12
16
|
- Tracker Binding (task/status/sprint):
|
|
13
17
|
- Git Strategy (Git Flow Lite: feature/* -> develop, release/* -> main + back-merge, hotfix/* -> main + back-merge):
|
|
@@ -3,10 +3,19 @@
|
|
|
3
3
|
### Описание
|
|
4
4
|
- Что и зачем делаем на этапе.
|
|
5
5
|
|
|
6
|
+
## Architecture
|
|
7
|
+
- Контекст и ограничения архитектуры.
|
|
8
|
+
- Контракты компонентов (вход/выход, инварианты).
|
|
9
|
+
|
|
6
10
|
### Проверяемость
|
|
7
11
|
- strict:
|
|
8
12
|
- statistical:
|
|
9
13
|
- human:
|
|
14
|
+
- architecture:
|
|
15
|
+
- tests_unit:
|
|
16
|
+
- tests_system:
|
|
17
|
+
- tests_e2e_playwright:
|
|
18
|
+
- external_analysis:
|
|
10
19
|
- evidence:
|
|
11
20
|
|
|
12
21
|
### Что сделано
|
|
@@ -17,10 +17,19 @@
|
|
|
17
17
|
## PRD Step
|
|
18
18
|
### Описание
|
|
19
19
|
-
|
|
20
|
+
## Architecture
|
|
21
|
+
- Контекст:
|
|
22
|
+
- Компоненты/контракты:
|
|
23
|
+
- Ограничения и инварианты:
|
|
20
24
|
### Проверяемость
|
|
21
25
|
- strict:
|
|
22
26
|
- statistical:
|
|
23
27
|
- human:
|
|
28
|
+
- architecture:
|
|
29
|
+
- tests_unit:
|
|
30
|
+
- tests_system:
|
|
31
|
+
- tests_e2e_playwright:
|
|
32
|
+
- external_analysis:
|
|
24
33
|
### Что сделано
|
|
25
34
|
- [ ] Не начато
|
|
26
35
|
|
|
@@ -28,7 +37,11 @@
|
|
|
28
37
|
-
|
|
29
38
|
|
|
30
39
|
## Evidence
|
|
31
|
-
-
|
|
40
|
+
- Unit tests report:
|
|
41
|
+
- System tests report:
|
|
42
|
+
- Playwright e2e report:
|
|
43
|
+
- External analysis report:
|
|
44
|
+
- Tracker links:
|
|
32
45
|
|
|
33
46
|
## Progress Log
|
|
34
47
|
- YYYY-MM-DD: created
|
|
@@ -3,13 +3,24 @@
|
|
|
3
3
|
## Scope
|
|
4
4
|
-
|
|
5
5
|
|
|
6
|
-
##
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
|
|
6
|
+
## Architecture Validation
|
|
7
|
+
- архитектурные ограничения и инварианты зафиксированы
|
|
8
|
+
- контракты компонентов проверяемы и трассируемы
|
|
9
|
+
|
|
10
|
+
## Test Matrix
|
|
11
|
+
- unit:
|
|
12
|
+
- system:
|
|
13
|
+
- e2e_playwright:
|
|
14
|
+
|
|
15
|
+
## External Analysis
|
|
16
|
+
- независимый агентный анализ по ключевым рискам и решениям
|
|
17
|
+
- ссылки на отчеты/артефакты
|
|
10
18
|
|
|
11
19
|
## Metrics & Thresholds
|
|
12
|
-
-
|
|
20
|
+
- statistical:
|
|
21
|
+
|
|
22
|
+
## Human Approval
|
|
23
|
+
- human:
|
|
13
24
|
|
|
14
25
|
## Evidence Mapping
|
|
15
26
|
- criterion -> proof artifact
|
package/template/agents.md
CHANGED
|
@@ -26,6 +26,15 @@
|
|
|
26
26
|
Правило запуска этапа:
|
|
27
27
|
- если не заполнены `Описание` и `Проверяемость`, этап не стартует.
|
|
28
28
|
|
|
29
|
+
## 2.1) Закон No-Code-Before-PRD
|
|
30
|
+
До выполнения любых кодовых изменений (`write/edit/refactor/test-fix`) обязательно должны быть зафиксированы:
|
|
31
|
+
- PRD с заполненными `Описание` и `Проверяемость`;
|
|
32
|
+
- архитектурное решение (контекст, ограничения, контракты компонентов);
|
|
33
|
+
- верификационная матрица минимум: `unit`, `system`, `e2e_playwright`, `external_analysis`;
|
|
34
|
+
- evidence-план и критерии PASS/FAIL.
|
|
35
|
+
|
|
36
|
+
Если любой пункт отсутствует, агент обязан остановить реализацию и сначала завершить PRD/архитектуру/проверки.
|
|
37
|
+
|
|
29
38
|
## 3) Роли агентов
|
|
30
39
|
- `Chief of Staff Agent`: оркестрация цепочки, приоритеты, блокеры, эскалации.
|
|
31
40
|
- `Status Agent`: сводный статус проекта (`tracker/sprint/task/git`) по запросам состояния.
|
|
@@ -92,6 +101,12 @@ Name: <agent role>
|
|
|
92
101
|
- `statistical`: benchmark/метрики/judge score/пороговые значения.
|
|
93
102
|
- `human`: review/approval в рискованных и неоднозначных точках.
|
|
94
103
|
|
|
104
|
+
Минимальный обязательный набор перед стартом кодирования:
|
|
105
|
+
- unit tests plan;
|
|
106
|
+
- system tests plan;
|
|
107
|
+
- e2e tests plan на Playwright;
|
|
108
|
+
- независимый внешний анализ (другой агент/роль) по ключевым решениям и рискам.
|
|
109
|
+
|
|
95
110
|
## 7) AgentWorkContract
|
|
96
111
|
Перед передачей задачи Executor-агенту фиксируется контракт:
|
|
97
112
|
- scope;
|
|
@@ -205,18 +220,32 @@ Name: <agent role>
|
|
|
205
220
|
23. Коммит следует формату `#issue-number <summary>` (issue ref в начале сообщения).
|
|
206
221
|
24. Для branch routing собран e2e evidence по двум сценариям: `same feature` и `different feature`.
|
|
207
222
|
25. Перед `--apply` подтверждена консистентность контекста `AGENTS.md` (fallback: `agents.md`) или явно подтверждён осознанный switch при diff.
|
|
223
|
+
26. До любых кодовых правок заполнены архитектурные артефакты задачи (контекст, ограничения, контракты).
|
|
224
|
+
27. В `Проверяемость` явно зафиксированы `tests_unit`, `tests_system`, `tests_e2e_playwright`.
|
|
225
|
+
28. Для ключевых задач выполнен `external_analysis` (независимый агентный review) с evidence-ссылкой.
|
|
226
|
+
29. Запуск кодирования разрешён только после `VERIFY_IMPLEMENTATION_GATE: PASS`.
|
|
227
|
+
30. Если диалог уходит за рамки текущей задачи, агент сначала предлагает `CREATE_TASK` или возвращает диалог в рамки текущей задачи; кодирование до решения запрещено.
|
|
208
228
|
|
|
209
229
|
Если хотя бы один критерий не выполнен, задача не принимается.
|
|
210
230
|
|
|
211
231
|
## 12) Verification-first gate
|
|
212
232
|
Реализация не начинается, пока не определены:
|
|
213
233
|
- acceptance criteria;
|
|
234
|
+
- архитектура и контракты компонентов;
|
|
214
235
|
- метрики и пороги;
|
|
215
236
|
- инварианты и ограничения;
|
|
216
237
|
- процедуры проверки;
|
|
238
|
+
- test matrix (`unit`, `system`, `e2e_playwright`);
|
|
239
|
+
- внешний независимый анализ по критическим зонам;
|
|
217
240
|
- зоны неопределённости и правила эскалации;
|
|
218
241
|
- способ фиксации в трекере.
|
|
219
242
|
|
|
243
|
+
## 12.1) Контроль рамок задачи в диалоге
|
|
244
|
+
Если пользовательский запрос выходит за рамки текущей задачи, агент обязан:
|
|
245
|
+
1. Остановить кодовые действия.
|
|
246
|
+
2. Предложить завести новую задачу (`CREATE_TASK`) или явно продолжить текущую.
|
|
247
|
+
3. До фиксации решения продолжать только PRD/архитектурное/валидационное оформление.
|
|
248
|
+
|
|
220
249
|
## 13) Реакция на провал проверки
|
|
221
250
|
Допустимые сценарии:
|
|
222
251
|
- `retry` с корректировками;
|
|
@@ -226,4 +255,4 @@ Name: <agent role>
|
|
|
226
255
|
- возврат статуса задачи в `IN_PROGRESS` или `BLOCKED`.
|
|
227
256
|
|
|
228
257
|
## 14) Главный инвариант
|
|
229
|
-
Нельзя делегировать
|
|
258
|
+
Нельзя делегировать работу, писать код и закрывать задачу без формализованных критериев приёмки, PRD-блока `Проверяемость`, архитектурного описания и требуемых доказательств в трекере.
|
|
@@ -27,7 +27,7 @@ Name: Governance Watchdog Agent
|
|
|
27
27
|
|
|
28
28
|
Governance Watchdog Agent: verify governance gate,
|
|
29
29
|
task <#issue>,
|
|
30
|
-
required checks "prd_sections_complete, acceptance_defined, user_confirmation_policy_respected",
|
|
30
|
+
required checks "prd_sections_complete, architecture_documented, verification_matrix(unit/system/e2e_playwright/external_analysis), acceptance_defined, user_confirmation_policy_respected, no_code_before_prd",
|
|
31
31
|
result PASS
|
|
32
32
|
```
|
|
33
33
|
|
|
@@ -41,6 +41,15 @@ result PASS
|
|
|
41
41
|
- Если пользователь явно не запросил смену provider и конфиг не обновлён, команды выполняются только через `__DEFAULT_TRACKER__`.
|
|
42
42
|
- CLI enforcement: `npm run meta:ops -- --command <COMMAND> [--tracker ...]` блокирует выполнение при mismatch provider.
|
|
43
43
|
|
|
44
|
+
## 0.3) Жёсткий закон до начала кодирования
|
|
45
|
+
Перед реализацией обязателен порядок:
|
|
46
|
+
1. `Описание`.
|
|
47
|
+
2. `Архитектура`.
|
|
48
|
+
3. `Проверяемость` (включая `tests_unit`, `tests_system`, `tests_e2e_playwright`, `external_analysis`).
|
|
49
|
+
4. `VERIFY_IMPLEMENTATION_GATE: PASS`.
|
|
50
|
+
|
|
51
|
+
До пункта 4 кодовые изменения запрещены.
|
|
52
|
+
|
|
44
53
|
## 1) Ключевое правило подтверждения пользователя
|
|
45
54
|
Только по явному подтверждению пользователя в текущем диалоге разрешены:
|
|
46
55
|
- `COMMIT_BY_NAME`;
|
|
@@ -70,6 +79,7 @@ result PASS
|
|
|
70
79
|
- если задача не относится к текущей ветке, требуется: проверить dirty/ahead, согласовать действие с пользователем, перейти на `develop` (или `main` для hotfix), обновить и создать новую ветку;
|
|
71
80
|
- перед `--apply` обязателен контекстный check: сравнить `AGENTS.md` (fallback: `agents.md`) текущей и базовой ветки, при diff запросить явное подтверждение пользователя;
|
|
72
81
|
- сообщение коммита обязательно следует формату `#issue-number <summary>` (issue ref в начале).
|
|
82
|
+
- если диалог ушёл за рамки текущей задачи, сначала предложить `CREATE_TASK` или завершить текущую задачу; кодирование до решения запрещено.
|
|
73
83
|
|
|
74
84
|
Для GitHub трекера статус issue задаётся label-ом (одновременно только один статус из набора):
|
|
75
85
|
- `TODO`
|
|
@@ -102,7 +112,7 @@ Name: Governance Watchdog Agent
|
|
|
102
112
|
|
|
103
113
|
Governance Watchdog Agent: verify governance gate,
|
|
104
114
|
task #12,
|
|
105
|
-
checklist "PRD(Описание+Проверяемость), hard criteria, user confirmation policy",
|
|
115
|
+
checklist "PRD(Описание+Проверяемость), architecture, verification matrix(unit/system/e2e_playwright/external_analysis), hard criteria, user confirmation policy, no-code-before-prd",
|
|
106
116
|
result PASS
|
|
107
117
|
```
|
|
108
118
|
|
|
@@ -154,7 +164,7 @@ repo your-org/your-repo,
|
|
|
154
164
|
short name "API редирект офферов",
|
|
155
165
|
owner "Engineering Agent",
|
|
156
166
|
description "Добавить API редиректа на офферы",
|
|
157
|
-
verifiability "strict: schema+contracts; statistical: p95 latency < 200ms; human: reviewer approval required",
|
|
167
|
+
verifiability "strict: schema+contracts; statistical: p95 latency < 200ms; human: reviewer approval required; architecture: contracts documented; tests_unit: required; tests_system: required; tests_e2e_playwright: required; external_analysis: required",
|
|
158
168
|
sprint "SPRINT-3"
|
|
159
169
|
```
|
|
160
170
|
|
|
@@ -204,7 +214,7 @@ Governance Watchdog Agent: verify implementation gate,
|
|
|
204
214
|
tracker __DEFAULT_TRACKER__,
|
|
205
215
|
task #12,
|
|
206
216
|
command "npm run meta:implementation-gate -- --task #12",
|
|
207
|
-
required checks "issue_status_in_progress, prd_sections_complete, verifiability(strict/statistical/human), branch_alignment",
|
|
217
|
+
required checks "issue_status_in_progress, prd_sections_complete, architecture_documented, verifiability(strict/statistical/human), tests_matrix(unit/system/e2e_playwright), external_analysis_defined, branch_alignment, no_code_before_pass",
|
|
208
218
|
result PASS
|
|
209
219
|
```
|
|
210
220
|
|
|
@@ -427,6 +437,11 @@ reason "вошло в релиз v0.1.2"
|
|
|
427
437
|
- strict:
|
|
428
438
|
- statistical:
|
|
429
439
|
- human:
|
|
440
|
+
- architecture:
|
|
441
|
+
- tests_unit:
|
|
442
|
+
- tests_system:
|
|
443
|
+
- tests_e2e_playwright:
|
|
444
|
+
- external_analysis:
|
|
430
445
|
- evidence:
|
|
431
446
|
|
|
432
447
|
### Что сделано
|
|
@@ -441,18 +456,19 @@ reason "вошло в релиз v0.1.2"
|
|
|
441
456
|
3. `PREPARE_TASK_BRANCH`.
|
|
442
457
|
4. `SET_STATUS -> IN_PROGRESS`.
|
|
443
458
|
5. `VERIFY_IMPLEMENTATION_GATE`.
|
|
444
|
-
6.
|
|
445
|
-
7.
|
|
446
|
-
8. `
|
|
447
|
-
9.
|
|
448
|
-
10. `
|
|
449
|
-
11. `
|
|
450
|
-
12.
|
|
451
|
-
13.
|
|
452
|
-
14.
|
|
453
|
-
15. `
|
|
454
|
-
16.
|
|
455
|
-
17.
|
|
456
|
-
18. `SET_STATUS ->
|
|
457
|
-
19. `
|
|
458
|
-
20.
|
|
459
|
+
6. Только после `VERIFY_IMPLEMENTATION_GATE: PASS` разрешена реализация.
|
|
460
|
+
7. Реализация + evidence.
|
|
461
|
+
8. `SET_STATUS -> REVIEW`.
|
|
462
|
+
9. `RUN_REVIEW_GATE` (получить report + `PASS_CANDIDATE`/`FAIL`).
|
|
463
|
+
10. Пользователь подтверждает review (`Review Approved: yes`).
|
|
464
|
+
11. `RUN_REVIEW_GATE` -> `PASS_CONFIRMED`.
|
|
465
|
+
12. `COMMIT_BY_NAME` только после review PASS_CONFIRMED и отдельного подтверждения пользователя на коммит.
|
|
466
|
+
13. Push + open PR в целевую ветку по Git Flow Lite.
|
|
467
|
+
14. `RUN_MR_REVIEW_GATE` (получить report + `PASS_CANDIDATE`/`FAIL`).
|
|
468
|
+
15. Пользователь подтверждает MR review (`MR Review Approved: yes`).
|
|
469
|
+
16. `RUN_MR_REVIEW_GATE` -> `PASS_CONFIRMED`.
|
|
470
|
+
17. Merge PR по Git Flow Lite.
|
|
471
|
+
18. `SET_STATUS -> READY`.
|
|
472
|
+
19. `SET_STATUS -> DONE` только после подтверждения пользователя.
|
|
473
|
+
20. `PREPARE_RELEASE_NOTE` (какие задачи вошли в релиз).
|
|
474
|
+
21. Для релизных задач после публикации: `MARK_TASKS_PUBLISH` (`SET_STATUS -> PUBLISH` для всех вошедших задач).
|