code-ai-installer 4.1.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +3 -1
  2. package/dist/mcp/audit_ledger.d.ts +10 -0
  3. package/dist/mcp/audit_ledger.js +15 -0
  4. package/dist/mcp/cli.js +1 -0
  5. package/dist/mcp/tools/render_diff.d.ts +25 -0
  6. package/dist/mcp/tools/render_diff.js +138 -0
  7. package/dist/mcp/tools/sign_off.js +10 -5
  8. package/dist/mcp/tools/stubs.js +2 -0
  9. package/dist/shared/tools.d.ts +38 -0
  10. package/dist/shared/tools.js +24 -0
  11. package/domains/analytics/agents/conductor.md +15 -1
  12. package/domains/analytics/locales/en/agents/conductor.md +15 -1
  13. package/domains/content/agents/conductor.md +15 -1
  14. package/domains/content/locales/en/agents/conductor.md +15 -1
  15. package/domains/development/.agents/skills/mcp-integration/SKILL.md +3 -1
  16. package/domains/development/.agents/workflows/audit.md +25 -0
  17. package/domains/development/.agents/workflows/pipeline-rules.md +1 -0
  18. package/domains/development/AGENTS.md +1 -0
  19. package/domains/development/agents/architect.md +1 -1
  20. package/domains/development/agents/auditor.md +4 -3
  21. package/domains/development/agents/conductor.md +4 -1
  22. package/domains/development/agents/devops.md +1 -1
  23. package/domains/development/agents/reviewer.md +2 -1
  24. package/domains/development/agents/senior_full_stack.md +1 -1
  25. package/domains/development/agents/tester.md +1 -1
  26. package/domains/development/locales/en/.agents/skills/mcp-integration/SKILL.md +3 -1
  27. package/domains/development/locales/en/.agents/workflows/audit.md +25 -0
  28. package/domains/development/locales/en/.agents/workflows/pipeline-rules.md +1 -0
  29. package/domains/development/locales/en/AGENTS.md +2 -0
  30. package/domains/development/locales/en/agents/architect.md +1 -1
  31. package/domains/development/locales/en/agents/auditor.md +4 -3
  32. package/domains/development/locales/en/agents/conductor.md +4 -1
  33. package/domains/development/locales/en/agents/devops.md +1 -1
  34. package/domains/development/locales/en/agents/reviewer.md +2 -1
  35. package/domains/development/locales/en/agents/senior_full_stack.md +1 -1
  36. package/domains/development/locales/en/agents/tester.md +1 -1
  37. package/domains/product/agents/conductor.md +15 -1
  38. package/domains/product/locales/en/agents/conductor.md +15 -1
  39. package/package.json +1 -1
package/README.md CHANGED
@@ -157,8 +157,10 @@ Depending on `--target`, `code-ai` restructures your project:
157
157
 
158
158
  ## 🧬 Versions & migration
159
159
 
160
- `code-ai-installer` is on **v4.0.0**.
160
+ `code-ai-installer` is on **v4.3.0**.
161
161
 
162
+ - **v4.3.0** — `render_diff` MCP tool (unified diff → a standalone HTML review page); MCP gate-flow + stop-at-user-gate sections added to the content / analytics / product conductors; Auditor trigger — a `/audit` command plus a Release-Gate nudge that surfaces after every 3rd completed run (development pilot).
163
+ - **v4.1.0** — MCP servers now register in your **global (user-scope)** config via a direct, idempotent `~/.claude.json` merge (no dependency on the `claude` CLI); the conductor halts at each user gate — one at a time, no batching, no auto-pass on green.
162
164
  - **v4.0.0** — consolidated the previously separate `code-ai-mcp` and types packages into this single package with **two bins** (`code-ai` + `code-ai-mcp`). Installing the CLI now also delivers the MCP server; for Claude it is auto-registered in your global (user-scope) MCP config. Existing 3.x CLI behavior is unchanged.
163
165
  - **v3.0.0 (breaking)** — removed the legacy flat root layout (`AGENTS.md` + `agents/` + `.agents/` at package root); the CLI now reads exclusively from `domains/<id>/`. **Migrating from v2.x:** add `--domain <development|content|analytics|product>` to every CLI call. If you used a custom `--project-dir`, restructure it to `domains/<id>/` instead of a flat layout.
164
166
 
@@ -10,3 +10,13 @@ export declare function readLedger(): Promise<RunScorecard[]>;
10
10
  * break a sign-off (telemetry is never load-bearing for the gate).
11
11
  */
12
12
  export declare function recordRunScorecard(state: TaskState): Promise<void>;
13
+ /** Number of COMPLETED (RG-signed) runs in the ledger. */
14
+ export declare function countCompletedRuns(): Promise<number>;
15
+ /**
16
+ * A1 cadence (Variant A1): surface an Auditor nudge on every 3rd completed run
17
+ * (3, 6, 9, …). Stateless — no last-audit marker — so it re-reminds until the
18
+ * user runs /audit. Surfacing only; returns undefined when no nudge is due.
19
+ */
20
+ export declare function auditNudgeFor(completedRuns: number): {
21
+ runs_total: number;
22
+ } | undefined;
@@ -80,3 +80,18 @@ export async function recordRunScorecard(state) {
80
80
  const extras = await readSideCounts(state.task_id);
81
81
  await appendScorecard(buildScorecard(state, extras));
82
82
  }
83
+ /** Number of COMPLETED (RG-signed) runs in the ledger. */
84
+ export async function countCompletedRuns() {
85
+ const cards = await readLedger();
86
+ return cards.filter((c) => c.completed).length;
87
+ }
88
+ /**
89
+ * A1 cadence (Variant A1): surface an Auditor nudge on every 3rd completed run
90
+ * (3, 6, 9, …). Stateless — no last-audit marker — so it re-reminds until the
91
+ * user runs /audit. Surfacing only; returns undefined when no nudge is due.
92
+ */
93
+ export function auditNudgeFor(completedRuns) {
94
+ return completedRuns >= 3 && completedRuns % 3 === 0
95
+ ? { runs_total: completedRuns }
96
+ : undefined;
97
+ }
package/dist/mcp/cli.js CHANGED
@@ -56,6 +56,7 @@ const TOOL_DESCRIPTIONS = {
56
56
  dependency_supply_chain: "[stub] Check supply chain (npm audit, Socket integration, license check).",
57
57
  docker_compose: "[stub] Run docker compose up/down for a target.",
58
58
  e2e_playwright: "[stub] Run Playwright end-to-end suite.",
59
+ render_diff: "Render a unified diff (e.g. `git diff`) into a colored, per-file, line-numbered HTML review page written to the OS temp dir. Returns the path + a file:// URL the user opens in a browser. Use at the REV gate to present code changes for review. Informational only — the file lives in temp (cleared on reboot), never in the project.",
59
60
  };
60
61
  function buildServer() {
61
62
  const dispatch = new CodeAiMcpServer();
@@ -0,0 +1,25 @@
1
+ import { type RenderDiffInput, type RenderDiffOutput } from "../../shared/index.js";
2
+ type RowKind = "hunk" | "add" | "del" | "ctx";
3
+ interface DiffRow {
4
+ kind: RowKind;
5
+ text: string;
6
+ o: number | "";
7
+ n: number | "";
8
+ }
9
+ export interface DiffFile {
10
+ name: string;
11
+ added: number;
12
+ removed: number;
13
+ rows: DiffRow[];
14
+ }
15
+ /** Parse a unified diff into per-file rows with old/new line numbers. Pure. */
16
+ export declare function parseUnifiedDiff(raw: string): DiffFile[];
17
+ /** Render parsed diff files into a self-contained HTML page. Pure. */
18
+ export declare function renderDiffHtml(diff: string, title: string): {
19
+ html: string;
20
+ files: number;
21
+ added: number;
22
+ removed: number;
23
+ };
24
+ export declare function renderDiff(input: RenderDiffInput): Promise<RenderDiffOutput>;
25
+ export {};
@@ -0,0 +1,138 @@
1
+ import { writeFile } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { createHash } from "node:crypto";
6
+ /**
7
+ * render_diff — turn a unified diff into a colored, per-file, line-numbered HTML
8
+ * review page and write it to the OS temp dir.
9
+ *
10
+ * Why a tool (not a loose script): code reviews in the pipeline are presented as
11
+ * an HTML diff the user opens via a file:// link. Shipping it as an MCP tool keeps
12
+ * it version-controlled, testable, and reachable wherever the server runs.
13
+ *
14
+ * The output is INFORMATIONAL only — it lives in the system temp dir (cleared on
15
+ * reboot), never in the project, so it pollutes nothing and needs no cleanup.
16
+ * Self-contained: no deps, no network.
17
+ */
18
+ const esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
19
+ /** Parse a unified diff into per-file rows with old/new line numbers. Pure. */
20
+ export function parseUnifiedDiff(raw) {
21
+ const blocks = raw.split(/^diff --git /m).filter(Boolean);
22
+ const files = [];
23
+ for (const b of blocks) {
24
+ const lines = ("diff --git " + b).split("\n");
25
+ const header = lines[0];
26
+ const m = header.match(/a\/(.+?) b\/(.+)$/);
27
+ const name = m ? m[2] : header;
28
+ let added = 0;
29
+ let removed = 0;
30
+ const rows = [];
31
+ let oldLn = 0;
32
+ let newLn = 0;
33
+ for (const ln of lines) {
34
+ if (ln.startsWith("diff --git") ||
35
+ ln.startsWith("index ") ||
36
+ ln.startsWith("--- ") ||
37
+ ln.startsWith("+++ "))
38
+ continue;
39
+ const hunk = ln.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
40
+ if (hunk) {
41
+ oldLn = Number(hunk[1]);
42
+ newLn = Number(hunk[2]);
43
+ rows.push({ kind: "hunk", text: ln, o: "", n: "" });
44
+ continue;
45
+ }
46
+ if (ln.startsWith("+")) {
47
+ added++;
48
+ rows.push({ kind: "add", text: ln.slice(1), o: "", n: newLn++ });
49
+ }
50
+ else if (ln.startsWith("-")) {
51
+ removed++;
52
+ rows.push({ kind: "del", text: ln.slice(1), o: oldLn++, n: "" });
53
+ }
54
+ else if (ln.startsWith("\\")) {
55
+ // "" — skip
56
+ }
57
+ else {
58
+ rows.push({ kind: "ctx", text: ln.slice(1), o: oldLn++, n: newLn++ });
59
+ }
60
+ }
61
+ files.push({ name, added, removed, rows });
62
+ }
63
+ return files;
64
+ }
65
+ /** Render parsed diff files into a self-contained HTML page. Pure. */
66
+ export function renderDiffHtml(diff, title) {
67
+ const files = parseUnifiedDiff(diff);
68
+ const fileSections = files
69
+ .map((f, i) => {
70
+ const rowsHtml = f.rows
71
+ .map((r) => {
72
+ if (r.kind === "hunk")
73
+ return `<tr class="hunk"><td class="ln"></td><td class="ln"></td><td class="code">${esc(r.text)}</td></tr>`;
74
+ const sign = r.kind === "add" ? "+" : r.kind === "del" ? "-" : " ";
75
+ return `<tr class="${r.kind}"><td class="ln">${r.o}</td><td class="ln">${r.n}</td><td class="code"><span class="sign">${sign}</span>${esc(r.text)}</td></tr>`;
76
+ })
77
+ .join("\n");
78
+ return `<section id="f${i}">
79
+ <h2>${esc(f.name)} <span class="stat"><span class="plus">+${f.added}</span> <span class="minus">-${f.removed}</span></span></h2>
80
+ <table>${rowsHtml}</table>
81
+ </section>`;
82
+ })
83
+ .join("\n");
84
+ const added = files.reduce((s, f) => s + f.added, 0);
85
+ const removed = files.reduce((s, f) => s + f.removed, 0);
86
+ const nav = files
87
+ .map((f, i) => `<a href="#f${i}">${esc(f.name.split("/").pop() ?? f.name)}</a>`)
88
+ .join("");
89
+ const html = `<!doctype html><html lang="en"><head><meta charset="utf-8">
90
+ <title>${esc(title)}</title>
91
+ <style>
92
+ :root { color-scheme: light dark; }
93
+ body { font: 13px/1.5 ui-monospace, "Cascadia Code", Consolas, monospace; margin: 0; background:#0d1117; color:#c9d1d9; }
94
+ header { padding: 16px 24px; border-bottom: 1px solid #30363d; position: sticky; top:0; background:#0d1117; }
95
+ header h1 { font: 600 16px system-ui, sans-serif; margin: 0 0 4px; }
96
+ header .summary { font: 13px system-ui, sans-serif; color:#8b949e; }
97
+ .plus { color:#3fb950; } .minus { color:#f85149; }
98
+ section { margin: 20px 24px; border: 1px solid #30363d; border-radius: 8px; overflow:hidden; }
99
+ section h2 { font: 600 13px ui-monospace, monospace; margin:0; padding:10px 14px; background:#161b22; border-bottom:1px solid #30363d; }
100
+ .stat { float:right; font-weight:400; }
101
+ table { border-collapse: collapse; width:100%; }
102
+ td { padding: 0 6px; white-space: pre-wrap; word-break: break-word; vertical-align: top; }
103
+ td.ln { width:1%; text-align:right; color:#6e7681; user-select:none; border-right:1px solid #21262d; padding:0 8px; }
104
+ td.code { width:100%; }
105
+ .sign { display:inline-block; width:1ch; color:#6e7681; }
106
+ tr.add { background: rgba(63,185,80,.15); } tr.add .sign { color:#3fb950; }
107
+ tr.del { background: rgba(248,81,73,.15); } tr.del .sign { color:#f85149; }
108
+ tr.hunk td { background:#161b22; color:#8b949e; padding:4px 14px; }
109
+ nav { padding: 0 24px; font: 13px system-ui, sans-serif; }
110
+ nav a { color:#58a6ff; text-decoration:none; display:inline-block; margin:2px 12px 2px 0; }
111
+ </style></head><body>
112
+ <header>
113
+ <h1>${esc(title)}</h1>
114
+ <div class="summary">${files.length} files · <span class="plus">+${added}</span> <span class="minus">-${removed}</span></div>
115
+ </header>
116
+ <nav>${nav}</nav>
117
+ ${fileSections}
118
+ </body></html>`;
119
+ return { html, files: files.length, added, removed };
120
+ }
121
+ /** Slugify a label for use in a temp filename. */
122
+ function slug(s) {
123
+ return (s
124
+ .toLowerCase()
125
+ .replace(/[^a-z0-9]+/g, "-")
126
+ .replace(/^-+|-+$/g, "")
127
+ .slice(0, 40) || "review");
128
+ }
129
+ export async function renderDiff(input) {
130
+ const title = input.title ?? "Diff review";
131
+ const { html, files, added, removed } = renderDiffHtml(input.diff, title);
132
+ // Content-hashed name → same diff reuses one file; lands in the OS temp dir
133
+ // (cleared on reboot), never in the project.
134
+ const hash = createHash("sha1").update(input.diff).digest("hex").slice(0, 8);
135
+ const path = join(tmpdir(), `code-ai-diff-${slug(input.task_id ?? title)}-${hash}.html`);
136
+ await writeFile(path, html, "utf8");
137
+ return { path, file_url: pathToFileURL(path).href, files, added, removed };
138
+ }
@@ -1,6 +1,6 @@
1
1
  import { getGateConfig, loadPipeline } from "../pipeline.js";
2
2
  import { readTaskState, writeTaskState } from "../task_state.js";
3
- import { recordRunScorecard } from "../audit_ledger.js";
3
+ import { recordRunScorecard, countCompletedRuns, auditNudgeFor } from "../audit_ledger.js";
4
4
  import { resolveActiveDomain } from "../config.js";
5
5
  /**
6
6
  * Records a sign-off event for the task's current gate. Validates that:
@@ -27,7 +27,9 @@ export async function signOff(input) {
27
27
  switch (gateCfg.sign_off_policy) {
28
28
  case "user":
29
29
  if (input.signer !== "user") {
30
- throw new Error(`sign_off: gate ${input.gate} requires signer 'user' (policy=user), got '${input.signer}'`);
30
+ throw new Error(`sign_off: gate ${input.gate} requires signer 'user' (policy=user), got '${input.signer}'. ` +
31
+ `This is a USER gate — HALT: present the ${input.gate} artifact and request the user's sign_off(signer='user') for THIS gate. ` +
32
+ `Do not auto-pass it, do not batch it with other gates, and do not begin any downstream-gate work until it is signed.`);
31
33
  }
32
34
  break;
33
35
  case "mcp_auto_pass":
@@ -56,15 +58,18 @@ export async function signOff(input) {
56
58
  });
57
59
  await writeTaskState(state);
58
60
  // Auditor telemetry: when the terminal gate is signed, the run is complete —
59
- // append a scorecard to the local ledger. Best-effort: a ledger failure must
60
- // NEVER break a sign-off (telemetry is not load-bearing for the gate).
61
+ // append a scorecard to the local ledger, then compute the /audit nudge.
62
+ // Best-effort: a ledger failure (or nudge failure) must NEVER break a
63
+ // sign-off (telemetry is not load-bearing for the gate).
64
+ let audit_nudge;
61
65
  if (input.gate === "RG") {
62
66
  try {
63
67
  await recordRunScorecard(state);
68
+ audit_nudge = auditNudgeFor(await countCompletedRuns());
64
69
  }
65
70
  catch {
66
71
  /* swallow — see contract in audit_ledger.recordRunScorecard */
67
72
  }
68
73
  }
69
- return { signed: true, signer: input.signer, timestamp };
74
+ return { signed: true, signer: input.signer, timestamp, ...(audit_nudge ? { audit_nudge } : {}) };
70
75
  }
@@ -31,6 +31,7 @@ import { reviewProposal } from "./review_proposal.js";
31
31
  import { e2ePlaywright } from "./e2e_playwright.js";
32
32
  import { dockerCompose } from "./docker_compose.js";
33
33
  import { dependencySupplyChain } from "./dependency_supply_chain.js";
34
+ import { renderDiff } from "./render_diff.js";
34
35
  /** Thrown by every stub until the real implementation lands. */
35
36
  export class NotImplementedError extends Error {
36
37
  constructor(tool) {
@@ -83,4 +84,5 @@ export const DEFAULT_HANDLERS = {
83
84
  dependency_supply_chain: dependencySupplyChain,
84
85
  docker_compose: dockerCompose,
85
86
  e2e_playwright: e2ePlaywright,
87
+ render_diff: renderDiff,
86
88
  };
@@ -687,6 +687,10 @@ export declare const SignOffInput: z.ZodObject<{
687
687
  }>;
688
688
  evidence: z.ZodOptional<z.ZodUnknown>;
689
689
  }, z.core.$strip>;
690
+ /** Surfacing-only Auditor reminder, emitted when completed runs hit the A1 cadence (every 3rd). */
691
+ export declare const AuditNudge: z.ZodObject<{
692
+ runs_total: z.ZodNumber;
693
+ }, z.core.$strip>;
690
694
  export declare const SignOffOutput: z.ZodObject<{
691
695
  signed: z.ZodLiteral<true>;
692
696
  signer: z.ZodEnum<{
@@ -695,6 +699,9 @@ export declare const SignOffOutput: z.ZodObject<{
695
699
  system: "system";
696
700
  }>;
697
701
  timestamp: z.ZodString;
702
+ audit_nudge: z.ZodOptional<z.ZodObject<{
703
+ runs_total: z.ZodNumber;
704
+ }, z.core.$strip>>;
698
705
  }, z.core.$strip>;
699
706
  export type SignOffInput = z.infer<typeof SignOffInput>;
700
707
  export type SignOffOutput = z.infer<typeof SignOffOutput>;
@@ -1578,6 +1585,20 @@ export declare const E2EPlaywrightOutput: z.ZodObject<{
1578
1585
  }, z.core.$strip>;
1579
1586
  export type E2EPlaywrightInput = z.infer<typeof E2EPlaywrightInput>;
1580
1587
  export type E2EPlaywrightOutput = z.infer<typeof E2EPlaywrightOutput>;
1588
+ export declare const RenderDiffInput: z.ZodObject<{
1589
+ diff: z.ZodString;
1590
+ title: z.ZodOptional<z.ZodString>;
1591
+ task_id: z.ZodOptional<z.ZodString>;
1592
+ }, z.core.$strip>;
1593
+ export declare const RenderDiffOutput: z.ZodObject<{
1594
+ path: z.ZodString;
1595
+ file_url: z.ZodString;
1596
+ files: z.ZodNumber;
1597
+ added: z.ZodNumber;
1598
+ removed: z.ZodNumber;
1599
+ }, z.core.$strip>;
1600
+ export type RenderDiffInput = z.infer<typeof RenderDiffInput>;
1601
+ export type RenderDiffOutput = z.infer<typeof RenderDiffOutput>;
1581
1602
  export declare const TOOL_REGISTRY: {
1582
1603
  readonly load_role: {
1583
1604
  readonly input: z.ZodObject<{
@@ -2245,6 +2266,9 @@ export declare const TOOL_REGISTRY: {
2245
2266
  system: "system";
2246
2267
  }>;
2247
2268
  timestamp: z.ZodString;
2269
+ audit_nudge: z.ZodOptional<z.ZodObject<{
2270
+ runs_total: z.ZodNumber;
2271
+ }, z.core.$strip>>;
2248
2272
  }, z.core.$strip>;
2249
2273
  };
2250
2274
  readonly submit_artifact: {
@@ -3017,5 +3041,19 @@ export declare const TOOL_REGISTRY: {
3017
3041
  }, z.core.$strip>>>;
3018
3042
  }, z.core.$strip>;
3019
3043
  };
3044
+ readonly render_diff: {
3045
+ readonly input: z.ZodObject<{
3046
+ diff: z.ZodString;
3047
+ title: z.ZodOptional<z.ZodString>;
3048
+ task_id: z.ZodOptional<z.ZodString>;
3049
+ }, z.core.$strip>;
3050
+ readonly output: z.ZodObject<{
3051
+ path: z.ZodString;
3052
+ file_url: z.ZodString;
3053
+ files: z.ZodNumber;
3054
+ added: z.ZodNumber;
3055
+ removed: z.ZodNumber;
3056
+ }, z.core.$strip>;
3057
+ };
3020
3058
  };
3021
3059
  export type ToolName = keyof typeof TOOL_REGISTRY;
@@ -159,10 +159,16 @@ export const SignOffInput = z.object({
159
159
  /** Evidence — for mcp signer this is the auto_check tool output; for user it's free-form. */
160
160
  evidence: z.unknown().optional(),
161
161
  });
162
+ /** Surfacing-only Auditor reminder, emitted when completed runs hit the A1 cadence (every 3rd). */
163
+ export const AuditNudge = z.object({
164
+ runs_total: z.number().int().nonnegative(),
165
+ });
162
166
  export const SignOffOutput = z.object({
163
167
  signed: z.literal(true),
164
168
  signer: Signer,
165
169
  timestamp: z.string(),
170
+ /** Present only when RG is signed AND the run count hits the cadence. Best-effort; never load-bearing. */
171
+ audit_nudge: AuditNudge.optional(),
166
172
  });
167
173
  // ─── submit_artifact ─────────────────────────────────────────────────────────
168
174
  export const SubmitArtifactInput = z.object({
@@ -598,6 +604,23 @@ export const E2EPlaywrightOutput = z.object({
598
604
  failed: z.number().int().nonnegative(),
599
605
  failures: z.array(ExceptionItem).default([]),
600
606
  });
607
+ export const RenderDiffInput = z.object({
608
+ /** A unified diff (e.g. the output of `git diff`). */
609
+ diff: z.string().min(1),
610
+ /** Heading shown at the top of the review page. */
611
+ title: z.string().optional(),
612
+ /** Optional task id — only used to label the output filename. */
613
+ task_id: TaskId.optional(),
614
+ });
615
+ export const RenderDiffOutput = z.object({
616
+ /** Absolute path of the written HTML file (in the OS temp dir). */
617
+ path: z.string(),
618
+ /** file:// URL the user can open in a browser. */
619
+ file_url: z.string(),
620
+ files: z.number().int().nonnegative(),
621
+ added: z.number().int().nonnegative(),
622
+ removed: z.number().int().nonnegative(),
623
+ });
601
624
  // ════════════════════════════════════════════════════════════════════════════
602
625
  // TOOL REGISTRY — name → { input, output } for runtime dispatch
603
626
  // ════════════════════════════════════════════════════════════════════════════
@@ -639,4 +662,5 @@ export const TOOL_REGISTRY = {
639
662
  },
640
663
  docker_compose: { input: DockerComposeInput, output: DockerComposeOutput },
641
664
  e2e_playwright: { input: E2EPlaywrightInput, output: E2EPlaywrightOutput },
665
+ render_diff: { input: RenderDiffInput, output: RenderDiffOutput },
642
666
  };
@@ -5,7 +5,7 @@ domain: analytics
5
5
  signs_off_at:
6
6
  - RELEASE_GATE
7
7
  tool_allowlist: role:conductor
8
- budget_lines: 459
8
+ budget_lines: 473
9
9
  schema_version: 1
10
10
  ---
11
11
 
@@ -360,6 +360,20 @@ $handoff → RES-02 (Researcher Beta).
360
360
 
361
361
  ---
362
362
 
363
+ ## MCP-интеграция и операционные гарантии
364
+
365
+ Дирижёр оркестрирует весь поток гейтов через машину состояний `code-ai` MCP — общий поток см. в `analytics-pipeline-rules.md` § «Машина гейтов (code-ai MCP)». Conductor-specific операционные гарантии:
366
+
367
+ - **Оркестрация гейтов** — Дирижёр ведёт последовательность гейтов выбранного режима через MCP: `classify_gate` (на какой гейт ложится задача), `current_gate` (где сейчас), `advance_gate` (переход к следующему гейту только после deliverable + Handoff Envelope). Переход без полного Handoff Envelope → `advance_gate` блокирует.
368
+ - **`sign_off` — все гейты `user`, Дирижёр не подписывает за пользователя** — в аналитике каждый гейт закрывает ПОЛЬЗОВАТЕЛЬ. Дирижёр ОСТАНАВЛИВАЕТСЯ, показывает артефакт гейта и запрашивает `sign_off(signer="user")` — по одному гейту, без батчинга нескольких подтверждений, и не начинает работу следующего гейта, пока текущий не подписан. Авто-пас на зелёном не применяется (домен суждения, детерминированных авто-чеков нет).
369
+ - **RELEASE_GATE** фиксируется как `sign_off(gate="RELEASE_GATE", signer="user", decision=..., evidence=<RG checklist>)` — не «прозой».
370
+ - **`request_decision` для эскалаций** — конфликты между агентами и waiver'ы обязательных пунктов: `request_decision(...)` → решает пользователь → `record_decision`. См. § Conflict Resolution Protocol.
371
+ - **`record_decision` для ADR-достойных решений** — зафиксированные конфликты и отклонения от брифа, согласованные с пользователем: `record_decision(signer="user", domain="analytics", task_id, decision_text)`.
372
+ - **Circuit breaker отключён** — в аналитике нет полосы откатов в стиле development (DEV/REV/OPS/TEST); возвраты идут через reverse `$handoff` (см. Reverse Handoff).
373
+ - **Degraded mode** — если MCP-поток недоступен: Дирижёр ведёт Master Checklist (`$board`) и статусы Handoff Envelope вручную, sign-off фиксируется явным "Approved" пользователя, эскалации — вручную.
374
+
375
+ ---
376
+
363
377
  ## Формат ответа агента
364
378
 
365
379
  ### Full Pipeline
@@ -5,7 +5,7 @@ domain: analytics
5
5
  signs_off_at:
6
6
  - RELEASE_GATE
7
7
  tool_allowlist: role:conductor
8
- budget_lines: 457
8
+ budget_lines: 471
9
9
  schema_version: 1
10
10
  ---
11
11
 
@@ -358,6 +358,20 @@ If an agent's submission encounters `$gates` failure:
358
358
 
359
359
  ---
360
360
 
361
+ ## MCP integration & operational guardrails
362
+
363
+ The Conductor orchestrates the whole gate-flow through the `code-ai` MCP state machine — for the general flow see `analytics-pipeline-rules.md` § "Gate machine (code-ai MCP)". Conductor-specific operational guardrails:
364
+
365
+ - **Gate-flow orchestration** — the Conductor drives the active mode's gate sequence through MCP: `classify_gate` (which gate the task lands on), `current_gate` (where we are now), `advance_gate` (move to the next gate only after the deliverable + Handoff Envelope). A transition without a complete Handoff Envelope → `advance_gate` blocks.
366
+ - **`sign_off` — all gates are `user`; the Conductor does not sign for the user** — in analytics every gate is closed by the USER. The Conductor STOPS, presents the gate artifact, and requests `sign_off(signer="user")` — one gate at a time, with no batching of approvals, and does NOT start next-gate work until the current one is signed. No auto-pass on green (a judgment domain, no deterministic auto-checks).
367
+ - **RELEASE_GATE** is recorded as `sign_off(gate="RELEASE_GATE", signer="user", decision=..., evidence=<RG checklist>)` — not prose approval.
368
+ - **`request_decision` for escalations** — conflicts between agents and waivers of mandatory items: `request_decision(...)` → the user decides → `record_decision`. See § Conflict Resolution Protocol.
369
+ - **`record_decision` for ADR-worthy outcomes** — recorded conflicts and brief deviations approved by the user: `record_decision(signer="user", domain="analytics", task_id, decision_text)`.
370
+ - **Circuit breaker disabled** — analytics has no development-style rollback lane (DEV/REV/OPS/TEST); returns go through reverse `$handoff` (see Reverse Handoff).
371
+ - **Degraded mode** — if the MCP flow is unavailable: the Conductor keeps the Master Checklist (`$board`) and Handoff Envelope statuses by hand, sign-off is recorded by the user's explicit "Approved", and escalations are manual.
372
+
373
+ ---
374
+
361
375
  ## Agent Response Template Format
362
376
 
363
377
  ### Full Pipeline Sequence
@@ -5,7 +5,7 @@ domain: content
5
5
  signs_off_at:
6
6
  - RELEASE_GATE
7
7
  tool_allowlist: role:conductor
8
- budget_lines: 393
8
+ budget_lines: 407
9
9
  schema_version: 1
10
10
  ---
11
11
 
@@ -267,6 +267,20 @@ Conductor отслеживает соответствие контента ис
267
267
 
268
268
  ---
269
269
 
270
+ ## MCP-интеграция и операционные гарантии
271
+
272
+ Дирижёр оркестрирует весь поток гейтов через машину состояний `code-ai` MCP — общий поток см. в `content-pipeline-rules.md` § «Машина гейтов (code-ai MCP)». Conductor-specific операционные гарантии:
273
+
274
+ - **Оркестрация гейтов** — Дирижёр ведёт последовательность гейтов выбранного режима через MCP: `classify_gate` (на какой гейт ложится задача), `current_gate` (где сейчас), `advance_gate` (переход к следующему гейту только после deliverable + Handoff Envelope). Переход без полного Handoff Envelope → `advance_gate` блокирует.
275
+ - **`sign_off` — все гейты `user`, Дирижёр не подписывает за пользователя** — в контенте каждый гейт закрывает ПОЛЬЗОВАТЕЛЬ. Дирижёр ОСТАНАВЛИВАЕТСЯ, показывает артефакт гейта и запрашивает `sign_off(signer="user")` — по одному гейту, без батчинга нескольких подтверждений, и не начинает работу следующего гейта, пока текущий не подписан. Авто-пас на зелёном не применяется (домен суждения, детерминированных авто-чеков нет).
276
+ - **RELEASE_GATE** фиксируется как `sign_off(gate="RELEASE_GATE", signer="user", decision=..., evidence=<RG checklist>)` — не «прозой».
277
+ - **`request_decision` для эскалаций** — конфликты между агентами и waiver'ы обязательных пунктов: `request_decision(...)` → решает пользователь → `record_decision`. См. § Conflict Resolution Protocol.
278
+ - **`record_decision` для ADR-достойных решений** — зафиксированные конфликты и отклонения от брифа, согласованные с пользователем: `record_decision(signer="user", domain="content", task_id, decision_text)`.
279
+ - **Circuit breaker отключён** — в контенте нет полосы откатов в стиле development (DEV/REV/OPS/TEST); возвраты идут через reverse `$handoff` (см. Reverse Handoff).
280
+ - **Degraded mode** — если MCP-поток недоступен: Дирижёр ведёт Master Checklist (`$board`) и статусы Handoff Envelope вручную, sign-off фиксируется явным "Approved" пользователя, эскалации — вручную.
281
+
282
+ ---
283
+
270
284
  ## Формат ответа Conductor (строго)
271
285
 
272
286
  ### Инициализация
@@ -5,7 +5,7 @@ domain: content
5
5
  signs_off_at:
6
6
  - RELEASE_GATE
7
7
  tool_allowlist: role:conductor
8
- budget_lines: 393
8
+ budget_lines: 407
9
9
  schema_version: 1
10
10
  ---
11
11
 
@@ -267,6 +267,20 @@ If two agents disagree (Reviewer vs Copywriter on edits, Strategist vs Copywrite
267
267
 
268
268
  ---
269
269
 
270
+ ## MCP integration & operational guardrails
271
+
272
+ The Conductor orchestrates the whole gate-flow through the `code-ai` MCP state machine — for the general flow see `content-pipeline-rules.md` § "Gate machine (code-ai MCP)". Conductor-specific operational guardrails:
273
+
274
+ - **Gate-flow orchestration** — the Conductor drives the active mode's gate sequence through MCP: `classify_gate` (which gate the task lands on), `current_gate` (where we are now), `advance_gate` (move to the next gate only after the deliverable + Handoff Envelope). A transition without a complete Handoff Envelope → `advance_gate` blocks.
275
+ - **`sign_off` — all gates are `user`; the Conductor does not sign for the user** — in content every gate is closed by the USER. The Conductor STOPS, presents the gate artifact, and requests `sign_off(signer="user")` — one gate at a time, with no batching of approvals, and does NOT start next-gate work until the current one is signed. No auto-pass on green (a judgment domain, no deterministic auto-checks).
276
+ - **RELEASE_GATE** is recorded as `sign_off(gate="RELEASE_GATE", signer="user", decision=..., evidence=<RG checklist>)` — not prose approval.
277
+ - **`request_decision` for escalations** — conflicts between agents and waivers of mandatory items: `request_decision(...)` → the user decides → `record_decision`. See § Conflict Resolution Protocol.
278
+ - **`record_decision` for ADR-worthy outcomes** — recorded conflicts and brief deviations approved by the user: `record_decision(signer="user", domain="content", task_id, decision_text)`.
279
+ - **Circuit breaker disabled** — content has no development-style rollback lane (DEV/REV/OPS/TEST); returns go through reverse `$handoff` (see Reverse Handoff).
280
+ - **Degraded mode** — if the MCP flow is unavailable: the Conductor keeps the Master Checklist (`$board`) and Handoff Envelope statuses by hand, sign-off is recorded by the user's explicit "Approved", and escalations are manual.
281
+
282
+ ---
283
+
270
284
  ## Conductor Response Format (Strict)
271
285
 
272
286
  ### Initialization
@@ -97,7 +97,7 @@ license: MIT
97
97
 
98
98
  **`advance_gate`** — продвинуть задачу в следующий gate. **Только после** того как все artefacts текущего gate submitted и sign_off проставлен.
99
99
 
100
- **`sign_off`** — подпись текущего gate. Sign_off без предыдущего `submit_artifact` — anti-pattern (см. §8). Сначала результат, потом подпись.
100
+ **`sign_off`** — подпись текущего gate. Sign_off без предыдущего `submit_artifact` — anti-pattern (см. §8). Сначала результат, потом подпись. **Кто подписывает — по `sign_off_policy` гейта:** user-гейты (PM/UX/ARCH/RG) требуют `signer="user"` — ОСТАНОВИСЬ и запроси подпись у пользователя, по одному гейту, без батчинга, и не начинай следующий gate пока текущий не подписан; исполнительские (DEV/REV/OPS/TEST, policy=either) можно подписать как `signer="mcp"` при выполненном DoD. Машина отвергнет `mcp`-подпись user-гейта.
101
101
 
102
102
  **Канонический ритуал gate:** `current_gate` (понять где ты) → `classify_gate` → если fork: `request_decision` → ждёшь → `record_decision` → продолжаешь → `submit_artifact` → `verify_claim` (где применимо) → `sign_off` → `advance_gate`.
103
103
 
@@ -139,6 +139,8 @@ license: MIT
139
139
 
140
140
  **`review_proposal`** — авторизовать переход статуса предложения (approve/reject для pending; пометить approved как applied) + обязательный отчёт. Применяет матрицу автономии + тумблер из `.code-ai/config.json`: `decided_by='auditor_auto'` может одобрить только low/additive и только при ВЫКЛЮЧЕННОМ гейте; destructive (high) и включённый гейт — всегда через user. Авто-добавление нового скила проходит дедуп-проверку: при пересечении с существующим скилом уходит к user, а не добавляется само. Только авторизация — сама запись в ассет это отдельный шаг submit_artifact/edit (см. next_step).
141
141
 
142
+ **`render_diff`** — отрендерить unified-diff (например вывод `git diff`) в цветную HTML-страницу ревью (по файлам, с номерами строк) в системный TEMP. Возвращает путь + `file://` URL для открытия в браузере. Зови на REV-гейте, чтобы показать изменения кода на ревью. Только информационный вывод — файл в TEMP (стирается при перезагрузке), проект не засоряет.
143
+
142
144
  ---
143
145
 
144
146
  ## 6. Группа 4 — Запись решений (6 инструментов + 1 служебный)
@@ -0,0 +1,25 @@
1
+ ---
2
+ description: Прогон Аудитора — оценка агентов/скилов по накопленным прогонам и черновики улучшений. Вне пайплайна, код задачи не трогает.
3
+ ---
4
+
5
+ # /audit — проход Аудитора (мета / сопровождение)
6
+
7
+ Аудитор стоит СБОКУ от пайплайна: гейты не подписывает, задачу и код пользователя не трогает. Он оценивает, как сработали агенты / скилы / воркфлоу на реальных прогонах, и предлагает улучшения (или добавление новых). Полный контракт — в роли `auditor`.
8
+
9
+ ## Когда запускать
10
+ - Вручную этой командой в любой момент — или по подсказке `audit_nudge`, которую `sign_off` возвращает после закрытия RG.
11
+ - Нужно **≥3 завершённых прогона** в леджере (`.code-ai/state/audit/runs.jsonl`). Меньше — данных мало, Аудитор молчит (малая выборка).
12
+
13
+ ## Поток
14
+ 1. `load_role auditor` — загрузить роль и её принципы (гипотезы, не вердикты; surfacing, не принуждение).
15
+ 2. `aggregate_run_metrics` — сухие числа по агентам / воркфлоу / скилам. **Обязательно прочитать `notes`** — там честные ограничения данных.
16
+ 3. Если `met_threshold=false` (прогонов <3) — остановиться, сообщить «данных мало», ничего не предлагать.
17
+ 4. Сформировать находки-гипотезы. На каждое предложение — `propose_change` (`change_kind`: `edit_minor` / `add_asset` / `destructive`). Оно попадает в стор как `pending` и **ничего не меняет**.
18
+ 5. Показать пользователю отчёт + `list_proposals` (что в очереди, с уровнем риска по матрице).
19
+ 6. Применение — только через `review_proposal` (approve) + запись в ассет (`submit_artifact` / правка). Гейт одобрения по умолчанию включён: без явного решения человека ничего не применяется. `destructive` — всегда через человека.
20
+
21
+ ## Принципы (из роли auditor)
22
+ - Гипотезы, не вердикты. Атрибуция со смирением (числа — корреляция, не причинность).
23
+ - Не оптимизировать метрику ради метрики (Goodhart); человек — бэкстоп. Никогда не действовать на n=1 (порог ≥3).
24
+ - Перед `add_asset` — дедуп-проверка пересечений; отчёт перечисляет добавления для последующей чистки.
25
+ - Пилот — домен `development`. Раскатка на другие домены — позже и совместно.
@@ -53,6 +53,7 @@ DEV (фикс+тест) → RG
53
53
 
54
54
  - К пользователю попадает только: гейты-суждения (PM/UX/ARCH/RG) и явная эскалация через `request_decision` (классификация `fork`).
55
55
  - Рутинные проходы пользователь не подтверждает.
56
+ - После закрытия RG `sign_off` может вернуть `audit_nudge` (накопилось ≥3 завершённых прогона, кратно 3) — показать одну строку: «📊 N прогонов — пора `/audit`» (Аудитор оценит агентов/скилы и предложит улучшения). Подсказка, не блокер.
56
57
 
57
58
  ## 🔁 Красный, Fix Cycle и Circuit Breaker
58
59
 
@@ -195,6 +195,7 @@ CONDUCTOR → DEV+TEST(Fix + self-check + GO/NO-GO)
195
195
 
196
196
  > **Выбор режима:** Conductor определяет по Decision Tree (см. `agents/conductor.md`).
197
197
  > Approved обязателен на **каждом** гейте, в любом режиме.
198
+ > **Ревью кода:** на REV-гейте diff показывается как HTML через MCP `render_diff` (file:// ссылка; файл в системном TEMP, не в проекте).
198
199
 
199
200
  ---
200
201
 
@@ -199,7 +199,7 @@ schema_version: 1
199
199
 
200
200
  ARCH gate ritual через MCP — общий flow см. в `$mcp-integration`. Architect-specific operational guardrails:
201
201
 
202
- - **`sign_off` для ARCH gate** — после финализации Architecture Doc + всех ADR + System Design Checklist: `sign_off(gate="ARCH", signer="architect", evidence=<architecture_doc_path + ADR_IDs>)`. Без подписи `advance_gate` не пропустит задачу в DEV.
202
+ - **`sign_off` для ARCH gate** — после финализации Architecture Doc + всех ADR + System Design Checklist: `sign_off(gate="ARCH", signer="user", evidence=<architecture_doc_path + ADR_IDs>)`. Без подписи `advance_gate` не пропустит задачу в DEV.
203
203
  - **`request_decision` для архитектурного выбора** — когда есть 2+ валидных решения с trade-offs (монолит vs микросервисы, ORM выбор, sync vs async pipeline): `request_decision(question, options=[plan_a, plan_b, plan_c], tradeoffs)`. Решение принимает пользователь, затем `record_decision` фиксирует ADR.
204
204
  - **`record_decision` для каждого ADR** — каждое архитектурное решение = ADR через `$adr-log`. `record_decision(signer="user", domain="development", task_id, decision_text)` после approve. Архитектурные ADR — основной аудит-trail архитектуры.
205
205
  - **Circuit Breaker (DEV-054) — destination, не source** — architect это **получатель** auto-route'а от MCP, не источник rollback'а. 2 consecutive DEV-rollback на REV/TEST → MCP блокирует return-to-DEV и роутит задачу в ARCH deep audit. Architect выполняет: current-state-analysis + system-design-checklist + design-patterns-reference review, выдаёт корректирующий ADR.
@@ -22,6 +22,7 @@ schema_version: 1
22
22
  - НЕ на каждом гейте и НЕ в фоне. Один проход, когда накопилось **≥3 завершённых прогона** (порог настраивается).
23
23
  - Ниже порога — молчит. На n=1 выводов не делает (малая выборка).
24
24
  - Per-gate телеметрию уже пишет стейт-машина; Аудитор делает один проход по накопленным данным.
25
+ - Запуск прохода: команда `/audit` (вручную) или подсказка `audit_nudge`, которую `sign_off` возвращает после RG.
25
26
 
26
27
  ---
27
28
 
@@ -49,20 +50,20 @@ schema_version: 1
49
50
 
50
51
  ---
51
52
 
52
- ## Модель автономии (ОПИСАНИЕ поведения; механизм — отдельный ADR)
53
+ ## Модель автономии (поведение; механизм — `propose_change` / `review_proposal`)
53
54
  - **По умолчанию: предлагает → человек одобряет.** Человек может отключить гейт одобрения.
54
55
  - **Когда автономия включена** (матрица):
55
56
  - **Сам, без спроса:** мелкие правки существующего (триггеры, `budget_lines`, `gates`, формулировки) + **ДОБАВЛЕНИЕ** новых агентов / скилов.
56
57
  - **Через человека даже в автономии:** разрушительное по существующему (удаление, крупная переписка, снятие возможностей).
57
58
  - **Всегда:** обязательный отчёт после любого автономного действия. Ничего невидимого.
58
59
  - **Дедуп при добавлении:** перед авто-добавлением скила — проверка пересечения (`related` + контролируемый словарь); отчёт перечисляет добавления для последующей чистки.
59
- - Сам механизм предложение→одобрение и тумблер автономии СЛЕДУЮЩИЙ шаг. Здесь зафиксирован только поведенческий контракт.
60
+ - Механизм предложение→одобрение и тумблер автономии уже реализованы (`propose_change` `review_proposal`: матрица рисков + дедуп). Проход запускается командой `/audit` или подсказкой после RG.
60
61
 
61
62
  ---
62
63
 
63
64
  ## MCP integration
64
65
  - **Читает:** `aggregate_run_metrics` (числа по агентам / воркфлоу / скилам) + его `notes`.
65
- - **Черновики правок** оформляет как артефакты через `submit_artifact` когда механизм предложений появится (item 4).
66
+ - **Черновики правок** оформляет через `propose_change` (стор `pending`, ничего не меняет); человек смотрит `list_proposals`, одобряет через `review_proposal`; запись в ассет — отдельным `submit_artifact` / правкой.
66
67
  - **НЕ зовёт** gate-инструменты (`classify_gate` / `sign_off` / `advance_gate`) — Аудитор вне стейт-машины.
67
68
  - Пилот — домен `development`. Раскатка на другие домены — позже и совместно (граница доменов).
68
69
 
@@ -297,7 +297,10 @@ Tester report + Handoff Envelope → Conductor. Check: DEMO-xx validated + UX-PA
297
297
  Conductor оркестрирует весь gate-flow через MCP — общий flow см. в `$mcp-integration`. Conductor-specific operational guardrails:
298
298
 
299
299
  - **Gate-flow orchestration** — Conductor ведёт пайплайн `PM → UX → ARCH → DEV → REV → OPS → TEST → RG` через MCP: `classify_gate` (на какой гейт ложится задача), `current_gate` (где сейчас), `advance_gate` (переход к следующей фазе только после артефактов + Handoff Envelope). Phase transition без полного Handoff Envelope → `advance_gate` блокирует.
300
- - **`sign_off` на всех 8 гейтах** Conductor подписывает PM/UX/ARCH/DEV/REV/OPS/TEST/RG. RG-решение фиксируется через MCP `sign_off` (NOT prose approval): `sign_off(gate="RG", signer="conductor", decision=GO|NO-GO|GO-with-conditions, evidence=<RG checklist + REV-xx + QA-xx>)`. Детали → `$release-gate` § Decision Recording.
300
+ - **`sign_off` — по политике гейта, НЕ «сам подписываю всё»** гейты двух классов:
301
+ - **User-гейты (PM/UX/ARCH/RG, policy=user)** — подписывает ПОЛЬЗОВАТЕЛЬ. Conductor ОСТАНАВЛИВАЕТСЯ, показывает артефакт гейта и запрашивает `sign_off(signer="user")` — по одному гейту, без батчинга нескольких подтверждений, и не начинает работу следующего гейта, пока текущий не подписан. Неприменимый гейт (UX для backend/тест-задачи) — тоже явный sign-off пользователя: показать как N/A и спросить, не авто-проходить как `mcp`.
302
+ - **Исполнительские гейты (DEV/REV/OPS/TEST, policy=either)** — Conductor может подписать сам: `sign_off(signer="mcp")` при выполненном DoD.
303
+ - **RG** фиксируется как `sign_off(gate="RG", signer="user", decision=GO|NO-GO|GO-with-conditions, evidence=<RG checklist + REV-xx + QA-xx>)` (NOT prose approval). Детали → `$release-gate` § Decision Recording.
301
304
  - **Circuit Breaker (DEV-054), MCP-enforced** — 2 последовательных DEV-rollback на REV/TEST → MCP блокирует return-to-DEV и auto-route в ARCH deep audit. Conductor НЕ обходит circuit breaker вручную. Полная логика → `$gates` § Circuit Breaker.
302
305
  - **`request_decision` для маршрутизации эскалаций** — конфликты между агентами (DEV vs ARCH, REV vs DEV, UX vs PM) и waiver'ы mandatory-пунктов: `request_decision(conflict_summary, options, tradeoffs)` → решает пользователь → `record_decision`. См. § Conflict Resolution Protocol.
303
306
  - **`record_decision` для ADR-достойных решений** — архитектурный дрейф, разрешённые конфликты, mandatory waiver'ы = ADR через `$adr-log`. `record_decision(signer="user", domain="development", task_id, decision_text)`.
@@ -213,7 +213,7 @@ lint → typecheck → unit tests → integration tests → build → deploy (st
213
213
 
214
214
  OPS gate ritual через MCP — общий flow см. в `$mcp-integration`. DevOps-specific operational guardrails:
215
215
 
216
- - **`sign_off` для OPS gate** — OPS-подпись это обязательное звено финальной RG-цепочки `DEV → REV → QA → OPS → RG` (см. `$release-gate`): `sign_off(gate="OPS", signer="devops", evidence=<RG confirmation checklist ниже>)`. Подпись **блокирует RG**, если хотя бы один пункт failed. Доказательство OPS-подписи:
216
+ - **`sign_off` для OPS gate** — OPS-подпись это обязательное звено финальной RG-цепочки `DEV → REV → QA → OPS → RG` (см. `$release-gate`): `sign_off(gate="OPS", signer="mcp", evidence=<RG confirmation checklist ниже>)`. Подпись **блокирует RG**, если хотя бы один пункт failed. Доказательство OPS-подписи:
217
217
  - HTTPS valid во всех prod-средах (cert expiry ≥ 30d)
218
218
  - Secrets rotation актуален (последняя rotation ≤ 90d для критичных ключей)
219
219
  - Rollback procedure протестирован за ≤ 30d
@@ -198,7 +198,8 @@ Reviewer обязан выдать отчёт, который может исп
198
198
 
199
199
  REV gate ritual через MCP — общий flow см. в `$mcp-integration`. Reviewer-specific operational guardrails:
200
200
 
201
- - **`sign_off` для REV gate** — после завершения ревью один MCP-вызов: `sign_off(gate="REV", signer="reviewer", evidence=<REV-xx_report_path или audit_trail link>)`. Без подписи `advance_gate` не пропустит задачу в OPS/TEST.
201
+ - **`render_diff` перед подписью REV** — покажи ревьюируемый diff как HTML-страницу: `render_diff(diff=<git diff>, title="REV-xx review")` отдай пользователю `file://` URL. Только информационно (файл в системном TEMP), затем подпись.
202
+ - **`sign_off` для REV gate** — после завершения ревью один MCP-вызов: `sign_off(gate="REV", signer="mcp", evidence=<REV-xx_report_path или audit_trail link>)`. Без подписи `advance_gate` не пропустит задачу в OPS/TEST.
202
203
  - **`request_decision` для P0 unresolved** — если P0 BLOCKER не решается технически (waiver-кандидат, конфликт с архитектурой): `request_decision(blocker_summary, options=[block, waive_with_compensating_control, escalate_to_architect], tradeoffs)`. Решение принимает пользователь, затем `record_decision` фиксирует ADR.
203
204
  - **`record_decision` для P0 waiver** — каждый waiver = ADR через `$adr-log` (persona-base principle 3: рисковые решения видимы). `record_decision(signer="user", domain="development", task_id, decision_text)` после approve.
204
205
  - **Circuit Breaker (DEV-054)** — 2 consecutive DEV-rollback на REV/TEST → MCP блокирует return-to-DEV, автоматически роутит задачу в ARCH deep audit (см. `$gates`). Reviewer не обходит circuit breaker manually.
@@ -200,7 +200,7 @@ REV проверяет это через `$tests-quality-review §2.G`. Без c
200
200
 
201
201
  DEV gate ritual через MCP — общий flow см. в `$mcp-integration`. SFS-specific operational guardrails:
202
202
 
203
- - **`sign_off` для DEV gate** — после завершения среза один MCP-вызов: `sign_off(gate="DEV", signer="senior_full_stack", evidence=<DEMO-xx envelope + green CI link; для tier 1-2 — RED_COMMIT_HASH + GREEN_COMMIT_HASH>)`. Содержание доказательства — это Test Integrity Discipline выше (Boundary Mocking + RED/GREEN hashes), здесь не пересказывается. Без подписи `advance_gate` не пропустит задачу в REV.
203
+ - **`sign_off` для DEV gate** — после завершения среза один MCP-вызов: `sign_off(gate="DEV", signer="mcp", evidence=<DEMO-xx envelope + green CI link; для tier 1-2 — RED_COMMIT_HASH + GREEN_COMMIT_HASH>)`. Содержание доказательства — это Test Integrity Discipline выше (Boundary Mocking + RED/GREEN hashes), здесь не пересказывается. Без подписи `advance_gate` не пропустит задачу в REV.
204
204
  - **`request_decision` для заблокированного P0** — если P0 не решается технически (файл > 500 строк не декомпозируется, guardrails не заданы архитектором, упрощение ломает acceptance): `request_decision(blocker_summary, options=[block, simplify_with_tech_debt, escalate_to_architect], tradeoffs)`. Решение принимает пользователь, затем `record_decision`.
205
205
  - **`record_decision` для tech-debt waiver** — каждое намеренное упрощение (`// TODO`) с риском = ADR через `$adr-log` (persona-base principle 3: рисковые решения видимы). `record_decision(signer="user", domain="development", task_id, decision_text)` после approve.
206
206
  - **Circuit Breaker (DEV-054)** — sfs — **источник** отката: 2 consecutive DEV-rollback на REV/TEST → MCP блокирует возврат в DEV и автоматически роутит задачу в ARCH deep audit (см. `$gates`). sfs не обходит circuit breaker и не переоткрывает задачу вручную — ждёт корректирующий ADR от архитектора.
@@ -219,7 +219,7 @@ Tester не обязан писать всю автоматизацию сам,
219
219
 
220
220
  TEST gate ritual через MCP — общий flow см. в `$mcp-integration`. Tester-specific operational guardrails:
221
221
 
222
- - **`sign_off` для TEST gate** — TEST-подпись это звено финальной RG-цепочки `DEV → REV → QA → OPS → RG` (см. `$release-gate`): `sign_off(gate="TEST", signer="tester", evidence=<QA-xx report + TID status>)`. Доказательство — tier-based GO logic из секции «Tier-based Release Recommendation logic» выше (mutation score ≥ 80%/60% для tier 1/2, flake rate < 1%, integrity audit clean, RED/GREEN hashes для tier 1-2), здесь не пересказывается. Без подписи `advance_gate` не пропустит релиз в RG.
222
+ - **`sign_off` для TEST gate** — TEST-подпись это звено финальной RG-цепочки `DEV → REV → QA → OPS → RG` (см. `$release-gate`): `sign_off(gate="TEST", signer="mcp", evidence=<QA-xx report + TID status>)`. Доказательство — tier-based GO logic из секции «Tier-based Release Recommendation logic» выше (mutation score ≥ 80%/60% для tier 1/2, flake rate < 1%, integrity audit clean, RED/GREEN hashes для tier 1-2), здесь не пересказывается. Без подписи `advance_gate` не пропустит релиз в RG.
223
223
  - **Action tools, которые Tester гоняет через MCP** — `e2e_playwright` для автоматизированных E2E spec-файлов (`$qa-e2e-playwright`); `run_tests` / `docker_compose` для regression-прогона после подтверждённого container reload (evidence от DevOps обязателен).
224
224
  - **`record_decision` для test-integrity finding** — block-merge на mutation regression или P0 integrity finding = ADR через `$adr-log`. `record_decision(signer="user", domain="development", task_id, decision_text)` после approve.
225
225
  - **`request_decision` для спорного NO-GO / waiver** — если NO-GO оспаривается или нужен waiver на регрессию mutation score с компенсацией: `request_decision(blocker_summary, options=[block_release, waive_with_compensating_control, escalate_to_architect], tradeoffs)`. Решение принимает пользователь, затем `record_decision`.
@@ -97,7 +97,7 @@ This is the gate-passage ritual. **Every gate** must follow these steps in order
97
97
 
98
98
  **`advance_gate`** — push the task into the next gate. **Only after** all artifacts of the current gate are submitted and sign_off is in place.
99
99
 
100
- **`sign_off`** — sign the current gate. Sign_off without a prior `submit_artifact` is an anti-pattern (see §8). Result first, signature second.
100
+ **`sign_off`** — sign the current gate. Sign_off without a prior `submit_artifact` is an anti-pattern (see §8). Result first, signature second. **Who signs depends on the gate's `sign_off_policy`:** user gates (PM/UX/ARCH/RG) require `signer="user"` — STOP and request the user's sign-off, one gate at a time, no batching, and do not start the next gate until the current one is signed; execution gates (DEV/REV/OPS/TEST, policy=either) may be signed as `signer="mcp"` once DoD is met. The machine rejects an `mcp` sign-off of a user gate.
101
101
 
102
102
  **Canonical gate ritual:** `current_gate` (understand where you are) → `classify_gate` → if fork: `request_decision` → wait → `record_decision` → continue → `submit_artifact` → `verify_claim` (where applicable) → `sign_off` → `advance_gate`.
103
103
 
@@ -139,6 +139,8 @@ Tools that **do** something in the project. Each answers one DoD question.
139
139
 
140
140
  **`review_proposal`** — authorize a proposal status transition (approve/reject a pending one; mark an approved one applied) plus a mandatory report. Applies the autonomy matrix + the `.code-ai/config.json` toggle: `decided_by='auditor_auto'` may approve only low/additive AND only when the gate is OFF; destructive (high) and gate-ON always require user. Auto-adding a new skill also runs an additive-dedup guard — on overlap with an existing skill it routes to user instead of auto-adding. Authorization only — the byte write into the asset is a separate submit_artifact/edit step (see next_step).
141
141
 
142
+ **`render_diff`** — render a unified diff (e.g. `git diff` output) into a colored, per-file, line-numbered HTML review page in the system temp dir. Returns the path + a `file://` URL to open in a browser. Call it at the REV gate to present code changes for review. Informational only — the file lives in temp (cleared on reboot), never in the project.
143
+
142
144
  ---
143
145
 
144
146
  ## 6. Group 4 — Recording decisions (6 tools + 1 utility)
@@ -0,0 +1,25 @@
1
+ ---
2
+ description: Auditor pass — evaluate agents/skills over accumulated runs and draft improvements. Beside the pipeline; does not touch the task's code.
3
+ ---
4
+
5
+ # /audit — Auditor pass (meta / maintenance)
6
+
7
+ The Auditor stands BESIDE the pipeline: it signs no gates and does not touch the user's task or code. It evaluates how agents / skills / workflows performed on real runs and proposes improvements (or new additions). Full contract — in the `auditor` role.
8
+
9
+ ## When to run
10
+ - Manually with this command at any time — or on the `audit_nudge` that `sign_off` returns after RG is closed.
11
+ - Needs **≥3 completed runs** in the ledger (`.code-ai/state/audit/runs.jsonl`). Fewer — too little data, the Auditor stays silent (small sample).
12
+
13
+ ## Flow
14
+ 1. `load_role auditor` — load the role and its principles (hypotheses not verdicts; surfacing, not enforcing).
15
+ 2. `aggregate_run_metrics` — dry numbers per agent / workflow / skill. **Read its `notes`** — the honest data limits live there.
16
+ 3. If `met_threshold=false` (fewer than 3 runs) — stop, say "too little data", propose nothing.
17
+ 4. Form hypotheses. For each proposal — `propose_change` (`change_kind`: `edit_minor` / `add_asset` / `destructive`). It lands in the store as `pending` and **changes nothing**.
18
+ 5. Show the user a report + `list_proposals` (what is queued, with the matrix risk tier).
19
+ 6. Apply only via `review_proposal` (approve) + the asset write (`submit_artifact` / edit). The approval gate is ON by default: nothing is applied without an explicit human decision. `destructive` — always via the human.
20
+
21
+ ## Principles (from the auditor role)
22
+ - Hypotheses, not verdicts. Attribution with humility (numbers are correlation, not causation).
23
+ - Do not optimize a metric for its own sake (Goodhart); the human is the backstop. Never act on n=1 (threshold ≥3).
24
+ - Before `add_asset` — an overlap dedup check; the report lists additions for later pruning.
25
+ - Pilot — the `development` domain. Roll-out to other domains is later and joint.
@@ -53,6 +53,7 @@ The machine flows silently; the user is pulled in only for judgment decisions.
53
53
 
54
54
  - The user sees only: judgment gates (PM/UX/ARCH/RG) and an explicit escalation via `request_decision` (a `fork` classification).
55
55
  - Routine passes are not confirmed by the user.
56
+ - After RG is closed `sign_off` may return `audit_nudge` (≥3 completed runs, a multiple of 3) — surface one line: «📊 N runs — time for `/audit`» (the Auditor evaluates agents/skills and proposes improvements). A hint, not a blocker.
56
57
 
57
58
  ## 🔁 Red, Fix Cycle and Circuit Breaker
58
59
 
@@ -162,6 +162,8 @@ Use skills (folders with `SKILL.md`). Full list:
162
162
  ## Gates (Pipeline)
163
163
  PM(PRD) -> UX(UX Spec) -> ARCH(Architecture/ADR/Contracts) -> DEV(TDD) -> REV(Security/Best) -> OPS(Infrastructure/CI-CD) -> TEST(Test plan/report) -> RG(Release Gate)
164
164
 
165
+ > **Code review:** at the REV gate the diff is presented as HTML via the MCP `render_diff` tool (file:// link; the file lives in the system temp dir, not the project).
166
+
165
167
  ---
166
168
 
167
169
  ## Mandatory function documentation rule
@@ -199,7 +199,7 @@ Canonical ADR format (Context / Decision / Consequences / Alternatives / Status
199
199
 
200
200
  ARCH gate ritual via MCP — general flow in `$mcp-integration`. Architect-specific operational guardrails:
201
201
 
202
- - **`sign_off` for ARCH gate** — after finalizing the Architecture Doc + all ADRs + System Design Checklist: `sign_off(gate="ARCH", signer="architect", evidence=<architecture_doc_path + ADR_IDs>)`. Without the signature `advance_gate` will not pass the task to DEV.
202
+ - **`sign_off` for ARCH gate** — after finalizing the Architecture Doc + all ADRs + System Design Checklist: `sign_off(gate="ARCH", signer="user", evidence=<architecture_doc_path + ADR_IDs>)`. Without the signature `advance_gate` will not pass the task to DEV.
203
203
  - **`request_decision` for architectural choice** — when 2+ valid options exist with trade-offs (monolith vs microservices, ORM choice, sync vs async pipeline): `request_decision(question, options=[plan_a, plan_b, plan_c], tradeoffs)`. the user decides, then `record_decision` writes the ADR.
204
204
  - **`record_decision` for every ADR** — every architectural decision = ADR via `$adr-log`. `record_decision(signer="user", domain="development", task_id, decision_text)` after approval. Architectural ADRs are the primary audit trail of the architecture.
205
205
  - **Circuit Breaker (DEV-054) — destination, not source** — architect is the **recipient** of an MCP auto-route, not the source of a rollback. 2 consecutive DEV-rollback on REV/TEST → MCP blocks return-to-DEV and routes the task to ARCH deep audit. Architect performs: current-state-analysis + system-design-checklist + design-patterns-reference review and produces a corrective ADR.
@@ -22,6 +22,7 @@ Close the self-improvement loop: build → run → measure → improve. Once rea
22
22
  - NOT at every gate and NOT in the background. One pass, once **≥3 completed runs** have accumulated (threshold configurable).
23
23
  - Below the threshold — silent. It draws no conclusions from n=1 (small sample).
24
24
  - Per-gate telemetry is already persisted by the state machine; the Auditor makes one pass over the accumulated data.
25
+ - Triggering a pass: the `/audit` command (manual) or the `audit_nudge` that `sign_off` returns after RG.
25
26
 
26
27
  ---
27
28
 
@@ -49,20 +50,20 @@ Close the self-improvement loop: build → run → measure → improve. Once rea
49
50
 
50
51
  ---
51
52
 
52
- ## Autonomy model (DESCRIPTION of behavior; mechanism is a separate ADR)
53
+ ## Autonomy model (behavior; mechanism `propose_change` / `review_proposal`)
53
54
  - **By default: proposes → the human approves.** The human may disable the approval gate.
54
55
  - **When autonomy is enabled** (matrix):
55
56
  - **Auto, no ask:** low-risk edits to existing assets (triggers, `budget_lines`, `gates`, wording) + **ADDING** new agents / skills.
56
57
  - **Human-gated even under autonomy:** destructive changes to existing assets (delete, major rewrite, capability removal).
57
58
  - **Always:** a mandatory report after any autonomous action. Nothing invisible.
58
59
  - **Additive dedup:** before auto-adding a skill — an overlap check (`related` + controlled vocab); the report lists additions for later pruning.
59
- - The propose→approve mechanism and the autonomy toggle are the NEXT step. Only the behavioral contract is fixed here.
60
+ - The propose→approve mechanism and the autonomy toggle already exist (`propose_change` `review_proposal`: risk matrix + dedup). A pass is triggered by `/audit` or the post-RG nudge.
60
61
 
61
62
  ---
62
63
 
63
64
  ## MCP integration
64
65
  - **Reads:** `aggregate_run_metrics` (numbers per agent / workflow / skill) + its `notes`.
65
- - **Draft changes** are written as artifacts via `submit_artifact` once the proposal mechanism lands (item 4).
66
+ - **Draft changes** go through `propose_change` (pending in the store, changing nothing); the human reviews via `list_proposals` and approves via `review_proposal`; the asset write is a separate `submit_artifact` / edit.
66
67
  - **Does NOT call** gate tools (`classify_gate` / `sign_off` / `advance_gate`) — the Auditor is outside the state machine.
67
68
  - Pilot — the `development` domain. Roll-out to other domains is later and joint (domain boundary).
68
69
 
@@ -297,7 +297,10 @@ If two agents disagree (DEV vs ARCH on an ADR, REV vs DEV on a P0, UX vs PM on s
297
297
  The Conductor orchestrates the entire gate flow via MCP — see the general flow in `$mcp-integration`. Conductor-specific operational guardrails:
298
298
 
299
299
  - **Gate-flow orchestration** — the Conductor drives the pipeline `PM → UX → ARCH → DEV → REV → OPS → TEST → RG` via MCP: `classify_gate` (which gate a task lands on), `current_gate` (where it is now), `advance_gate` (move to the next phase only after artifacts + Handoff Envelope). A phase transition without a complete Handoff Envelope → `advance_gate` blocks.
300
- - **`sign_off` across all 8 gates** the Conductor signs PM/UX/ARCH/DEV/REV/OPS/TEST/RG. The RG decision is recorded via MCP `sign_off` (NOT prose approval): `sign_off(gate="RG", signer="conductor", decision=GO|NO-GO|GO-with-conditions, evidence=<RG checklist + REV-xx + QA-xx>)`. Details → `$release-gate` § Decision Recording.
300
+ - **`sign_off` — by gate policy, NOT "I sign everything"** gates fall into two classes:
301
+ - **User gates (PM/UX/ARCH/RG, policy=user)** — the USER signs. The Conductor STOPS, presents the gate artifact, and requests `sign_off(signer="user")` — one gate at a time, no batching of approvals, and does NOT start next-gate work until the current one is signed. An inapplicable gate (UX for a backend/test-only task) still needs an explicit user sign-off: present it as N/A and ask — do not auto-pass it as `mcp`.
302
+ - **Execution gates (DEV/REV/OPS/TEST, policy=either)** — the Conductor may sign itself: `sign_off(signer="mcp")` once DoD is met.
303
+ - **RG** is recorded as `sign_off(gate="RG", signer="user", decision=GO|NO-GO|GO-with-conditions, evidence=<RG checklist + REV-xx + QA-xx>)` (NOT prose approval). Details → `$release-gate` § Decision Recording.
301
304
  - **Circuit Breaker (DEV-054), MCP-enforced** — 2 consecutive DEV-rollbacks at REV/TEST → MCP blocks return-to-DEV and auto-routes to ARCH deep audit. The Conductor does NOT bypass the circuit breaker manually. Full logic → `$gates` § Circuit Breaker.
302
305
  - **`request_decision` for escalation routing** — conflicts between agents (DEV vs ARCH, REV vs DEV, UX vs PM) and waivers of mandatory items: `request_decision(conflict_summary, options, tradeoffs)` → the user decides → `record_decision`. See § Conflict Resolution Protocol.
303
306
  - **`record_decision` for ADR-worthy outcomes** — architectural drift, resolved conflicts, mandatory waivers = an ADR via `$adr-log`. `record_decision(signer="user", domain="development", task_id, decision_text)`.
@@ -213,7 +213,7 @@ In case of a production incident:
213
213
 
214
214
  OPS gate ritual via MCP — see the general flow in `$mcp-integration`. DevOps-specific operational guardrails:
215
215
 
216
- - **`sign_off` for the OPS gate** — the OPS sign-off is a mandatory link in the final RG chain `DEV → REV → QA → OPS → RG` (see `$release-gate`): `sign_off(gate="OPS", signer="devops", evidence=<RG confirmation checklist below>)`. The sign-off **blocks RG** if any item failed. Evidence for the OPS sign-off:
216
+ - **`sign_off` for the OPS gate** — the OPS sign-off is a mandatory link in the final RG chain `DEV → REV → QA → OPS → RG` (see `$release-gate`): `sign_off(gate="OPS", signer="mcp", evidence=<RG confirmation checklist below>)`. The sign-off **blocks RG** if any item failed. Evidence for the OPS sign-off:
217
217
  - HTTPS valid in all prod environments (cert expiry ≥ 30d)
218
218
  - Secrets rotation up to date (last rotation ≤ 90d for critical keys)
219
219
  - Rollback procedure tested within ≤ 30d
@@ -198,7 +198,8 @@ The Reviewer must produce a report usable by the conductor in the Release Gate:
198
198
 
199
199
  REV gate ritual via MCP — general flow in `$mcp-integration`. Reviewer-specific operational guardrails:
200
200
 
201
- - **`sign_off` for REV gate** — after review completion one MCP call: `sign_off(gate="REV", signer="reviewer", evidence=<REV-xx_report_path or audit_trail link>)`. Without the signature `advance_gate` will not pass the task to OPS/TEST.
201
+ - **`render_diff` before the REV sign-off** — present the reviewed diff as an HTML page: `render_diff(diff=<git diff>, title="REV-xx review")` hand the user the `file://` URL. Informational only (file in the system temp dir), then sign off.
202
+ - **`sign_off` for REV gate** — after review completion one MCP call: `sign_off(gate="REV", signer="mcp", evidence=<REV-xx_report_path or audit_trail link>)`. Without the signature `advance_gate` will not pass the task to OPS/TEST.
202
203
  - **`request_decision` for P0 unresolved** — if a P0 BLOCKER is not resolvable technically (waiver candidate, architectural conflict): `request_decision(blocker_summary, options=[block, waive_with_compensating_control, escalate_to_architect], tradeoffs)`. the user decides, then `record_decision` writes the ADR.
203
204
  - **`record_decision` for P0 waiver** — every waiver = ADR via `$adr-log` (persona-base principle 3: risk decisions are visible). `record_decision(signer="user", domain="development", task_id, decision_text)` after approval.
204
205
  - **Circuit Breaker (DEV-054)** — 2 consecutive DEV-rollback on REV/TEST → MCP blocks return-to-DEV and auto-routes the task to ARCH deep audit (see `$gates`). Reviewer does not bypass the circuit breaker manually.
@@ -200,7 +200,7 @@ Each stack workflow below has a companion `-reference` for deep lookup — the `
200
200
 
201
201
  DEV gate ritual via MCP — see the general flow in `$mcp-integration`. SFS-specific operational guardrails:
202
202
 
203
- - **`sign_off` for the DEV gate** — after finishing a slice, one MCP call: `sign_off(gate="DEV", signer="senior_full_stack", evidence=<DEMO-xx envelope + green CI link; for tier 1-2 — RED_COMMIT_HASH + GREEN_COMMIT_HASH>)`. The evidence content is the Test Integrity Discipline above (Boundary Mocking + RED/GREEN hashes), not restated here. Without the sign-off, `advance_gate` will not move the task to REV.
203
+ - **`sign_off` for the DEV gate** — after finishing a slice, one MCP call: `sign_off(gate="DEV", signer="mcp", evidence=<DEMO-xx envelope + green CI link; for tier 1-2 — RED_COMMIT_HASH + GREEN_COMMIT_HASH>)`. The evidence content is the Test Integrity Discipline above (Boundary Mocking + RED/GREEN hashes), not restated here. Without the sign-off, `advance_gate` will not move the task to REV.
204
204
  - **`request_decision` for a blocked P0** — when a P0 cannot be resolved technically (a >500-line file cannot be decomposed, guardrails not provided by the architect, a simplification breaks acceptance): `request_decision(blocker_summary, options=[block, simplify_with_tech_debt, escalate_to_architect], tradeoffs)`. the user decides, then `record_decision`.
205
205
  - **`record_decision` for a tech-debt waiver** — every intentional simplification (`// TODO`) carrying risk = an ADR via `$adr-log` (persona-base principle 3: risky decisions are visible). `record_decision(signer="user", domain="development", task_id, decision_text)` after approval.
206
206
  - **Circuit Breaker (DEV-054)** — sfs is the **origin** of rollback: 2 consecutive DEV-rollbacks on REV/TEST → MCP blocks the return to DEV and automatically routes the task to an ARCH deep audit (see `$gates`). sfs does not bypass the circuit breaker or re-open the task manually — it waits for a corrective ADR from the architect.
@@ -219,7 +219,7 @@ For testing applications inside closed ecosystems (Wix Dashboard, Shopify Admin,
219
219
 
220
220
  TEST gate ritual via MCP — see the general flow in `$mcp-integration`. Tester-specific operational guardrails:
221
221
 
222
- - **`sign_off` for the TEST gate** — the TEST sign-off is a link in the final RG chain `DEV → REV → QA → OPS → RG` (see `$release-gate`): `sign_off(gate="TEST", signer="tester", evidence=<QA-xx report + TID status>)`. The evidence is the tier-based GO logic from the "Tier-based Release Recommendation logic" section above (mutation score ≥ 80%/60% for tier 1/2, flake rate < 1%, integrity audit clean, RED/GREEN hashes for tier 1-2), not restated here. Without the sign-off, `advance_gate` will not move the release to RG.
222
+ - **`sign_off` for the TEST gate** — the TEST sign-off is a link in the final RG chain `DEV → REV → QA → OPS → RG` (see `$release-gate`): `sign_off(gate="TEST", signer="mcp", evidence=<QA-xx report + TID status>)`. The evidence is the tier-based GO logic from the "Tier-based Release Recommendation logic" section above (mutation score ≥ 80%/60% for tier 1/2, flake rate < 1%, integrity audit clean, RED/GREEN hashes for tier 1-2), not restated here. Without the sign-off, `advance_gate` will not move the release to RG.
223
223
  - **Action tools Tester drives via MCP** — `e2e_playwright` for automated E2E spec files (`$qa-e2e-playwright`); `run_tests` / `docker_compose` for the regression run after a confirmed container reload (evidence from DevOps required).
224
224
  - **`record_decision` for a test-integrity finding** — a block-merge on mutation regression or a P0 integrity finding = an ADR via `$adr-log`. `record_decision(signer="user", domain="development", task_id, decision_text)` after approval.
225
225
  - **`request_decision` for a contested NO-GO / waiver** — when a NO-GO is contested or a waiver on a mutation-score regression with compensation is needed: `request_decision(blocker_summary, options=[block_release, waive_with_compensating_control, escalate_to_architect], tradeoffs)`. the user decides, then `record_decision`.
@@ -5,7 +5,7 @@ domain: product
5
5
  signs_off_at:
6
6
  - RELEASE_GATE
7
7
  tool_allowlist: role:conductor
8
- budget_lines: 529
8
+ budget_lines: 543
9
9
  schema_version: 1
10
10
  ---
11
11
 
@@ -396,6 +396,20 @@ $handoff → MED-01 (Unified Strategy Synthesis).
396
396
 
397
397
  ---
398
398
 
399
+ ## MCP-интеграция и операционные гарантии
400
+
401
+ Дирижёр оркестрирует весь поток гейтов через машину состояний `code-ai` MCP — общий поток см. в `product-pipeline-rules.md` § «Машина гейтов (code-ai MCP)». Conductor-specific операционные гарантии:
402
+
403
+ - **Оркестрация гейтов** — Дирижёр ведёт последовательность гейтов выбранного режима через MCP: `classify_gate` (на какой гейт ложится задача), `current_gate` (где сейчас), `advance_gate` (переход к следующему гейту только после deliverable + Handoff Envelope). Переход без полного Handoff Envelope → `advance_gate` блокирует.
404
+ - **`sign_off` — все гейты `user`, Дирижёр не подписывает за пользователя** — в продукте каждый гейт закрывает ПОЛЬЗОВАТЕЛЬ. Дирижёр ОСТАНАВЛИВАЕТСЯ, показывает артефакт гейта и запрашивает `sign_off(signer="user")` — по одному гейту, без батчинга нескольких подтверждений, и не начинает работу следующего гейта, пока текущий не подписан. Авто-пас на зелёном не применяется (домен суждения, детерминированных авто-чеков нет).
405
+ - **RELEASE_GATE** фиксируется как `sign_off(gate="RELEASE_GATE", signer="user", decision=..., evidence=<RG checklist>)` — не «прозой».
406
+ - **`request_decision` для эскалаций** — конфликты между агентами и waiver'ы обязательных пунктов: `request_decision(...)` → решает пользователь → `record_decision`. См. § Conflict Resolution Protocol.
407
+ - **`record_decision` для ADR-достойных решений** — зафиксированные конфликты и отклонения от брифа, согласованные с пользователем: `record_decision(signer="user", domain="product", task_id, decision_text)`.
408
+ - **Circuit breaker отключён** — в продукте нет полосы откатов в стиле development (DEV/REV/OPS/TEST); возвраты идут через reverse `$handoff` (см. Reverse Handoff).
409
+ - **Degraded mode** — если MCP-поток недоступен: Дирижёр ведёт Master Checklist (`$board`) и статусы Handoff Envelope вручную, sign-off фиксируется явным "Approved" пользователя, эскалации — вручную.
410
+
411
+ ---
412
+
399
413
  ## Формат ответа агента
400
414
 
401
415
  ### Full Pipeline (A / B)
@@ -5,7 +5,7 @@ domain: product
5
5
  signs_off_at:
6
6
  - RELEASE_GATE
7
7
  tool_allowlist: role:conductor
8
- budget_lines: 529
8
+ budget_lines: 543
9
9
  schema_version: 1
10
10
  ---
11
11
 
@@ -396,6 +396,20 @@ If an agent's deliverable does not pass `$gates`:
396
396
 
397
397
  ---
398
398
 
399
+ ## MCP integration & operational guardrails
400
+
401
+ The Conductor orchestrates the whole gate-flow through the `code-ai` MCP state machine — for the general flow see `product-pipeline-rules.md` § "Gate machine (code-ai MCP)". Conductor-specific operational guardrails:
402
+
403
+ - **Gate-flow orchestration** — the Conductor drives the active mode's gate sequence through MCP: `classify_gate` (which gate the task lands on), `current_gate` (where we are now), `advance_gate` (move to the next gate only after the deliverable + Handoff Envelope). A transition without a complete Handoff Envelope → `advance_gate` blocks.
404
+ - **`sign_off` — all gates are `user`; the Conductor does not sign for the user** — in product every gate is closed by the USER. The Conductor STOPS, presents the gate artifact, and requests `sign_off(signer="user")` — one gate at a time, with no batching of approvals, and does NOT start next-gate work until the current one is signed. No auto-pass on green (a judgment domain, no deterministic auto-checks).
405
+ - **RELEASE_GATE** is recorded as `sign_off(gate="RELEASE_GATE", signer="user", decision=..., evidence=<RG checklist>)` — not prose approval.
406
+ - **`request_decision` for escalations** — conflicts between agents and waivers of mandatory items: `request_decision(...)` → the user decides → `record_decision`. See § Conflict Resolution Protocol.
407
+ - **`record_decision` for ADR-worthy outcomes** — recorded conflicts and brief deviations approved by the user: `record_decision(signer="user", domain="product", task_id, decision_text)`.
408
+ - **Circuit breaker disabled** — product has no development-style rollback lane (DEV/REV/OPS/TEST); returns go through reverse `$handoff` (see Reverse Handoff).
409
+ - **Degraded mode** — if the MCP flow is unavailable: the Conductor keeps the Master Checklist (`$board`) and Handoff Envelope statuses by hand, sign-off is recorded by the user's explicit "Approved", and escalations are manual.
410
+
411
+ ---
412
+
399
413
  ## Agent response format
400
414
 
401
415
  ### Full Pipeline (A / B)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-ai-installer",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "Production-ready CLI to install code-ai agents and skills for multiple AI coding assistants. Bundles the code-ai-mcp MCP server for Claude Code.",
5
5
  "license": "MIT",
6
6
  "author": "Denish1209",