@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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k0t0vich/meta-agents-template",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Template system for verification-first agentic development",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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` только после фактической публикации.
@@ -1,3 +1,4 @@
1
1
  Role: Verifier Designer Agent
2
2
  Goal: определить strict/statistical/human проверки.
3
+ Rule: verification plan обязан включать `tests_unit`, `tests_system`, `tests_e2e_playwright` и `external_analysis`.
3
4
  Output: verification plan и evidence mapping.
@@ -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
- if (!hasStrict) {
248
- reasons.push("missing 'strict:' row in verifiability");
249
- }
250
- if (!hasStatistical) {
251
- reasons.push("missing 'statistical:' row in verifiability");
252
- }
253
- if (!hasHuman) {
254
- reasons.push("missing 'human:' row in verifiability");
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 { resolveLockedTrackerProvider } from "./tracker/provider-lock.mjs";
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
- async function main() {
43
- const args = process.argv.slice(2);
44
- const validateLocalCache = args.includes("--validate-local-cache");
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
- let trackerProvider = "";
47
- try {
48
- trackerProvider = resolveLockedTrackerProvider(process.cwd());
49
- } catch (error) {
50
- console.error(`Governance FAIL: ${error.message}`);
51
- process.exit(1);
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
- if (!/(^|\n)\s*-\s*strict\s*:/i.test(verifiability)) {
176
- blockers.push("missing 'strict:' row in verifiability");
177
- }
178
- if (!/(^|\n)\s*-\s*statistical\s*:/i.test(verifiability)) {
179
- blockers.push("missing 'statistical:' row in verifiability");
180
- }
181
- if (!/(^|\n)\s*-\s*human\s*:/i.test(verifiability)) {
182
- blockers.push("missing 'human:' row in verifiability");
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/verifiability: ${report.prdOk ? "PASS" : "FAIL"}`);
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):
@@ -2,6 +2,10 @@
2
2
 
3
3
  - Task ID:
4
4
  - Build/Test artifacts:
5
+ - Unit tests:
6
+ - System tests:
7
+ - Playwright e2e:
8
+ - External agent analysis:
5
9
  - Eval metrics:
6
10
  - Trace/Logs:
7
11
  - Commit refs:
@@ -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
- ## Checks
7
- - strict:
8
- - statistical:
9
- - human:
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
@@ -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
- Нельзя делегировать работу и нельзя закрывать задачу без формализованных критериев приёмки, PRD-блока `Проверяемость` и требуемых доказательств в трекере.
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. Реализация + evidence.
445
- 7. `SET_STATUS -> REVIEW`.
446
- 8. `RUN_REVIEW_GATE` (получить report + `PASS_CANDIDATE`/`FAIL`).
447
- 9. Пользователь подтверждает review (`Review Approved: yes`).
448
- 10. `RUN_REVIEW_GATE` -> `PASS_CONFIRMED`.
449
- 11. `COMMIT_BY_NAME` только после review PASS_CONFIRMED и отдельного подтверждения пользователя на коммит.
450
- 12. Push + open PR в целевую ветку по Git Flow Lite.
451
- 13. `RUN_MR_REVIEW_GATE` (получить report + `PASS_CANDIDATE`/`FAIL`).
452
- 14. Пользователь подтверждает MR review (`MR Review Approved: yes`).
453
- 15. `RUN_MR_REVIEW_GATE` -> `PASS_CONFIRMED`.
454
- 16. Merge PR по Git Flow Lite.
455
- 17. `SET_STATUS -> READY`.
456
- 18. `SET_STATUS -> DONE` только после подтверждения пользователя.
457
- 19. `PREPARE_RELEASE_NOTE` (какие задачи вошли в релиз).
458
- 20. Для релизных задач после публикации: `MARK_TASKS_PUBLISH` (`SET_STATUS -> PUBLISH` для всех вошедших задач).
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` для всех вошедших задач).