gennady 0.8.4-draft.2 → 0.8.4-draft.3

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 (146) hide show
  1. package/ai/directives/sdd-v2/root.directive.xml +36 -3
  2. package/ai/directives/sdd-v2/router.directive.xml +22 -1
  3. package/ai/kit/templates/sdd-v2/root.directive.hbs +11 -3
  4. package/ai/kit/templates/sdd-v2/router.directive.hbs +22 -1
  5. package/ai/skills/agent-inbox/SKILL.md +1 -1
  6. package/ai/skills/sdd/SKILL.md +5 -3
  7. package/ai/skills/sdd-audit/SKILL.md +5 -2
  8. package/ai/skills/sdd-check/SKILL.md +2 -2
  9. package/ai/skills/sdd-code-review/SKILL.md +4 -1
  10. package/ai/skills/sdd-critic/SKILL.md +5 -2
  11. package/ai/skills/sdd-execute/SKILL.md +5 -2
  12. package/ai/skills/sdd-reconcile/SKILL.md +5 -2
  13. package/ai/skills/sdd-scaffold/SKILL.md +5 -2
  14. package/dist/ai/directives/sdd-v2/root.directive.xml +36 -3
  15. package/dist/ai/directives/sdd-v2/router.directive.xml +22 -1
  16. package/dist/ai/kit/templates/sdd-v2/root.directive.hbs +11 -3
  17. package/dist/ai/kit/templates/sdd-v2/router.directive.hbs +22 -1
  18. package/dist/ai/skills/agent-inbox/SKILL.md +1 -1
  19. package/dist/ai/skills/sdd/SKILL.md +5 -3
  20. package/dist/ai/skills/sdd-audit/SKILL.md +5 -2
  21. package/dist/ai/skills/sdd-check/SKILL.md +2 -2
  22. package/dist/ai/skills/sdd-code-review/SKILL.md +4 -1
  23. package/dist/ai/skills/sdd-critic/SKILL.md +5 -2
  24. package/dist/ai/skills/sdd-execute/SKILL.md +5 -2
  25. package/dist/ai/skills/sdd-reconcile/SKILL.md +5 -2
  26. package/dist/ai/skills/sdd-scaffold/SKILL.md +5 -2
  27. package/dist/chunks/{classify-mr-stage.logic-BiCHTmPp.js → classify-mr-stage.logic-CazmQDwZ.js} +2 -2
  28. package/dist/chunks/{config-index-9VHWSDQD.js → config-index-DU8-FEjq.js} +1 -1
  29. package/dist/chunks/{devtools-b0DwO1x_.js → devtools-1JmXJjUG.js} +1 -1
  30. package/dist/chunks/{eval.cmd-CwNPaNJd.js → eval.cmd-CBANnOFG.js} +1 -1
  31. package/dist/chunks/{help-D5cXtdMI.js → help-DVloaFF5.js} +1 -1
  32. package/dist/chunks/{index-BVnJEutp.js → index-2xhpqJtd.js} +2 -2
  33. package/dist/chunks/{index-RR5OUxje.js → index-AxsLBUAx.js} +14 -14
  34. package/dist/chunks/{index-CUkeTGqM.js → index-B7sydB0W.js} +2 -2
  35. package/dist/chunks/{index-CMCn9ErF.js → index-BKxk4zOz.js} +2 -2
  36. package/dist/chunks/{index-Db13NlHh.js → index-BNMmX_Mv.js} +21 -21
  37. package/dist/chunks/{index-CmQO-RmM.js → index-BPzldG3a.js} +2 -2
  38. package/dist/chunks/{index-BOQl7F_Z.js → index-BQlFDvKW.js} +2 -2
  39. package/dist/chunks/{index-RzkvIfJQ.js → index-Baq7RL1L.js} +3 -3
  40. package/dist/chunks/index-BbPiwvY9.js +2 -0
  41. package/dist/chunks/{index-ClJLPEUB.js → index-BreGNLJ_.js} +1 -1
  42. package/dist/chunks/{index-DjSafAkN.js → index-BslPwGtM.js} +2 -2
  43. package/dist/chunks/{index-DiMFxS0z.js → index-BtCUN2fZ.js} +16 -16
  44. package/dist/chunks/{index-CS0VbiLD.js → index-C10-EOdB.js} +1 -1
  45. package/dist/chunks/{index-2BOEcJIa.js → index-C4JmZLaj.js} +2 -2
  46. package/dist/chunks/index-CA-JKLr4.js +2 -0
  47. package/dist/chunks/{index-43GiH--T.js → index-CG_jJZVu.js} +2 -2
  48. package/dist/chunks/{index-BdkFKsMm.js → index-CGyP2uDE.js} +3 -3
  49. package/dist/chunks/{index-BOKv0b01.js → index-CPl1s9XJ.js} +2 -2
  50. package/dist/chunks/{index-DIPrBH-4.js → index-CSxE4cEm.js} +9 -9
  51. package/dist/chunks/{index-Cm7U1-fU.js → index-CWR5EzXx.js} +2 -2
  52. package/dist/chunks/{index-BwN5llCR.js → index-Camql5kL.js} +2 -2
  53. package/dist/chunks/{index-Drh-J9O7.js → index-CdUiTipO.js} +7 -7
  54. package/dist/chunks/{index-Cn029KTN.js → index-Crg61pK5.js} +2 -2
  55. package/dist/chunks/{index-Dja2O-hV.js → index-Cv9ZYXso.js} +1 -1
  56. package/dist/chunks/{index-Ck8v_Gv7.js → index-D7ADMlG3.js} +1 -1
  57. package/dist/chunks/index-DNl2gC8l.js +158 -0
  58. package/dist/chunks/{index-BYIzl-Ut.js → index-DVJA0qVm.js} +36 -36
  59. package/dist/chunks/{index-BAEIZVx0.js → index-DcFJhkY1.js} +2 -2
  60. package/dist/chunks/{index-Dx5_CB2E.js → index-DdEd-L3x.js} +2 -2
  61. package/dist/chunks/{index-DVmqMmgb.js → index-DkGA1eW_.js} +32 -32
  62. package/dist/chunks/{index-3k7mPX1e.js → index-Dnwxlti3.js} +1 -1
  63. package/dist/chunks/{index-CrizvxOJ.js → index-DqdEJDi2.js} +2 -2
  64. package/dist/chunks/{index-BIPebtDl.js → index-DqiwmBt4.js} +1 -1
  65. package/dist/chunks/{index-DS4MhAw-.js → index-PfuqBWjY.js} +2 -2
  66. package/dist/chunks/{index-BmFT1Kx2.js → index-SVP6RfVl.js} +2 -2
  67. package/dist/chunks/{index-CDxV4b81.js → index-Y8wu48Q0.js} +1 -1
  68. package/dist/chunks/index-_ewSKppm.js +2 -0
  69. package/dist/chunks/{index-Ctcr_Qeu.js → index-aBVtCLIJ.js} +2 -2
  70. package/dist/chunks/index-dNdz9j6d.js +2 -0
  71. package/dist/chunks/{index-BFUkVkSo.js → index-gskOpu3H.js} +16 -16
  72. package/dist/chunks/{index-CXpkT25O.js → index-pBSLMn5Q.js} +3 -3
  73. package/dist/chunks/index-sqPhX5Io.js +2 -0
  74. package/dist/chunks/{index-BzmR4Es2.js → index-vfrjhUD1.js} +39 -39
  75. package/dist/chunks/{index-J2NvjjDV.js → index-xGF5XC_i.js} +2 -2
  76. package/dist/chunks/{run-review-command.logic-CA2Rjymb.js → run-review-command.logic-B9GoCxh-.js} +24 -24
  77. package/dist/chunks/{serve.cmd-RxYS6WoN.js → serve.cmd-UXkaeaPI.js} +2 -2
  78. package/dist/chunks/{services-Csd556Tv.js → services-BYCeGBlO.js} +4 -4
  79. package/dist/chunks/{shared-B5CTGvpG.js → shared-B3cXL2Np.js} +1178 -1117
  80. package/dist/chunks/{stats-index-BLztvK69.js → stats-index-AIAnnp9S.js} +2 -2
  81. package/dist/gennady.js +46 -46
  82. package/dist/index.js +4 -4
  83. package/dist/shared/sdd/ladder.d.ts +42 -0
  84. package/dist/shared/sdd/module-specs.d.ts +7 -0
  85. package/dist/shared/sdd/tracker.d.ts +9 -0
  86. package/package.json +1 -1
  87. package/dist/chunks/classify-mr-stage.logic-ClmhzQPQ.js +0 -53
  88. package/dist/chunks/config-index-RFeqlDWs.js +0 -104
  89. package/dist/chunks/devtools-p8tmPuLn.js +0 -79
  90. package/dist/chunks/eval.cmd-ewU5lcUY.js +0 -34
  91. package/dist/chunks/help-DzGnMNi2.js +0 -7
  92. package/dist/chunks/index--AXFi0ty.js +0 -89
  93. package/dist/chunks/index-64TSesTc.js +0 -186
  94. package/dist/chunks/index-9Gv5trS_.js +0 -125
  95. package/dist/chunks/index-B1DQIryA.js +0 -2
  96. package/dist/chunks/index-B1PiBeQ3.js +0 -2
  97. package/dist/chunks/index-B4rzuhkt.js +0 -183
  98. package/dist/chunks/index-B97HJjkg.js +0 -159
  99. package/dist/chunks/index-BF6qypm0.js +0 -131
  100. package/dist/chunks/index-BK84ZQsh.js +0 -128
  101. package/dist/chunks/index-BRVIirjj.js +0 -141
  102. package/dist/chunks/index-BXnryCGW.js +0 -96
  103. package/dist/chunks/index-BaZm7Otb.js +0 -2
  104. package/dist/chunks/index-Bhk746A2.js +0 -129
  105. package/dist/chunks/index-Bi-eY_dY.js +0 -164
  106. package/dist/chunks/index-BjumU69g.js +0 -2
  107. package/dist/chunks/index-BkWXcpXU.js +0 -16979
  108. package/dist/chunks/index-BlY4jQIA.js +0 -168
  109. package/dist/chunks/index-C0iy7GxD.js +0 -140
  110. package/dist/chunks/index-CCBTXczb.js +0 -56
  111. package/dist/chunks/index-CDAfkSrr.js +0 -2
  112. package/dist/chunks/index-CDHymWzC.js +0 -102
  113. package/dist/chunks/index-CNfXJAao.js +0 -2
  114. package/dist/chunks/index-CQsae1nq.js +0 -207
  115. package/dist/chunks/index-CVmd0prf.js +0 -2
  116. package/dist/chunks/index-CZuTNeNm.js +0 -2
  117. package/dist/chunks/index-CasNhhrL.js +0 -96
  118. package/dist/chunks/index-Ce7GWENF.js +0 -377
  119. package/dist/chunks/index-Cf-02TAg.js +0 -265
  120. package/dist/chunks/index-CfjQWSrh.js +0 -52
  121. package/dist/chunks/index-Chr7gBBz.js +0 -443
  122. package/dist/chunks/index-Ci875Zlg.js +0 -346
  123. package/dist/chunks/index-CwA6RzIB.js +0 -3793
  124. package/dist/chunks/index-D1dI63ej.js +0 -46
  125. package/dist/chunks/index-DCS32A2i.js +0 -663
  126. package/dist/chunks/index-DOFoNxvb.js +0 -131
  127. package/dist/chunks/index-DVkCEuws.js +0 -136
  128. package/dist/chunks/index-DkadaaXq.js +0 -658
  129. package/dist/chunks/index-Dn11CLtk.js +0 -7
  130. package/dist/chunks/index-Do3spFJT.js +0 -340
  131. package/dist/chunks/index-DrFRZ0Yg.js +0 -2
  132. package/dist/chunks/index-DvEQhXi2.js +0 -1054
  133. package/dist/chunks/index-GiS0x6jg.js +0 -90
  134. package/dist/chunks/index-NacvqeQ5.js +0 -69
  135. package/dist/chunks/index-RNJhFzdr.js +0 -227
  136. package/dist/chunks/index-R_vUB6CL.js +0 -2
  137. package/dist/chunks/index-TQft1s5H.js +0 -20
  138. package/dist/chunks/index-ZmQRP38W.js +0 -26969
  139. package/dist/chunks/index-jdOZ4AkD.js +0 -143
  140. package/dist/chunks/index-kNa21kUI.js +0 -279
  141. package/dist/chunks/index-v4AV9kAc.js +0 -108
  142. package/dist/chunks/run-review-command.logic-CU1Slmc_.js +0 -331
  143. package/dist/chunks/serve.cmd-dWu_k_G_.js +0 -162
  144. package/dist/chunks/services-CwvXl2MB.js +0 -46832
  145. package/dist/chunks/shared-DSZTUx5b.js +0 -4509
  146. package/dist/chunks/stats-index-H6ALcjxy.js +0 -66
@@ -1,36 +1,36 @@
1
- import { spawn as gt, execSync as Ge, execFile as It, execFileSync as Ot } from "node:child_process";
2
- import v, { mkdirSync as Fe, readFileSync as D, existsSync as R, readdirSync as $, statSync as oe, writeFileSync as q, rmSync as Se, renameSync as Tt } from "node:fs";
3
- import k, { resolve as y, dirname as w, join as h, basename as G, relative as x, sep as b, extname as _t, posix as B } from "node:path";
4
- import { platform as ge, homedir as te } from "node:os";
5
- import { fileURLToPath as fe } from "node:url";
6
- import { l as O, V as Nt, a as Ct } from "./services-Csd556Tv.js";
7
- import { promisify as Dt } from "node:util";
8
- const At = 864e5, yt = 3e3, Rt = "update-check-worker.ts", kt = "update-check-cache.json";
9
- function vt(e) {
10
- return ge() === "win32" ? y(process.env.LOCALAPPDATA ?? y(te(), "AppData", "Local"), "gennady") : ge() === "darwin" ? y(te(), "Library", "Caches", "gennady") : y(te(), ".cache", "gennady");
11
- }
12
- function wt(e) {
1
+ import { spawn as Ot, execSync as Ve, execFile as Tt, execFileSync as _t } from "node:child_process";
2
+ import v, { mkdirSync as je, readFileSync as C, existsSync as R, readdirSync as B, statSync as ie, writeFileSync as W, rmSync as Ie, renameSync as Nt } from "node:fs";
3
+ import k, { resolve as y, dirname as w, join as h, basename as V, relative as x, sep as b, extname as Ct, posix as F } from "node:path";
4
+ import { platform as Oe, homedir as ne } from "node:os";
5
+ import { fileURLToPath as me } from "node:url";
6
+ import { l as O, V as Dt, a as At } from "./services-BYCeGBlO.js";
7
+ import { promisify as yt } from "node:util";
8
+ const Rt = 864e5, kt = 3e3, vt = "update-check-worker.ts", wt = "update-check-cache.json";
9
+ function Pt(e) {
10
+ return Oe() === "win32" ? y(process.env.LOCALAPPDATA ?? y(ne(), "AppData", "Local"), "gennady") : Oe() === "darwin" ? y(ne(), "Library", "Caches", "gennady") : y(ne(), ".cache", "gennady");
11
+ }
12
+ function Lt(e) {
13
13
  try {
14
- const t = D(e, "utf-8"), s = JSON.parse(t);
14
+ const t = C(e, "utf-8"), s = JSON.parse(t);
15
15
  return typeof s?.lastCheck != "string" || typeof s?.latestVersion != "string" ? null : s;
16
16
  } catch {
17
17
  return null;
18
18
  }
19
19
  }
20
- function Pt(e, t) {
20
+ function bt(e, t) {
21
21
  return Date.now() - new Date(e.lastCheck).getTime() < t;
22
22
  }
23
- function Ie(e, t) {
24
- const s = (r) => r.split(".").map((i) => parseInt(i, 10)), n = s(e), o = s(t);
25
- if (n.some(isNaN) || o.some(isNaN)) return !1;
26
- for (let r = 0; r < Math.max(n.length, o.length); r++) {
27
- const i = n[r] ?? 0, a = o[r] ?? 0;
23
+ function Te(e, t) {
24
+ const s = (o) => o.split(".").map((i) => parseInt(i, 10)), n = s(e), r = s(t);
25
+ if (n.some(isNaN) || r.some(isNaN)) return !1;
26
+ for (let o = 0; o < Math.max(n.length, r.length); o++) {
27
+ const i = n[o] ?? 0, a = r[o] ?? 0;
28
28
  if (a > i) return !0;
29
29
  if (a < i) return !1;
30
30
  }
31
31
  return !1;
32
32
  }
33
- function Oe(e, t) {
33
+ function _e(e, t) {
34
34
  let s = !1;
35
35
  process.on("beforeExit", () => {
36
36
  s || (s = !0, process.stderr.write(`
@@ -40,7 +40,7 @@ Update available: ${e} → ${t}
40
40
  `));
41
41
  });
42
42
  }
43
- function oo(e, t) {
43
+ function ao(e, t) {
44
44
  if (process.env.GENNADY_NO_UPDATE_CHECK === "1" || process.argv.includes("--no-update-check")) {
45
45
  process.env.GENNADY_DEBUG === "1" && process.stderr.write(
46
46
  `[update-check] skipped: opt-out (GENNADY_NO_UPDATE_CHECK or --no-update-check)
@@ -53,25 +53,25 @@ function oo(e, t) {
53
53
  `);
54
54
  return;
55
55
  }
56
- const s = Number(process.env.GENNADY_UPDATE_CHECK_INTERVAL) || At, n = vt(), o = y(n, kt);
57
- Fe(n, { recursive: !0 });
58
- const r = wt(o);
59
- if (r && Pt(r, s)) {
60
- r.latestVersion && Ie(e.version, r.latestVersion) && (process.stderr.isTTY || t?.skipNotificationIfNoTty === !1) && Oe(e.version, r.latestVersion);
56
+ const s = Number(process.env.GENNADY_UPDATE_CHECK_INTERVAL) || Rt, n = Pt(), r = y(n, wt);
57
+ je(n, { recursive: !0 });
58
+ const o = Lt(r);
59
+ if (o && bt(o, s)) {
60
+ o.latestVersion && Te(e.version, o.latestVersion) && (process.stderr.isTTY || t?.skipNotificationIfNoTty === !1) && _e(e.version, o.latestVersion);
61
61
  return;
62
62
  }
63
- const i = y(w(fe(import.meta.url)), Rt);
64
- gt(
63
+ const i = y(w(me(import.meta.url)), vt);
64
+ Ot(
65
65
  process.execPath,
66
- [i, e.name, e.version, o, String(yt)],
66
+ [i, e.name, e.version, r, String(kt)],
67
67
  {
68
68
  stdio: "ignore"
69
69
  }
70
- ).unref(), r?.latestVersion && Ie(e.version, r.latestVersion) && (process.stderr.isTTY || t?.skipNotificationIfNoTty === !1) && Oe(e.version, r.latestVersion);
70
+ ).unref(), o?.latestVersion && Te(e.version, o.latestVersion) && (process.stderr.isTTY || t?.skipNotificationIfNoTty === !1) && _e(e.version, o.latestVersion);
71
71
  }
72
- const j = ["plain", "nocolor", "noColor", "no-color", "color=no", "color=never"].some(
72
+ const Y = ["plain", "nocolor", "noColor", "no-color", "color=no", "color=never"].some(
73
73
  (e) => process.argv.includes(`-${e}`) || process.argv.includes(`--${e}`)
74
- ), U = {
74
+ ), G = {
75
75
  // Modifiers
76
76
  reset: "\x1B[0m",
77
77
  bold: "\x1B[1m",
@@ -117,27 +117,27 @@ const j = ["plain", "nocolor", "noColor", "no-color", "color=no", "color=never"]
117
117
  bgCyanBright: "\x1B[106m",
118
118
  bgWhiteBright: "\x1B[107m"
119
119
  };
120
- function Ve(e = []) {
121
- const t = (s) => j ? s : e.join("") + s + U.reset;
120
+ function Ye(e = []) {
121
+ const t = (s) => Y ? s : e.join("") + s + G.reset;
122
122
  return new Proxy(t, {
123
123
  get(s, n) {
124
124
  if (n === "toString")
125
- return () => j ? "%s" : e.join("") + "%s" + U.reset;
126
- if (n in U) {
127
- const o = U[n];
128
- return Ve(j ? [] : [...e, o].filter(Boolean));
125
+ return () => Y ? "%s" : e.join("") + "%s" + G.reset;
126
+ if (n in G) {
127
+ const r = G[n];
128
+ return Ye(Y ? [] : [...e, r].filter(Boolean));
129
129
  }
130
130
  },
131
- apply(s, n, o) {
132
- const r = o[0] ?? "";
133
- return j ? r : e.join("") + r + U.reset;
131
+ apply(s, n, r) {
132
+ const o = r[0] ?? "";
133
+ return Y ? o : e.join("") + o + G.reset;
134
134
  }
135
135
  });
136
136
  }
137
- const ro = Ve(), io = (e, t = {}, s = {}) => {
138
- const n = { _: [] }, o = e.slice(2);
139
- for (let r = 0; r < o.length; r++) {
140
- const i = o[r];
137
+ const co = Ye(), lo = (e, t = {}, s = {}) => {
138
+ const n = { _: [] }, r = e.slice(2);
139
+ for (let o = 0; o < r.length; o++) {
140
+ const i = r[o];
141
141
  if (i.startsWith("-")) {
142
142
  const a = i.replace(/^-+/, ""), [c, l] = a.split("=");
143
143
  let f = !1;
@@ -147,7 +147,7 @@ const ro = Ve(), io = (e, t = {}, s = {}) => {
147
147
  f = !0;
148
148
  const m = typeof u == "object" && !Array.isArray(u) ? u.takesValue === !0 : !1;
149
149
  let E;
150
- l !== void 0 ? E = l.replace(/^"|"$/g, "") : m && r + 1 < o.length && !o[r + 1].startsWith("-") ? (E = o[r + 1], r++) : E = !0, d in n ? (Array.isArray(n[d]) || (n[d] = [n[d]]), n[d].push(E)) : n[d] = E;
150
+ l !== void 0 ? E = l.replace(/^"|"$/g, "") : m && o + 1 < r.length && !r[o + 1].startsWith("-") ? (E = r[o + 1], o++) : E = !0, d in n ? (Array.isArray(n[d]) || (n[d] = [n[d]]), n[d].push(E)) : n[d] = E;
151
151
  break;
152
152
  }
153
153
  }
@@ -157,7 +157,7 @@ const ro = Ve(), io = (e, t = {}, s = {}) => {
157
157
  n._.push(i);
158
158
  }
159
159
  return n;
160
- }, Lt = {
160
+ }, Mt = {
161
161
  js: "JavaScript",
162
162
  jsx: "JavaScript",
163
163
  ts: "TypeScript",
@@ -183,16 +183,16 @@ const ro = Ve(), io = (e, t = {}, s = {}) => {
183
183
  sass: "Sass",
184
184
  md: "Markdown",
185
185
  mdc: "Markdown"
186
- }, Te = (e) => Lt[e] ?? void 0, ao = () => {
186
+ }, Ne = (e) => Mt[e] ?? void 0, uo = () => {
187
187
  try {
188
- return Ge("osascript -e 'user locale of (get system info)'").toString().trim().toLowerCase().split("_").filter((s) => s !== "en" && s !== "us")[0] ?? "en";
188
+ return Ve("osascript -e 'user locale of (get system info)'").toString().trim().toLowerCase().split("_").filter((s) => s !== "en" && s !== "us")[0] ?? "en";
189
189
  } catch {
190
190
  return "en";
191
191
  }
192
- }, _e = (e) => {
192
+ }, Ce = (e) => {
193
193
  const t = e.match(/[\p{L}\p{N}_]+|[^\s\p{L}\p{N}_]/gu);
194
194
  return t ? t.length : 0;
195
- }, bt = [
195
+ }, $t = [
196
196
  "^package\\.json",
197
197
  "^tsconfig\\.json",
198
198
  "^babel\\.config\\.json",
@@ -202,7 +202,7 @@ const ro = Ve(), io = (e, t = {}, s = {}) => {
202
202
  "^\\.env(?:\\.[\\w]+)?",
203
203
  "^\\..+",
204
204
  ".*\\.(?:yml|yaml|rc|ini|conf)"
205
- ], Mt = [
205
+ ], xt = [
206
206
  "^package-lock\\.json",
207
207
  "^npm-shrinkwrap\\.json",
208
208
  "^yarn(?:-lock)?\\.(?:yaml|yml|toml)",
@@ -211,41 +211,41 @@ const ro = Ve(), io = (e, t = {}, s = {}) => {
211
211
  "^podfile\\.lock",
212
212
  "^go\\.sum",
213
213
  "^gemfile\\.lock"
214
- ], xt = {
214
+ ], Bt = {
215
215
  doc: /\.(md|markdown|txt|rst)$/i,
216
- cfg: new RegExp(bt.join("|"), "i"),
216
+ cfg: new RegExp($t.join("|"), "i"),
217
217
  img: /\.(png|jpe?g|gif|svg|bmp|tiff|ico)$/i,
218
218
  css: /\.(css|less|scss|sass|styl)$/i,
219
219
  html: /\.(html?)$/i,
220
220
  code: /\.(js|jsx|ts|tsx|java|py|c|cpp|cs|rb|php|go|swift|m|mm|kt|sh|bash)$/i,
221
221
  bin: /^(exe|dll|so|bin)\b/i,
222
- lock: new RegExp(Mt.join("|"), "i"),
222
+ lock: new RegExp(xt.join("|"), "i"),
223
223
  json: /\.json$/i
224
- }, Ne = (e, t) => {
224
+ }, De = (e, t) => {
225
225
  if (t?.extra && Array.isArray(t.extra)) {
226
226
  for (const n of t.extra)
227
227
  if (/^Binary files? /i.test(n) || /GIT binary patch/i.test(n))
228
228
  return "bin";
229
229
  }
230
- return Object.entries(xt).find(([, n]) => n.test(e))?.[0] ?? "other";
231
- }, $t = (e) => {
230
+ return Object.entries(Bt).find(([, n]) => n.test(e))?.[0] ?? "other";
231
+ }, Ut = (e) => {
232
232
  const t = e.split(`
233
233
  `), s = [];
234
- let n = null, o = null;
235
- if (t.forEach((r) => {
236
- if (r.startsWith("diff --git")) {
234
+ let n = null, r = null;
235
+ if (t.forEach((o) => {
236
+ if (o.startsWith("diff --git")) {
237
237
  if (n) {
238
238
  n.diff.tokens = n.diff.hunks.reduce(
239
239
  (f, d) => f + d.tokens,
240
240
  0
241
241
  ), n.tokens = n.diff.tokens;
242
242
  const l = n.filename.match(/\.([^.]+)$/);
243
- n.ext = l?.[1]?.toLowerCase() ?? "", n.category = Ne(
243
+ n.ext = l?.[1]?.toLowerCase() ?? "", n.category = De(
244
244
  n.filename,
245
245
  n.metadata
246
- ), n.programmingLanguage = Te(n.ext), s.push(n);
246
+ ), n.programmingLanguage = Ne(n.ext), s.push(n);
247
247
  }
248
- const i = r.match(/^diff --git a\/(.+?) b\/(.+)$/), a = i?.[1] ?? null;
248
+ const i = o.match(/^diff --git a\/(.+?) b\/(.+)$/), a = i?.[1] ?? null;
249
249
  n = {
250
250
  isNew: !1,
251
251
  isDeleted: !1,
@@ -263,93 +263,93 @@ const ro = Ve(), io = (e, t = {}, s = {}) => {
263
263
  ext: "",
264
264
  category: "other",
265
265
  programmingLanguage: void 0
266
- }, o = null;
267
- } else if (n && r.startsWith("new file mode")) {
268
- const i = r.split(" ");
266
+ }, r = null;
267
+ } else if (n && o.startsWith("new file mode")) {
268
+ const i = o.split(" ");
269
269
  n.isNew = !0, n.newFileMode = i[3] ?? null, n.metadata.newFileMode = n.newFileMode;
270
- } else if (n && r.startsWith("deleted file mode")) {
271
- const i = r.split(" ");
270
+ } else if (n && o.startsWith("deleted file mode")) {
271
+ const i = o.split(" ");
272
272
  n.isDeleted = !0, n.deletedFileMode = i[3] ?? null, n.metadata.deletedFileMode = n.deletedFileMode;
273
- } else if (n && r.startsWith("old mode")) {
274
- const i = r.split(" ");
273
+ } else if (n && o.startsWith("old mode")) {
274
+ const i = o.split(" ");
275
275
  n.metadata.oldMode = i[2] ?? null;
276
- } else if (n && r.startsWith("new mode")) {
277
- const i = r.split(" ");
276
+ } else if (n && o.startsWith("new mode")) {
277
+ const i = o.split(" ");
278
278
  n.metadata.newMode = i[2] ?? null;
279
- } else if (n && r.startsWith("similarity index")) {
280
- const i = r.split(" ");
279
+ } else if (n && o.startsWith("similarity index")) {
280
+ const i = o.split(" ");
281
281
  n.metadata.similarityIndex = i[2] ?? null;
282
- } else if (n && r.startsWith("rename from")) {
283
- const i = r.substring(11).trim();
282
+ } else if (n && o.startsWith("rename from")) {
283
+ const i = o.substring(11).trim();
284
284
  n.isRenamed = !0, n.oldFilename = i, n.metadata.renameFrom = i;
285
- } else if (n && r.startsWith("rename to")) {
286
- const i = r.substring(9).trim();
285
+ } else if (n && o.startsWith("rename to")) {
286
+ const i = o.substring(9).trim();
287
287
  n.isRenamed = !0, n.filename = i, n.metadata.renameTo = i;
288
- } else n && r.startsWith("index") ? n.metadata.index = r.substring(5).trim() : n && (r.startsWith("--- ") || r.startsWith("+++ ")) ? r.startsWith("--- ") ? n.metadata.oldFileMarker = r : n.metadata.newFileMarker = r : n && r.startsWith("@@") ? (o = {
289
- header: r,
290
- changes: [r],
291
- tokens: _e(r)
292
- }, n.diff.hunks.push(o)) : o && (r.startsWith("+") || r.startsWith("-") || r.startsWith(" ")) ? (o.changes.push(r), o.tokens += _e(r)) : n && (Array.isArray(n.metadata.extra) || (n.metadata.extra = []), n.metadata.extra.push(r));
288
+ } else n && o.startsWith("index") ? n.metadata.index = o.substring(5).trim() : n && (o.startsWith("--- ") || o.startsWith("+++ ")) ? o.startsWith("--- ") ? n.metadata.oldFileMarker = o : n.metadata.newFileMarker = o : n && o.startsWith("@@") ? (r = {
289
+ header: o,
290
+ changes: [o],
291
+ tokens: Ce(o)
292
+ }, n.diff.hunks.push(r)) : r && (o.startsWith("+") || o.startsWith("-") || o.startsWith(" ")) ? (r.changes.push(o), r.tokens += Ce(o)) : n && (Array.isArray(n.metadata.extra) || (n.metadata.extra = []), n.metadata.extra.push(o));
293
293
  }), n) {
294
- const r = n, i = r.filename.match(/\.([^.]+)$/);
295
- r.diff.tokens = r.diff.hunks.reduce(
294
+ const o = n, i = o.filename.match(/\.([^.]+)$/);
295
+ o.diff.tokens = o.diff.hunks.reduce(
296
296
  (a, c) => a + c.tokens,
297
297
  0
298
- ), r.tokens = r.diff.tokens, r.ext = i?.[1]?.toLowerCase() ?? "", r.category = Ne(r.filename, r.metadata), r.programmingLanguage = Te(r.ext), s.push(r);
298
+ ), o.tokens = o.diff.tokens, o.ext = i?.[1]?.toLowerCase() ?? "", o.category = De(o.filename, o.metadata), o.programmingLanguage = Ne(o.ext), s.push(o);
299
299
  }
300
300
  return s;
301
301
  }, P = (e, t) => {
302
302
  try {
303
- return Ge(e, { encoding: "utf-8" });
303
+ return Ve(e, { encoding: "utf-8" });
304
304
  } catch (s) {
305
305
  const n = s.status;
306
306
  return n !== void 0 && (t?.expectedExitCodes ?? []).includes(n) || O.error("[execSyncSafe] [running → failed] Command failed", { cause: s }), "";
307
307
  }
308
- }, Ce = (e) => /\.(test|spec)s?\./.test(e), Bt = () => P("git branch --list 2>/dev/null")?.match(/\s*\*?\s*(master|main)$/m)?.[1] ?? "master", co = () => P("git rev-parse --abbrev-ref HEAD 2>/dev/null").trim() || "HEAD", lo = () => {
308
+ }, Ae = (e) => /\.(test|spec)s?\./.test(e), Ft = () => P("git branch --list 2>/dev/null")?.match(/\s*\*?\s*(master|main)$/m)?.[1] ?? "master", fo = () => P("git rev-parse --abbrev-ref HEAD 2>/dev/null").trim() || "HEAD", po = () => {
309
309
  const t = (P("git config --get remote.origin.url 2>/dev/null").trim() || P("git remote get-url origin 2>/dev/null").trim() || "").trim();
310
310
  if (!t) return null;
311
311
  if (/^[a-z]+:\/\//i.test(t))
312
312
  try {
313
- const n = new URL(t), o = (n.hostname || "").toLowerCase(), r = (n.protocol || "").replace(/:$/, "").toLowerCase(), i = (n.pathname || "").replace(/^\/+/, "").replace(/\.git$/i, "");
314
- return !o || !i ? null : { host: o, project: i, scheme: r };
313
+ const n = new URL(t), r = (n.hostname || "").toLowerCase(), o = (n.protocol || "").replace(/:$/, "").toLowerCase(), i = (n.pathname || "").replace(/^\/+/, "").replace(/\.git$/i, "");
314
+ return !r || !i ? null : { host: r, project: i, scheme: o };
315
315
  } catch (n) {
316
316
  O.debug("[getGitRemote] [parsing → skip] URL parse failed", { cause: n });
317
317
  }
318
318
  const s = t.match(/^[\w.-]+@([^:\/]+)[:\/](.+)$/);
319
319
  if (s) {
320
- const n = (s[1] || "").toLowerCase(), o = (s[2] || "").replace(/^\/+/, "").replace(/\.git$/i, ""), r = "ssh";
321
- return !n || !o ? null : { host: n, project: o, scheme: r };
320
+ const n = (s[1] || "").toLowerCase(), r = (s[2] || "").replace(/^\/+/, "").replace(/\.git$/i, ""), o = "ssh";
321
+ return !n || !r ? null : { host: n, project: r, scheme: o };
322
322
  }
323
323
  return null;
324
- }, Ut = () => {
324
+ }, Gt = () => {
325
325
  try {
326
- const e = P(`git rev-list --count HEAD ^${Bt()} 2>/dev/null`);
326
+ const e = P(`git rev-list --count HEAD ^${Ft()} 2>/dev/null`);
327
327
  return parseInt(e, 10) || 0;
328
328
  } catch (e) {
329
329
  return O.debug("[getGitCommitCount] [counting → fallback] Using 0", { cause: e }), 0;
330
330
  }
331
- }, Gt = (e) => P(e ? `git diff ${e}` : "git diff HEAD"), uo = (e) => {
332
- const t = Gt(e), s = $t(t).sort((a, c) => a.tokens - c.tokens), n = s.filter(
333
- (a) => !a.isDeleted && !a.isRenamed && !Ce(a.filename) && (a.category === "config" || a.programmingLanguage)
331
+ }, Vt = (e) => P(e ? `git diff ${e}` : "git diff HEAD"), mo = (e) => {
332
+ const t = Vt(e), s = Ut(t).sort((a, c) => a.tokens - c.tokens), n = s.filter(
333
+ (a) => !a.isDeleted && !a.isRenamed && !Ae(a.filename) && (a.category === "config" || a.programmingLanguage)
334
334
  );
335
335
  n.length || n.push(
336
336
  ...s.filter(
337
- (a) => !a.isDeleted && !a.isRenamed && (a.category === "doc" || Ce(a.filename))
337
+ (a) => !a.isDeleted && !a.isRenamed && (a.category === "doc" || Ae(a.filename))
338
338
  )
339
339
  );
340
- const o = n.reduce((a, c) => a + c.tokens, 0), r = n.at(-1)?.tokens ?? 0, i = [
340
+ const r = n.reduce((a, c) => a + c.tokens, 0), o = n.at(-1)?.tokens ?? 0, i = [
341
341
  ...new Set(n.map((a) => a.programmingLanguage).filter(Boolean))
342
342
  ];
343
343
  return {
344
344
  diff: t,
345
345
  parsedDiff: s,
346
346
  parsedCodeDiff: n,
347
- parsedCodeTokens: o,
348
- parsedCodeChunkMaxTokens: r,
347
+ parsedCodeTokens: r,
348
+ parsedCodeChunkMaxTokens: o,
349
349
  programmingLanguages: i,
350
- commitCount: Ut()
350
+ commitCount: Gt()
351
351
  };
352
- }, Ft = (e) => {
352
+ }, jt = (e) => {
353
353
  if (Array.isArray(e) && e.length === 2) {
354
354
  const t = e[1];
355
355
  if (t === null)
@@ -360,11 +360,11 @@ const ro = Ve(), io = (e, t = {}, s = {}) => {
360
360
  "[UNGUARD_ERROR_SYNTAX] Invalid input: not a valid [result, error] tuple.",
361
361
  { cause: e }
362
362
  );
363
- }, fo = async (e) => {
363
+ }, Eo = async (e) => {
364
364
  const t = await e;
365
- return Ft(t);
366
- }, De = "</think>", po = (e) => {
367
- const t = String(e ?? "").split(De).slice(-1).join(De).trim();
365
+ return jt(t);
366
+ }, ye = "</think>", ho = (e) => {
367
+ const t = String(e ?? "").split(ye).slice(-1).join(ye).trim();
368
368
  return /^(Хорошо,|Okay,)/.test(t) ? t.split(`
369
369
 
370
370
 
@@ -373,7 +373,7 @@ const ro = Ve(), io = (e, t = {}, s = {}) => {
373
373
 
374
374
  `).trim() : t;
375
375
  };
376
- class re {
376
+ class ae {
377
377
  /** @purpose Default configuration filename. */
378
378
  static DEFAULT_FILENAME = ".gennadyrc";
379
379
  /**
@@ -382,7 +382,7 @@ class re {
382
382
  * @sideEffect IO: file read at constructor.
383
383
  */
384
384
  static getDefaults() {
385
- return [process.cwd(), process.env.HOME].map((t) => new re(t));
385
+ return [process.cwd(), process.env.HOME].map((t) => new ae(t));
386
386
  }
387
387
  /** @purpose Full path to the loaded rc config file. */
388
388
  _filename = "";
@@ -397,11 +397,11 @@ class re {
397
397
  * @param [dir] Directory to look for the rc file in (defaults to cwd).
398
398
  * @param [name] Config filename (defaults to .gennadyrc).
399
399
  */
400
- constructor(t = process.cwd(), s = re.DEFAULT_FILENAME) {
400
+ constructor(t = process.cwd(), s = ae.DEFAULT_FILENAME) {
401
401
  this._filename = h(t, s);
402
402
  try {
403
403
  if (R(this._filename)) {
404
- const n = JSON.parse(D(this._filename).toString());
404
+ const n = JSON.parse(C(this._filename).toString());
405
405
  Array.isArray(n) ? this._data.models = n : n && typeof n == "object" && Array.isArray(n.models) ? this._data = {
406
406
  ...this._data,
407
407
  ...n
@@ -438,7 +438,7 @@ class re {
438
438
  return this._error;
439
439
  }
440
440
  }
441
- const Vt = Dt(It);
441
+ const Yt = yt(Tt);
442
442
  class A extends Error {
443
443
  /**
444
444
  * @purpose Create a VCS resolution error with an optional root cause.
@@ -449,36 +449,36 @@ class A extends Error {
449
449
  super(t, { cause: s }), this.name = "VcsResolveError";
450
450
  }
451
451
  }
452
- function jt() {
452
+ function Ht() {
453
453
  return {
454
454
  git: async (e) => {
455
- const { stdout: t } = await Vt("git", e, { encoding: "utf-8" });
455
+ const { stdout: t } = await Yt("git", e, { encoding: "utf-8" });
456
456
  return String(t ?? "").trim();
457
457
  },
458
458
  env: (e) => process.env[e]
459
459
  };
460
460
  }
461
- function Yt(e) {
461
+ function qt(e) {
462
462
  const t = e.lastIndexOf("!");
463
463
  if (t === -1) return null;
464
- const s = e.slice(0, t), n = e.slice(t + 1), o = Number(n);
465
- return !s || !Number.isInteger(o) || o <= 0 ? null : { project: s, iid: o };
464
+ const s = e.slice(0, t), n = e.slice(t + 1), r = Number(n);
465
+ return !s || !Number.isInteger(r) || r <= 0 ? null : { project: s, iid: r };
466
466
  }
467
- function Ht(e) {
467
+ function Wt(e) {
468
468
  const t = e.match(/^git@([^:]+):(.+)\.git$/);
469
469
  if (t)
470
470
  return { host: t[1], project: t[2] };
471
471
  const s = e.match(/^https?:\/\/([^/]+)\/(.+)\.git$/);
472
472
  return s ? { host: s[1], project: s[2] } : null;
473
473
  }
474
- function qt(e) {
474
+ function Kt(e) {
475
475
  const t = e.match(/^https?:\/\/([^/]+)\/(.+)\/-\/merge_requests\/(\d+)\/?$/);
476
476
  return t ? { host: t[1], project: t[2], iid: Number(t[3]) } : null;
477
477
  }
478
- async function Wt(e, t = jt()) {
478
+ async function Xt(e, t = Ht()) {
479
479
  if (O.debug("[resolveVcsContext] [idle → resolving]"), typeof e.url == "string") {
480
480
  O.debug("[resolveVcsContext] [resolving → parsing-url]");
481
- const d = qt(e.url);
481
+ const d = Kt(e.url);
482
482
  if (!d) {
483
483
  const N = `[resolveVcsContext] Некорректный URL: ${e.url}`;
484
484
  throw O.error(`[resolveVcsContext] [resolving → failed] ${N}`), new A(`Некорректный URL: ${e.url}`);
@@ -493,25 +493,25 @@ async function Wt(e, t = jt()) {
493
493
  }
494
494
  if (typeof e.ref == "string" && e.branch)
495
495
  throw O.error("[resolveVcsContext] [resolving → failed] [resolveVcsContext] ref и branch не могут быть указаны одновременно"), new A("ref и branch не могут быть указаны одновременно");
496
- const s = typeof e.ref == "string" ? Yt(e.ref) : null;
496
+ const s = typeof e.ref == "string" ? qt(e.ref) : null;
497
497
  if (typeof e.ref == "string" && !s) {
498
498
  const d = `[resolveVcsContext] Некорректный формат ref: ${e.ref}`;
499
499
  throw O.error(`[resolveVcsContext] [resolving → failed] ${d}`), new A(`Некорректный формат ref: ${e.ref}`);
500
500
  }
501
- const n = s?.iid ?? e.iid, o = s?.project ?? e.project;
502
- let r = e.host, i = o;
503
- if (!r || !i)
501
+ const n = s?.iid ?? e.iid, r = s?.project ?? e.project;
502
+ let o = e.host, i = r;
503
+ if (!o || !i)
504
504
  try {
505
505
  O.debug("[resolveVcsContext] [resolving → fetching-remote]");
506
- const d = await t.git(["config", "remote.origin.url"]), u = Ht(d);
506
+ const d = await t.git(["config", "remote.origin.url"]), u = Wt(d);
507
507
  if (!u) {
508
508
  const p = `[resolveVcsContext] Не удалось разобрать URL удалённого репозитория: ${d}`;
509
509
  throw O.error(`[resolveVcsContext] [resolving → failed] ${p}`), new A(`Не удалось разобрать URL удалённого репозитория: ${d}`);
510
510
  }
511
- r ??= u.host, i ??= u.project;
511
+ o ??= u.host, i ??= u.project;
512
512
  } catch (d) {
513
513
  if (d instanceof A) throw d;
514
- if (!o) {
514
+ if (!r) {
515
515
  const u = "[resolveVcsContext] Не найден удалённый репозиторий origin", p = new A("Не найден удалённый репозиторий origin", d);
516
516
  throw O.error(`[resolveVcsContext] [resolving → failed] ${u}`, { error: p }), p;
517
517
  }
@@ -519,9 +519,9 @@ async function Wt(e, t = jt()) {
519
519
  "[resolveVcsContext] [resolving → remote-unreachable] project explicit, skipping host auto-detect"
520
520
  );
521
521
  }
522
- if (!r || !i)
522
+ if (!o || !i)
523
523
  throw O.error("[resolveVcsContext] [resolving → failed] [resolveVcsContext] Не удалось определить host и project"), new A("Не удалось определить host и project");
524
- const a = /github/i.test(r) ? "github" : "gitlab";
524
+ const a = /github/i.test(o) ? "github" : "gitlab";
525
525
  let c = e.branch;
526
526
  if (!s && n === void 0)
527
527
  try {
@@ -540,35 +540,35 @@ async function Wt(e, t = jt()) {
540
540
  }
541
541
  const f = {
542
542
  provider: a,
543
- host: r,
543
+ host: o,
544
544
  project: i,
545
545
  iid: n,
546
546
  branch: c,
547
547
  token: l
548
548
  };
549
549
  return O.info(
550
- `[resolveVcsContext] [resolving → resolved] ${r}/${i}${n ? `!${n}` : ""}`
550
+ `[resolveVcsContext] [resolving → resolved] ${o}/${i}${n ? `!${n}` : ""}`
551
551
  ), f;
552
552
  }
553
- const mo = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
553
+ const So = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
554
554
  __proto__: null,
555
555
  VcsResolveError: A,
556
- resolveVcsContext: Wt
556
+ resolveVcsContext: Xt
557
557
  }, Symbol.toStringTag, { value: "Module" }));
558
- function Eo(e) {
558
+ function go(e) {
559
559
  const t = String(e).match(/<message[\s\S]*?>[\s\S]*?<\/message>/)?.[0];
560
560
  if (!t)
561
561
  return null;
562
- const s = (a) => t.match(a)?.[1] ?? "", n = s(/type="([^"]+)"/), o = s(/icon="([^"]+)"/), r = s(/<subject>([\s\S]*?)<\/subject>/), i = s(/<description>([\s\S]*?)<\/description>/).replace(/\n\s+-/g, `
562
+ const s = (a) => t.match(a)?.[1] ?? "", n = s(/type="([^"]+)"/), r = s(/icon="([^"]+)"/), o = s(/<subject>([\s\S]*?)<\/subject>/), i = s(/<description>([\s\S]*?)<\/description>/).replace(/\n\s+-/g, `
563
563
  -`);
564
564
  return {
565
565
  type: n,
566
- icon: o,
567
- subject: r?.trim() || null,
566
+ icon: r,
567
+ subject: o?.trim() || null,
568
568
  description: i?.trim() || null
569
569
  };
570
570
  }
571
- function se(e) {
571
+ function oe(e) {
572
572
  return e ? String(e).replace(/[<>&'"]/g, (t) => {
573
573
  switch (t) {
574
574
  case "<":
@@ -586,37 +586,37 @@ function se(e) {
586
586
  }
587
587
  }) : "";
588
588
  }
589
- function Ae(e, t = 0) {
590
- const s = " ".repeat(t), { tag: n, attrs: o, children: r } = e;
589
+ function Re(e, t = 0) {
590
+ const s = " ".repeat(t), { tag: n, attrs: r, children: o } = e;
591
591
  let i = "";
592
- if (o && (i = Object.entries(o).filter(([, c]) => c != null).map(([c, l]) => ` ${c}="${se(String(l))}"`).join("")), r == null)
592
+ if (r && (i = Object.entries(r).filter(([, c]) => c != null).map(([c, l]) => ` ${c}="${oe(String(l))}"`).join("")), o == null)
593
593
  return `${s}<${n}${i} />`;
594
- if (Array.isArray(r) && r.length === 0)
594
+ if (Array.isArray(o) && o.length === 0)
595
595
  return `${s}<${n}${i} />`;
596
596
  let a = "";
597
- return Array.isArray(r) ? r.length > 0 && typeof r[0] == "string" ? a = r.map((l) => se(l)).join(`
597
+ return Array.isArray(o) ? o.length > 0 && typeof o[0] == "string" ? a = o.map((l) => oe(l)).join(`
598
598
  `) : a = `
599
- ` + r.map((l) => Ae(l, t + 1)).join(`
599
+ ` + o.map((l) => Re(l, t + 1)).join(`
600
600
  `) + `
601
- ` + s : typeof r == "string" ? a = se(r) : "cdata" in r ? a = `<![CDATA[${String(r.cdata).replaceAll("]]>", "]]]]><![CDATA[>")}]]>` : a = `
602
- ` + Ae(r, t + 1) + `
601
+ ` + s : typeof o == "string" ? a = oe(o) : "cdata" in o ? a = `<![CDATA[${String(o.cdata).replaceAll("]]>", "]]]]><![CDATA[>")}]]>` : a = `
602
+ ` + Re(o, t + 1) + `
603
603
  ` + s, `${s}<${n}${i}>${a}</${n}>`;
604
604
  }
605
- function ho(e) {
605
+ function Io(e) {
606
606
  const t = [
607
607
  "ai.knowledge.md",
608
608
  "ai/ai.knowledge.md"
609
609
  ], s = [];
610
610
  for (const n of t) {
611
- const o = k.join(e, n);
611
+ const r = k.join(e, n);
612
612
  try {
613
- v.existsSync(o) && v.statSync(o).isFile() && s.push(n);
613
+ v.existsSync(r) && v.statSync(r).isFile() && s.push(n);
614
614
  } catch {
615
615
  }
616
616
  }
617
617
  return s.length === 0 ? "" : `**MUST READ PROJECT KNOWLEDGE FILES**: ${s.join(", ")}.`;
618
618
  }
619
- const Kt = [
619
+ const Zt = [
620
620
  {
621
621
  kind: "marker",
622
622
  relativePath: "go.mod",
@@ -655,7 +655,7 @@ const Kt = [
655
655
  commands: ["cargo test", "cargo clippy"]
656
656
  }
657
657
  ];
658
- function Xt(e, t) {
658
+ function zt(e, t) {
659
659
  const s = k.join(e, t);
660
660
  try {
661
661
  return v.existsSync(s) && v.statSync(s).isFile();
@@ -663,28 +663,28 @@ function Xt(e, t) {
663
663
  return !1;
664
664
  }
665
665
  }
666
- function Zt(e, t) {
666
+ function Qt(e, t) {
667
667
  const s = e.toLowerCase(), n = t.toLowerCase();
668
668
  return /(^|:|-)watch($|:|-)/i.test(s) ? !0 : [
669
669
  /(^|\s)--watch(?:[=\s]|$)/i,
670
670
  /(^|\s)--watchall(?:[=\s]|$)/i,
671
671
  /(^|\s)watch(?:\s|$)/i,
672
672
  /(^|\s)nodemon(?:\s|$)/i
673
- ].some((r) => r.test(n));
673
+ ].some((o) => o.test(n));
674
674
  }
675
- function zt(e, t, s) {
675
+ function Jt(e, t, s) {
676
676
  const n = Object.entries(e).filter(
677
- ([o, r]) => !s.has(o) && !Zt(o, r)
677
+ ([r, o]) => !s.has(r) && !Qt(r, o)
678
678
  );
679
- for (const o of t.preferredNames)
680
- if (n.some(([r]) => r === o))
681
- return o;
682
- for (const [o] of n)
683
- if (t.fallbackPatterns.some((r) => r.test(o)))
684
- return o;
679
+ for (const r of t.preferredNames)
680
+ if (n.some(([o]) => o === r))
681
+ return r;
682
+ for (const [r] of n)
683
+ if (t.fallbackPatterns.some((o) => o.test(r)))
684
+ return r;
685
685
  return null;
686
686
  }
687
- function Qt(e, t) {
687
+ function es(e, t) {
688
688
  const s = k.join(e, "package.json");
689
689
  let n;
690
690
  try {
@@ -694,61 +694,61 @@ function Qt(e, t) {
694
694
  } catch {
695
695
  return null;
696
696
  }
697
- let o;
697
+ let r;
698
698
  try {
699
- o = JSON.parse(n);
699
+ r = JSON.parse(n);
700
700
  } catch {
701
701
  return null;
702
702
  }
703
- const r = o.scripts;
704
- if (!r || typeof r != "object")
703
+ const o = r.scripts;
704
+ if (!o || typeof o != "object")
705
705
  return null;
706
706
  const i = [], a = /* @__PURE__ */ new Set();
707
707
  for (const c of t.scriptGroups) {
708
- const l = zt(r, c, a);
708
+ const l = Jt(o, c, a);
709
709
  if (l && (i.push(`npm run ${l}`), a.add(l)), i.length >= t.maxCommands)
710
710
  break;
711
711
  }
712
712
  return i.length === 0 ? null : i.slice(0, t.maxCommands);
713
713
  }
714
- function Jt(e) {
715
- for (const t of Kt) {
714
+ function ts(e) {
715
+ for (const t of Zt) {
716
716
  if (t.kind === "marker") {
717
- if (Xt(e, t.relativePath))
717
+ if (zt(e, t.relativePath))
718
718
  return [...t.commands];
719
719
  continue;
720
720
  }
721
721
  if (t.kind === "npm-package-json") {
722
- const s = Qt(e, t);
722
+ const s = es(e, t);
723
723
  if (s != null && s.length > 0)
724
724
  return s;
725
725
  }
726
726
  }
727
727
  return [];
728
728
  }
729
- function es(e) {
729
+ function ss(e) {
730
730
  return e.map((t) => `\`${t}\``).join(", ");
731
731
  }
732
- function So(e) {
733
- const t = Jt(e);
732
+ function Oo(e) {
733
+ const t = ts(e);
734
734
  if (t.length === 0)
735
735
  return {
736
736
  axiomHint: "как в README или CI принято проверять код (тесты, линтер, типы). Не подменяй это тяжёлой production-сборкой или публикацией, если это явно не описано как проверка",
737
737
  toolsExample: "команды из `package.json` → `scripts`, из Makefile или из CI-шагов, которые относятся к качеству кода; сначала прочитай README",
738
738
  verifyStep: "Прочитай README и при наличии — конфиг CI: какие команды запускают тесты, линтер и проверку типов. Выполни их из корня репозитория. Не запускай `build`/`publish`/полный `ci`, если не уверен, что это нужно для проверки изменений; при сомнении спроси пользователя."
739
739
  };
740
- const s = es(t);
740
+ const s = ss(t);
741
741
  return {
742
742
  axiomHint: `\`${t[0]}\` или следующую команду из того же набора проверок`,
743
743
  toolsExample: s,
744
744
  verifyStep: `Из корня репозитория выполни: ${s}. Не добавляй \`build\`, полный \`ci\` или публикацию, если они не перечислены здесь и не описаны в README как обязательная проверка.`
745
745
  };
746
746
  }
747
- const Y = "ai/agents";
748
- function ye(e) {
747
+ const H = "ai/agents";
748
+ function ke(e) {
749
749
  return v.existsSync(e) ? v.promises.readFile(e, "utf-8") : null;
750
750
  }
751
- function ts(e) {
751
+ function ns(e) {
752
752
  let t = e;
753
753
  for (; ; ) {
754
754
  const s = k.join(t, "package.json");
@@ -760,27 +760,27 @@ function ts(e) {
760
760
  t = n;
761
761
  }
762
762
  }
763
- async function go(e) {
764
- const t = k.dirname(fe(import.meta.url)), s = k.join(process.cwd(), Y, e), n = ye(s);
763
+ async function To(e) {
764
+ const t = k.dirname(me(import.meta.url)), s = k.join(process.cwd(), H, e), n = ke(s);
765
765
  if (n)
766
766
  return n;
767
- const o = ts(t), r = [];
768
- o ? (r.push(k.join(o, Y, e)), r.push(k.join(o, "dist", Y, e))) : r.push(
769
- k.join(t, "../../../../../../dist", Y, e)
767
+ const r = ns(t), o = [];
768
+ r ? (o.push(k.join(r, H, e)), o.push(k.join(r, "dist", H, e))) : o.push(
769
+ k.join(t, "../../../../../../dist", H, e)
770
770
  );
771
- for (const i of r) {
772
- const a = ye(i);
771
+ for (const i of o) {
772
+ const a = ke(i);
773
773
  if (a)
774
774
  return a;
775
775
  }
776
776
  throw new Error(`Не найден файл шаблона ${e}.`, {
777
777
  cause: {
778
778
  projectOverridePath: s,
779
- packageCandidates: r
779
+ packageCandidates: o
780
780
  }
781
781
  });
782
782
  }
783
- const je = ["product", "library", "infrastructure", "interface"], z = "One-line human summary of how many decisions and what area; fold the full D-NNN entries under <details> per AX_SPEC_PROGRESSIVE_DISCLOSURE.", Q = 'One-line human summary of outstanding prerequisites; fold the full Requirement/Kind/Owner/Resolution table under <details>. Declare explicitly ("No external bootstrap required.") when the STEP_7 audit found none — do not leave the table silently empty.', F = "MANDATORY (AX_SPEC_MANDATORY_DIAGRAM): at least one fenced mermaid or ASCII diagram giving a reader the shape of this artifact at a glance, up top.", ss = "List infra-*/api/design-system-* scopes this scope depends on, and any consumer scopes it provides to.", ns = `# <scope-name>: Scope Specification
783
+ const He = ["product", "library", "infrastructure", "interface"], J = "One-line human summary of how many decisions and what area; fold the full D-NNN entries under <details> per AX_SPEC_PROGRESSIVE_DISCLOSURE.", ee = 'One-line human summary of outstanding prerequisites; fold the full Requirement/Kind/Owner/Resolution table under <details>. Declare explicitly ("No external bootstrap required.") when the STEP_7 audit found none — do not leave the table silently empty.', j = "MANDATORY (AX_SPEC_MANDATORY_DIAGRAM): at least one fenced mermaid or ASCII diagram giving a reader the shape of this artifact at a glance, up top.", os = "List infra-*/api/design-system-* scopes this scope depends on, and any consumer scopes it provides to.", rs = `# <scope-name>: Scope Specification
784
784
 
785
785
  <!--SECTION:SCOPE_TYPE-->
786
786
  ## scope-type
@@ -885,7 +885,7 @@ flowchart TD
885
885
 
886
886
  <!-- Pivot Invalidation List — only in pivot mode -->
887
887
  <!--/SECTION:HANDOFF-->
888
- `, os = [
888
+ `, is = [
889
889
  {
890
890
  name: "SCOPE_TYPE",
891
891
  required: !0,
@@ -900,7 +900,7 @@ flowchart TD
900
900
  fold: !1,
901
901
  fill: "Vision & primary goal — what this product scope is for, in a sentence or two."
902
902
  },
903
- { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: F },
903
+ { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: j },
904
904
  {
905
905
  name: "PROJECT_TYPE",
906
906
  required: !0,
@@ -920,7 +920,7 @@ flowchart TD
920
920
  required: !0,
921
921
  loadBearing: !1,
922
922
  fold: !1,
923
- fill: ss
923
+ fill: os
924
924
  },
925
925
  {
926
926
  name: "REQUIREMENTS_AND_CONSTRAINTS",
@@ -943,13 +943,13 @@ flowchart TD
943
943
  fold: !1,
944
944
  fill: "Appended by module-decomposition; initially a placeholder pointing at that command."
945
945
  },
946
- { name: "DECISION_LOG", required: !0, loadBearing: !0, fold: !0, fill: z },
946
+ { name: "DECISION_LOG", required: !0, loadBearing: !0, fold: !0, fill: J },
947
947
  {
948
948
  name: "BOOTSTRAP_REQUIREMENTS",
949
949
  required: !0,
950
950
  loadBearing: !1,
951
951
  fold: !0,
952
- fill: Q
952
+ fill: ee
953
953
  },
954
954
  {
955
955
  name: "HANDOFF",
@@ -958,7 +958,7 @@ flowchart TD
958
958
  fold: !1,
959
959
  fill: "Primary input path, areas requiring decomposition, named abstractions, bootstrap tickets, open risks."
960
960
  }
961
- ], rs = `# <scope-name>: Library Specification
961
+ ], as = `# <scope-name>: Library Specification
962
962
 
963
963
  <!--SECTION:SCOPE_TYPE-->
964
964
  ## scope-type
@@ -1054,7 +1054,7 @@ flowchart LR
1054
1054
 
1055
1055
  <!-- Pivot Invalidation List — only in pivot mode -->
1056
1056
  <!--/SECTION:HANDOFF-->
1057
- `, is = [
1057
+ `, cs = [
1058
1058
  {
1059
1059
  name: "SCOPE_TYPE",
1060
1060
  required: !0,
@@ -1069,7 +1069,7 @@ flowchart LR
1069
1069
  fold: !1,
1070
1070
  fill: "What the library does and the main problem it solves."
1071
1071
  },
1072
- { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: F },
1072
+ { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: j },
1073
1073
  {
1074
1074
  name: "GOLDEN_DX",
1075
1075
  required: !0,
@@ -1105,13 +1105,13 @@ flowchart LR
1105
1105
  fold: !1,
1106
1106
  fill: "Chosen design pattern, briefly, plus rejected alternatives."
1107
1107
  },
1108
- { name: "DECISION_LOG", required: !0, loadBearing: !0, fold: !0, fill: z },
1108
+ { name: "DECISION_LOG", required: !0, loadBearing: !0, fold: !0, fill: J },
1109
1109
  {
1110
1110
  name: "BOOTSTRAP_REQUIREMENTS",
1111
1111
  required: !0,
1112
1112
  loadBearing: !1,
1113
1113
  fold: !0,
1114
- fill: Q
1114
+ fill: ee
1115
1115
  },
1116
1116
  {
1117
1117
  name: "HANDOFF",
@@ -1120,7 +1120,7 @@ flowchart LR
1120
1120
  fold: !1,
1121
1121
  fill: "Areas requiring decomposition, named abstractions, bootstrap tickets, open risks."
1122
1122
  }
1123
- ], as = `# <scope-name>: Infrastructure Specification
1123
+ ], ls = `# <scope-name>: Infrastructure Specification
1124
1124
 
1125
1125
  <!--SECTION:SCOPE_TYPE-->
1126
1126
  ## scope-type
@@ -1235,7 +1235,7 @@ Include only command names for tools present in the chosen stack.
1235
1235
 
1236
1236
  <!-- Pivot Invalidation List — only in pivot mode -->
1237
1237
  <!--/SECTION:HANDOFF-->
1238
- `, cs = [
1238
+ `, ds = [
1239
1239
  {
1240
1240
  name: "SCOPE_TYPE",
1241
1241
  required: !0,
@@ -1250,7 +1250,7 @@ Include only command names for tools present in the chosen stack.
1250
1250
  fold: !1,
1251
1251
  fill: "What dev/ops experience this scope covers."
1252
1252
  },
1253
- { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: F },
1253
+ { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: j },
1254
1254
  {
1255
1255
  name: "SCOPE_DEPENDENCIES",
1256
1256
  required: !0,
@@ -1293,13 +1293,13 @@ Include only command names for tools present in the chosen stack.
1293
1293
  fold: !1,
1294
1294
  fill: "Mandatory: Command Name/Invocation table for the active phases (typecheck/test/lint/format) plus the composed check-command alias."
1295
1295
  },
1296
- { name: "DECISION_LOG", required: !0, loadBearing: !0, fold: !0, fill: z },
1296
+ { name: "DECISION_LOG", required: !0, loadBearing: !0, fold: !0, fill: J },
1297
1297
  {
1298
1298
  name: "BOOTSTRAP_REQUIREMENTS",
1299
1299
  required: !0,
1300
1300
  loadBearing: !1,
1301
1301
  fold: !0,
1302
- fill: Q
1302
+ fill: ee
1303
1303
  },
1304
1304
  {
1305
1305
  name: "HANDOFF",
@@ -1308,7 +1308,7 @@ Include only command names for tools present in the chosen stack.
1308
1308
  fold: !1,
1309
1309
  fill: "Setup tasks to scaffold, effective rules/verification commands/bootstrap tickets ready for cascade, open risks."
1310
1310
  }
1311
- ], ls = `# <scope-name>: Interface Specification
1311
+ ], us = `# <scope-name>: Interface Specification
1312
1312
 
1313
1313
  <!--SECTION:SCOPE_TYPE-->
1314
1314
  ## scope-type
@@ -1395,7 +1395,7 @@ flowchart LR
1395
1395
  - **Bootstrap tickets ready for cascade:** see Prerequisites
1396
1396
  - **Open risks:** [versioning gaps, unconfirmed consumers]
1397
1397
  <!--/SECTION:HANDOFF-->
1398
- `, ds = [
1398
+ `, fs = [
1399
1399
  {
1400
1400
  name: "SCOPE_TYPE",
1401
1401
  required: !0,
@@ -1410,7 +1410,7 @@ flowchart LR
1410
1410
  fold: !1,
1411
1411
  fill: "What the contract defines, and for whom."
1412
1412
  },
1413
- { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: F },
1413
+ { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: j },
1414
1414
  {
1415
1415
  name: "SCOPE_DEPENDENCIES",
1416
1416
  required: !0,
@@ -1439,13 +1439,13 @@ flowchart LR
1439
1439
  fold: !0,
1440
1440
  fill: "One-line summary of consumer count / pending breaking changes; full Consumer/Min-version/Breaking-change-protocol matrix folds under <details>."
1441
1441
  },
1442
- { name: "DECISION_LOG", required: !0, loadBearing: !0, fold: !0, fill: z },
1442
+ { name: "DECISION_LOG", required: !0, loadBearing: !0, fold: !0, fill: J },
1443
1443
  {
1444
1444
  name: "BOOTSTRAP_REQUIREMENTS",
1445
1445
  required: !0,
1446
1446
  loadBearing: !1,
1447
1447
  fold: !0,
1448
- fill: Q
1448
+ fill: ee
1449
1449
  },
1450
1450
  {
1451
1451
  name: "HANDOFF",
@@ -1454,7 +1454,7 @@ flowchart LR
1454
1454
  fold: !1,
1455
1455
  fill: "Contract files to scaffold (schemas, codegen configs), bootstrap tickets, open risks."
1456
1456
  }
1457
- ], us = `# Module: <ModuleName>
1457
+ ], ps = `# Module: <ModuleName>
1458
1458
 
1459
1459
  <!--SECTION:MODULE_VISION-->
1460
1460
  ## Module Vision
@@ -1596,7 +1596,7 @@ graph TD
1596
1596
 
1597
1597
  </details>
1598
1598
  <!--/SECTION:IMPLEMENTATION_INSIGHTS-->
1599
- `, fs = [
1599
+ `, ms = [
1600
1600
  {
1601
1601
  name: "MODULE_VISION",
1602
1602
  required: !0,
@@ -1604,7 +1604,7 @@ graph TD
1604
1604
  fold: !1,
1605
1605
  fill: "What this module owns; link to the parent scope spec and to sibling/parent/child modules."
1606
1606
  },
1607
- { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: F },
1607
+ { name: "OVERVIEW", required: !0, loadBearing: !1, fold: !1, fill: j },
1608
1608
  {
1609
1609
  name: "MODULE_USAGE_EXAMPLE",
1610
1610
  required: !0,
@@ -1675,7 +1675,7 @@ graph TD
1675
1675
  fold: !1,
1676
1676
  fill: "Optional appendix — non-trivial post-implementation learnings (library wrap patterns, transaction subtleties, fake-runtime pitfalls), added after audit-cycle compaction."
1677
1677
  }
1678
- ], ps = `# Task: <ACRONYM>-<slug> — <Task Title>
1678
+ ], Es = `# Task: <ACRONYM>-<slug> — <Task Title>
1679
1679
 
1680
1680
  <!--SECTION:META-->
1681
1681
  ## Meta
@@ -1783,7 +1783,7 @@ use-case → \`[<ACRONYM>-REQ-N]\` → vision chain the operator reviews at scaf
1783
1783
  <!--/SECTION:DECISION_LOG-->
1784
1784
 
1785
1785
  <!-- AUDIT_ROUNDS appended only after the first reopen-triggering audit (per the audit directive). -->
1786
- `, ms = [
1786
+ `, hs = [
1787
1787
  {
1788
1788
  name: "META",
1789
1789
  required: !0,
@@ -1840,7 +1840,7 @@ use-case → \`[<ACRONYM>-REQ-N]\` → vision chain the operator reviews at scaf
1840
1840
  fold: !1,
1841
1841
  fill: "Local ADR-compact decisions taken during execution; omit if none beyond the spec."
1842
1842
  }
1843
- ], Es = `# <module> — Tasks
1843
+ ], Ss = `# <module> — Tasks
1844
1844
 
1845
1845
  ## Tracker Index
1846
1846
  | Task-ID | Title | Dependencies | Status | Reopens |
@@ -1863,7 +1863,7 @@ graph TD
1863
1863
 
1864
1864
  ## Conventions
1865
1865
  Project-wide conventions (Execution-Log token vocabulary, Baseline Completion Rule, post-task audit hook, file-header) are declared once in \`specs/3-tasks.md\` and inherited here — not repeated.
1866
- `, hs = [
1866
+ `, gs = [
1867
1867
  {
1868
1868
  name: "TRACKER_INDEX",
1869
1869
  required: !0,
@@ -1899,7 +1899,7 @@ Project-wide conventions (Execution-Log token vocabulary, Baseline Completion Ru
1899
1899
  fold: !1,
1900
1900
  fill: "Pointer to specs/3-tasks.md — project-wide conventions are declared once there, inherited here."
1901
1901
  }
1902
- ], Ss = `# Tasks: <scope>
1902
+ ], Is = `# Tasks: <scope>
1903
1903
 
1904
1904
  ## Scope Spec
1905
1905
  - [Scope spec](./<scope>.spec.md)
@@ -1925,7 +1925,7 @@ graph TD
1925
1925
 
1926
1926
  ## Decision Log (scope task level)
1927
1927
  [D-NNN for scope-level decomposition / planning choices.]
1928
- `, gs = [
1928
+ `, Os = [
1929
1929
  {
1930
1930
  name: "SCOPE_SPEC_LINK",
1931
1931
  required: !0,
@@ -1961,7 +1961,7 @@ graph TD
1961
1961
  fold: !1,
1962
1962
  fill: "Scope-level decomposition/planning decisions, D-NNN, ADR-compact."
1963
1963
  }
1964
- ], Is = "# Project Tasks\n\n## Entry Points\n- [Specs Portal](./README.md) — Scope Graph + all scope specs.\n- Tickets execute ONLY via the `/sdd-execute` flow (one ticket) or its batch form; the orchestrator dispatches phase-workers then audit — the operator does not invoke audit by hand.\n\n## Project-Wide Conventions (declared once, inherited)\n- **File-header:** owned by the coding rule (`@file` / `@consumers` / `@tasks`), enforced by `sdd-verify`.\n- **Baseline Completion Rule:** a Round cannot go `[x] DONE` until — every phase `[x]`; every BDD scenario mapped to a test or `Deferred Test Ownership`; verification commands run with exit recorded; every entity beyond the Inventory logged `intro …`; a Handoff line closes each phase.\n- **Execution-Log token vocabulary:** `intro <Entity> ← <reason>` · `decision <key>=<value> ← <reason>` · `tried <approach> → <result>` · `discovery <fact>` · `insight <observation> → <spec-section>` · `verified <tool>@<version> <summary>` · `ver <cmd> → pass|fail exit=<N>` · `BLOCKED <cause>` · `DONE`. A `[x]` line with an unreplaced `<…>` placeholder is fabricated (BLOCKER).\n- **Post-task hook:** after a Round closes the orchestrator runs audit; until PASS the round is closed-but-unverified and dependents are blocked.\n\n## Cross-Scope DAG\nCross-scope edges + integration tickets only; intra-scope edges live in each scope index. Order follows the Portal Scope Graph.\n```mermaid\ngraph TD\n backend --> infra-base\n web --> backend\n```\n\n## Scope Tracker\n| Scope | Type | Index | Tasks | Done |\n|---|---|---|---|---|\n| infra-base | infrastructure | [3-tasks](./infra-base/infra-base.3-tasks.md) | 6 | 0/6 |\n| backend | product | [3-tasks](./backend/backend.3-tasks.md) | 12 | 0/12 |\n\n## Decision Log (project task level)\n[D-NNN when the operator made non-default cross-scope choices.]\n", Os = [
1964
+ ], Ts = "# Project Tasks\n\n## Entry Points\n- [Specs Portal](./README.md) — Scope Graph + all scope specs.\n- Tickets execute ONLY via the `/sdd-execute` flow (one ticket) or its batch form; the orchestrator dispatches phase-workers then audit — the operator does not invoke audit by hand.\n\n## Project-Wide Conventions (declared once, inherited)\n- **File-header:** owned by the coding rule (`@file` / `@consumers` / `@tasks`), enforced by `sdd-verify`.\n- **Baseline Completion Rule:** a Round cannot go `[x] DONE` until — every phase `[x]`; every BDD scenario mapped to a test or `Deferred Test Ownership`; verification commands run with exit recorded; every entity beyond the Inventory logged `intro …`; a Handoff line closes each phase.\n- **Execution-Log token vocabulary:** `intro <Entity> ← <reason>` · `decision <key>=<value> ← <reason>` · `tried <approach> → <result>` · `discovery <fact>` · `insight <observation> → <spec-section>` · `verified <tool>@<version> <summary>` · `ver <cmd> → pass|fail exit=<N>` · `BLOCKED <cause>` · `DONE`. A `[x]` line with an unreplaced `<…>` placeholder is fabricated (BLOCKER).\n- **Post-task hook:** after a Round closes the orchestrator runs audit; until PASS the round is closed-but-unverified and dependents are blocked.\n\n## Cross-Scope DAG\nCross-scope edges + integration tickets only; intra-scope edges live in each scope index. Order follows the Portal Scope Graph.\n```mermaid\ngraph TD\n backend --> infra-base\n web --> backend\n```\n\n## Scope Tracker\n| Scope | Type | Index | Tasks | Done |\n|---|---|---|---|---|\n| infra-base | infrastructure | [3-tasks](./infra-base/infra-base.3-tasks.md) | 6 | 0/6 |\n| backend | product | [3-tasks](./backend/backend.3-tasks.md) | 12 | 0/12 |\n\n## Decision Log (project task level)\n[D-NNN when the operator made non-default cross-scope choices.]\n", _s = [
1965
1965
  {
1966
1966
  name: "ENTRY_POINTS",
1967
1967
  required: !0,
@@ -1997,7 +1997,7 @@ graph TD
1997
1997
  fold: !1,
1998
1998
  fill: "Cross-scope decomposition/planning decisions, D-NNN, ADR-compact."
1999
1999
  }
2000
- ], Ts = `# <project-name>
2000
+ ], Ns = `# <project-name>
2001
2001
 
2002
2002
  ## Vision
2003
2003
  <Одно предложение. Опускается для infrastructure-only проектов.>
@@ -2022,7 +2022,7 @@ graph TD
2022
2022
  | [\`api\`](./api/api.spec.md) | interface | 🚧 | REST API v1 |
2023
2023
  | [\`backend\`](./backend/backend.spec.md) | product | ✅ | Node.js IMAP-сервис |
2024
2024
  | [\`web\`](./web/web.spec.md) | product | 🚧 | React SPA |
2025
- `, _s = [
2025
+ `, Cs = [
2026
2026
  {
2027
2027
  name: "VISION",
2028
2028
  required: !1,
@@ -2044,81 +2044,81 @@ graph TD
2044
2044
  fold: !1,
2045
2045
  fill: "Scope/Type/Spec-status/Description table — one row per scope, linking to its spec.md."
2046
2046
  }
2047
- ], pe = {
2047
+ ], Ee = {
2048
2048
  product: {
2049
2049
  kind: "product",
2050
- skeleton: ns,
2051
- sections: os,
2050
+ skeleton: rs,
2051
+ sections: is,
2052
2052
  pathPattern: "specs/<scope>/<scope>.spec.md"
2053
2053
  },
2054
2054
  library: {
2055
2055
  kind: "library",
2056
- skeleton: rs,
2057
- sections: is,
2056
+ skeleton: as,
2057
+ sections: cs,
2058
2058
  pathPattern: "specs/<scope>/<scope>.spec.md"
2059
2059
  },
2060
2060
  infrastructure: {
2061
2061
  kind: "infrastructure",
2062
- skeleton: as,
2063
- sections: cs,
2062
+ skeleton: ls,
2063
+ sections: ds,
2064
2064
  pathPattern: "specs/<scope>/<scope>.spec.md"
2065
2065
  },
2066
2066
  interface: {
2067
2067
  kind: "interface",
2068
- skeleton: ls,
2069
- sections: ds,
2068
+ skeleton: us,
2069
+ sections: fs,
2070
2070
  pathPattern: "specs/<scope>/<scope>.spec.md"
2071
2071
  },
2072
2072
  module: {
2073
2073
  kind: "module",
2074
- skeleton: us,
2075
- sections: fs,
2074
+ skeleton: ps,
2075
+ sections: ms,
2076
2076
  pathPattern: "specs/<scope>/<module>/<module>.spec.md"
2077
2077
  },
2078
2078
  task: {
2079
2079
  kind: "task",
2080
- skeleton: ps,
2081
- sections: ms,
2080
+ skeleton: Es,
2081
+ sections: hs,
2082
2082
  pathPattern: "specs/<scope>/<module>/<module>.task.<ACR>-<slug>.md"
2083
2083
  },
2084
2084
  "module-index": {
2085
2085
  kind: "module-index",
2086
- skeleton: Es,
2087
- sections: hs,
2086
+ skeleton: Ss,
2087
+ sections: gs,
2088
2088
  pathPattern: "specs/<scope>/<module...>/<module>.3-tasks.md"
2089
2089
  },
2090
2090
  "scope-index": {
2091
2091
  kind: "scope-index",
2092
- skeleton: Ss,
2093
- sections: gs,
2092
+ skeleton: Is,
2093
+ sections: Os,
2094
2094
  pathPattern: "specs/<scope>/<scope>.3-tasks.md"
2095
2095
  },
2096
2096
  "project-index": {
2097
2097
  kind: "project-index",
2098
- skeleton: Is,
2099
- sections: Os,
2098
+ skeleton: Ts,
2099
+ sections: _s,
2100
2100
  pathPattern: "specs/3-tasks.md"
2101
2101
  },
2102
2102
  portal: {
2103
2103
  kind: "portal",
2104
- skeleton: Ts,
2105
- sections: _s,
2104
+ skeleton: Ns,
2105
+ sections: Cs,
2106
2106
  pathPattern: "specs/README.md"
2107
2107
  }
2108
- }, Io = Object.keys(pe);
2109
- function Ye(e) {
2110
- return pe[e].sections.filter((t) => t.loadBearing).map((t) => t.name);
2108
+ }, _o = Object.keys(Ee);
2109
+ function qe(e) {
2110
+ return Ee[e].sections.filter((t) => t.loadBearing).map((t) => t.name);
2111
2111
  }
2112
- function Ns(e) {
2113
- return pe[e].sections.filter((t) => t.fold).map((t) => t.name);
2112
+ function Ds(e) {
2113
+ return Ee[e].sections.filter((t) => t.fold).map((t) => t.name);
2114
2114
  }
2115
- function Cs(e) {
2116
- return e.provider === "github" ? new Nt({ baseUrl: "https://api.github.com", token: e.token }) : new Ct({ baseUrl: `https://${e.host}/api/v4`, token: e.token });
2115
+ function As(e) {
2116
+ return e.provider === "github" ? new Dt({ baseUrl: "https://api.github.com", token: e.token }) : new At({ baseUrl: `https://${e.host}/api/v4`, token: e.token });
2117
2117
  }
2118
- const Oo = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2118
+ const No = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2119
2119
  __proto__: null,
2120
- createVcsClient: Cs
2121
- }, Symbol.toStringTag, { value: "Module" })), He = "(?<!\\p{L})", Ds = "(?!\\p{L})", L = (e) => new RegExp(`${He}${e}${Ds}`, "iu"), T = (e) => new RegExp(`${He}${e}\\p{L}*`, "iu"), As = [
2120
+ createVcsClient: As
2121
+ }, Symbol.toStringTag, { value: "Module" })), We = "(?<!\\p{L})", ys = "(?!\\p{L})", L = (e) => new RegExp(`${We}${e}${ys}`, "iu"), T = (e) => new RegExp(`${We}${e}\\p{L}*`, "iu"), Rs = [
2122
2122
  { re: L("проз[аыуе]"), why: "книжное", use: "текст" },
2123
2123
  { re: L("новь[её]"), why: "сленг", use: "новое" },
2124
2124
  { re: T("докрут"), why: "сленг", use: "доработать" },
@@ -2149,20 +2149,20 @@ const Oo = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2149
2149
  { re: T("блокер"), why: "сленг (blocker)", use: "блокирующий дефект" },
2150
2150
  { re: T("терминальн"), why: "калька (terminal)", use: "окончательный / конечный" }
2151
2151
  ];
2152
- function To(e) {
2152
+ function Co(e) {
2153
2153
  const t = [], s = e.split(`
2154
- `), o = e.replace(/<!--[\s\S]*?-->/g, (i) => i.replace(/[^\n]/g, " ")).split(`
2154
+ `), r = e.replace(/<!--[\s\S]*?-->/g, (i) => i.replace(/[^\n]/g, " ")).split(`
2155
2155
  `);
2156
- let r = !1;
2157
- for (let i = 0; i < o.length; i++) {
2158
- const a = o[i];
2156
+ let o = !1;
2157
+ for (let i = 0; i < r.length; i++) {
2158
+ const a = r[i];
2159
2159
  if (a.trim().startsWith("```")) {
2160
- r = !r;
2160
+ o = !o;
2161
2161
  continue;
2162
2162
  }
2163
- if (r || s[i].includes("<!-- stop-ok")) continue;
2163
+ if (o || s[i].includes("<!-- stop-ok")) continue;
2164
2164
  const l = a.replace(/`[^`]*`/g, (f) => " ".repeat(f.length));
2165
- for (const f of As) {
2165
+ for (const f of Rs) {
2166
2166
  const d = new RegExp(
2167
2167
  f.re.source,
2168
2168
  f.re.flags.includes("g") ? f.re.flags : f.re.flags + "g"
@@ -2174,25 +2174,25 @@ function To(e) {
2174
2174
  }
2175
2175
  return t;
2176
2176
  }
2177
- const ys = /^[A-Z][A-Z0-9_]*$/;
2178
- function qe(e) {
2179
- return ys.test(e);
2177
+ const ks = /^[A-Z][A-Z0-9_]*$/;
2178
+ function Ke(e) {
2179
+ return ks.test(e);
2180
2180
  }
2181
2181
  function g(e, t) {
2182
- if (!qe(t)) return { status: "invalid_name" };
2183
- const s = `<!--SECTION:${t}-->`, n = `<!--/SECTION:${t}-->`, o = e.split(`
2182
+ if (!Ke(t)) return { status: "invalid_name" };
2183
+ const s = `<!--SECTION:${t}-->`, n = `<!--/SECTION:${t}-->`, r = e.split(`
2184
2184
  `);
2185
- let r = 0, i = 0;
2186
- for (const f of o) {
2185
+ let o = 0, i = 0;
2186
+ for (const f of r) {
2187
2187
  const d = f.trim();
2188
- d === s ? r++ : d === n && i++;
2188
+ d === s ? o++ : d === n && i++;
2189
2189
  }
2190
- if (r === 0 && i === 0) return { status: "not_found" };
2191
- if (r !== i) return { status: "unbalanced", startCount: r, endCount: i };
2192
- if (r > 1) return { status: "duplicated", count: r };
2190
+ if (o === 0 && i === 0) return { status: "not_found" };
2191
+ if (o !== i) return { status: "unbalanced", startCount: o, endCount: i };
2192
+ if (o > 1) return { status: "duplicated", count: o };
2193
2193
  const a = [];
2194
2194
  let c = !1;
2195
- for (const f of o) {
2195
+ for (const f of r) {
2196
2196
  const d = f.trim();
2197
2197
  if (d === s) {
2198
2198
  c = !0;
@@ -2208,115 +2208,115 @@ function g(e, t) {
2208
2208
  `);
2209
2209
  return l.trim() === "" ? { status: "empty" } : { status: "ok", content: l };
2210
2210
  }
2211
- function _o(e, t) {
2212
- if (!qe(t)) return null;
2213
- const s = `<!--SECTION:${t}-->`, n = `<!--/SECTION:${t}-->`, o = e.split(`
2211
+ function Do(e, t) {
2212
+ if (!Ke(t)) return null;
2213
+ const s = `<!--SECTION:${t}-->`, n = `<!--/SECTION:${t}-->`, r = e.split(`
2214
2214
  `);
2215
- let r = -1, i = -1, a = 0, c = 0;
2216
- return o.forEach((l, f) => {
2215
+ let o = -1, i = -1, a = 0, c = 0;
2216
+ return r.forEach((l, f) => {
2217
2217
  const d = l.trim();
2218
- d === s ? (a++, r === -1 && (r = f)) : d === n && (c++, i = f);
2219
- }), a !== 1 || c !== 1 || i < r ? null : { openLine: r, closeLine: i };
2218
+ d === s ? (a++, o === -1 && (o = f)) : d === n && (c++, i = f);
2219
+ }), a !== 1 || c !== 1 || i < o ? null : { openLine: o, closeLine: i };
2220
2220
  }
2221
- function No(e) {
2221
+ function Ao(e) {
2222
2222
  const t = g(e, "ENTITY_INVENTORY");
2223
2223
  return t.status !== "ok" ? [] : t.content.split(`
2224
2224
  `).map((n) => n.trim()).filter((n) => n.startsWith("|") && !/^\|[\s:|-]+$/.test(n)).slice(1).map((n) => (n.split("|")[1] ?? "").replace(/`/g, "").trim()).filter(Boolean);
2225
2225
  }
2226
- function Rs(e, t) {
2226
+ function vs(e, t) {
2227
2227
  try {
2228
2228
  const s = h(e, "package.json");
2229
- if (!R(s) || JSON.parse(D(s, "utf-8")).name !== "gennady") return null;
2230
- const o = h(e, t);
2231
- return R(o) ? o : null;
2229
+ if (!R(s) || JSON.parse(C(s, "utf-8")).name !== "gennady") return null;
2230
+ const r = h(e, t);
2231
+ return R(r) ? r : null;
2232
2232
  } catch {
2233
2233
  return null;
2234
2234
  }
2235
2235
  }
2236
- function Co(e, t) {
2236
+ function yo(e, t) {
2237
2237
  try {
2238
2238
  const n = h(e, "node_modules", "gennady", t);
2239
2239
  if (R(n)) return n;
2240
2240
  } catch {
2241
2241
  }
2242
2242
  try {
2243
- const n = import.meta.resolve("gennady"), r = fe(n).replace(/[/\\]dist[/\\].*$/, ""), i = h(r, t);
2243
+ const n = import.meta.resolve("gennady"), o = me(n).replace(/[/\\]dist[/\\].*$/, ""), i = h(o, t);
2244
2244
  if (R(i)) return i;
2245
2245
  } catch {
2246
2246
  }
2247
- const s = Rs(e, t);
2247
+ const s = vs(e, t);
2248
2248
  return s || null;
2249
2249
  }
2250
- function Do(e, t) {
2250
+ function Ro(e, t) {
2251
2251
  return !Buffer.isBuffer(e) || !Buffer.isBuffer(t) ? !0 : Buffer.compare(e, t) !== 0;
2252
2252
  }
2253
- function Ao(e, t) {
2253
+ function ko(e, t) {
2254
2254
  let s = e;
2255
2255
  for (const n of t)
2256
2256
  s = s.replace(n.from, n.to);
2257
2257
  return s;
2258
2258
  }
2259
- const We = {
2259
+ const Xe = {
2260
2260
  from: /npx\s+tsx\s+~\/Developer\/gennady\/cli\/gennady\.ts\b/g,
2261
2261
  to: "npx gennady"
2262
- }, Ke = {
2262
+ }, Ze = {
2263
2263
  from: /npx tsx ~\/Developer\/gennady\/cli[ \t]+/g,
2264
2264
  to: "npx gennady "
2265
- }, Xe = {
2265
+ }, ze = {
2266
2266
  from: /~\/Developer\/gennady\/cli\/gennady\.ts/g,
2267
2267
  to: "npx gennady"
2268
- }, ks = {
2268
+ }, ws = {
2269
2269
  from: /~\/Developer\/gennady\/ai\/skills\//g,
2270
2270
  to: ".claude/skills/"
2271
- }, Ze = {
2271
+ }, Qe = {
2272
2272
  from: /~\/Developer\/gennady\/ai\/directives\//g,
2273
2273
  to: "ai/directives/"
2274
- }, ze = {
2274
+ }, Je = {
2275
2275
  from: /\/Users\/k\.lebedev\/Developer\/gennady\/ai\//g,
2276
2276
  to: "ai/"
2277
- }, Qe = {
2277
+ }, et = {
2278
2278
  from: /\/Users\/k\.lebedev\/Developer\/gennady\/cli\/gennady\.ts/g,
2279
2279
  to: "npx gennady"
2280
- }, Je = {
2280
+ }, tt = {
2281
2281
  from: /\$HOME\/Developer\/gennady\/cli\/gennady\.ts\b/g,
2282
2282
  to: "~/Developer/gennady/cli/gennady.ts"
2283
- }, yo = [
2284
- We,
2285
- Ke,
2283
+ }, vo = [
2286
2284
  Xe,
2287
2285
  Ze,
2288
2286
  ze,
2289
2287
  Qe,
2290
- Je
2291
- ], Ro = [
2292
- We,
2293
- Ke,
2288
+ Je,
2289
+ et,
2290
+ tt
2291
+ ], wo = [
2294
2292
  Xe,
2295
- ks,
2296
2293
  Ze,
2297
2294
  ze,
2295
+ ws,
2298
2296
  Qe,
2299
- Je
2300
- ], vs = "+", ws = "~", Ps = "-", Ls = "=", bs = "(unchanged)", Ms = "(would add)", xs = "(would update)", $s = "(would delete)", Bs = "(unchanged, skip)";
2301
- function ko(e, t = {}) {
2297
+ Je,
2298
+ et,
2299
+ tt
2300
+ ], Ps = "+", Ls = "~", bs = "-", Ms = "=", $s = "(unchanged)", xs = "(would add)", Bs = "(would update)", Us = "(would delete)", Fs = "(unchanged, skip)";
2301
+ function Po(e, t = {}) {
2302
2302
  const s = [];
2303
2303
  for (const a of e) {
2304
2304
  const { relativePath: c, status: l } = a;
2305
2305
  let f, d;
2306
- l === "added" ? (f = vs, d = t.dryRun ? Ms : "") : l === "updated" ? (f = ws, d = t.dryRun ? xs : "") : l === "deleted" ? (f = Ps, d = t.dryRun ? $s : "") : (f = Ls, d = t.dryRun ? Bs : bs);
2306
+ l === "added" ? (f = Ps, d = t.dryRun ? xs : "") : l === "updated" ? (f = Ls, d = t.dryRun ? Bs : "") : l === "deleted" ? (f = bs, d = t.dryRun ? Us : "") : (f = Ms, d = t.dryRun ? Fs : $s);
2307
2307
  const u = c.padEnd(64);
2308
2308
  d ? s.push(` ${f} ${u} ${d}`) : s.push(` ${f} ${c}`);
2309
2309
  }
2310
- const n = e.filter((a) => a.status === "added").length, o = e.filter((a) => a.status === "updated").length, r = e.filter((a) => a.status === "unchanged").length, i = e.filter((a) => a.status === "deleted").length;
2310
+ const n = e.filter((a) => a.status === "added").length, r = e.filter((a) => a.status === "updated").length, o = e.filter((a) => a.status === "unchanged").length, i = e.filter((a) => a.status === "deleted").length;
2311
2311
  if (t.dryRun)
2312
2312
  s.push("Dry-run: no files written.");
2313
2313
  else {
2314
- let a = `Synced: ${n} added, ${o} updated, ${r} skipped (unchanged)`;
2314
+ let a = `Synced: ${n} added, ${r} updated, ${o} skipped (unchanged)`;
2315
2315
  i > 0 && (a += `, ${i} deleted`), s.push(a);
2316
2316
  }
2317
2317
  return s;
2318
2318
  }
2319
- const Us = /[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~]))/g, Re = [
2319
+ const Gs = /[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~]))/g, ve = [
2320
2320
  /^\s*(✖|❌|⚠|🛑|× |✗ |FAIL |●|▶)/,
2321
2321
  /:\d+:\d+:\s+(error|warning)/i,
2322
2322
  /^\s+at\s+/,
@@ -2332,58 +2332,58 @@ const Us = /[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d/#&.:=?%@
2332
2332
  /^TAP version/i,
2333
2333
  /^\s*not\s+ok\s+\d+/i
2334
2334
  ];
2335
- function vo(e) {
2336
- const t = e.replace(Us, ""), s = t.split(`
2335
+ function Lo(e) {
2336
+ const t = e.replace(Gs, ""), s = t.split(`
2337
2337
  `).filter((n) => {
2338
- const o = n.trim();
2339
- return !o || o.length > 200 && !/:\d+/.test(o) && !Re.some((r) => r.test(o)) ? !1 : Re.some((r) => r.test(o));
2338
+ const r = n.trim();
2339
+ return !r || r.length > 200 && !/:\d+/.test(r) && !ve.some((o) => o.test(r)) ? !1 : ve.some((o) => o.test(r));
2340
2340
  });
2341
2341
  return s.length === 0 ? t.slice(0, 2e3) + `
2342
2342
  ... [no error lines]` : s.join(`
2343
2343
  `);
2344
2344
  }
2345
- const Gs = ["typecheck", "test", "test:coverage", "lint", "format"];
2346
- function Fs(e) {
2345
+ const Vs = ["typecheck", "test", "test:coverage", "lint", "format"];
2346
+ function js(e) {
2347
2347
  const t = e.lint;
2348
2348
  if (t === void 0) return !1;
2349
2349
  const s = /* @__PURE__ */ new Set(), n = [t];
2350
2350
  for (; n.length > 0; ) {
2351
- const o = n.shift();
2352
- if (o !== void 0) {
2353
- if (/\bgennady\b/.test(o)) return !0;
2354
- for (const r of o.matchAll(/npm run ([A-Za-z0-9:_-]+)/g)) {
2355
- const i = r[1];
2351
+ const r = n.shift();
2352
+ if (r !== void 0) {
2353
+ if (/\bgennady\b/.test(r)) return !0;
2354
+ for (const o of r.matchAll(/npm run ([A-Za-z0-9:_-]+)/g)) {
2355
+ const i = o[1];
2356
2356
  i && !s.has(i) && e[i] !== void 0 && (s.add(i), n.push(e[i]));
2357
2357
  }
2358
2358
  }
2359
2359
  }
2360
2360
  return !1;
2361
2361
  }
2362
- function wo(e) {
2363
- const { packageJsonPresent: t, scripts: s, gennadyAvailable: n } = e, o = Gs.map((c) => ({
2362
+ function bo(e) {
2363
+ const { packageJsonPresent: t, scripts: s, gennadyAvailable: n } = e, r = Vs.map((c) => ({
2364
2364
  name: c,
2365
2365
  present: s[c] !== void 0
2366
- })), r = Fs(s), i = [];
2367
- t || i.push("package.json"), i.push(...o.filter((c) => !c.present).map((c) => c.name)), s.lint !== void 0 && !r && i.push("lint→gennady"), n || i.push("gennady (not installed)");
2368
- const a = t && o.every((c) => c.present) && r && n;
2369
- return { packageJsonPresent: t, required: o, lintHasGennady: r, gennadyAvailable: n, ready: a, missing: i };
2366
+ })), o = js(s), i = [];
2367
+ t || i.push("package.json"), i.push(...r.filter((c) => !c.present).map((c) => c.name)), s.lint !== void 0 && !o && i.push("lint→gennady"), n || i.push("gennady (not installed)");
2368
+ const a = t && r.every((c) => c.present) && o && n;
2369
+ return { packageJsonPresent: t, required: r, lintHasGennady: o, gennadyAvailable: n, ready: a, missing: i };
2370
2370
  }
2371
- function Vs(e) {
2371
+ function Ys(e) {
2372
2372
  return e.includes("✅") ? "done" : e.includes("🚧") ? "wip" : "unknown";
2373
2373
  }
2374
- function Po(e) {
2374
+ function Mo(e) {
2375
2375
  const t = e.split(`
2376
2376
  `);
2377
2377
  let s = !1;
2378
2378
  const n = [];
2379
- for (const o of t) {
2380
- const r = o.trim();
2381
- if (/^#{1,6}\s/.test(r)) {
2382
- s = /^#{1,6}\s+Scopes\s*$/.test(r);
2379
+ for (const r of t) {
2380
+ const o = r.trim();
2381
+ if (/^#{1,6}\s/.test(o)) {
2382
+ s = /^#{1,6}\s+Scopes\s*$/.test(o);
2383
2383
  continue;
2384
2384
  }
2385
- if (!s || !r.startsWith("|")) continue;
2386
- const i = r.replace(/^\|/, "").replace(/\|$/, "").split("|").map((p) => p.trim());
2385
+ if (!s || !o.startsWith("|")) continue;
2386
+ const i = o.replace(/^\|/, "").replace(/\|$/, "").split("|").map((p) => p.trim());
2387
2387
  if (i.length < 3) continue;
2388
2388
  const [a, c, l, f] = i;
2389
2389
  if (a === void 0 || c === void 0 || l === void 0) continue;
@@ -2393,25 +2393,25 @@ function Po(e) {
2393
2393
  n.push({
2394
2394
  name: d[1],
2395
2395
  type: c,
2396
- status: Vs(l),
2396
+ status: Ys(l),
2397
2397
  description: f?.trim() ?? "",
2398
2398
  specPath: u?.[1] ?? null
2399
2399
  });
2400
2400
  }
2401
2401
  return n;
2402
2402
  }
2403
- function js(e) {
2403
+ function Hs(e) {
2404
2404
  const t = [], s = /([A-Za-z0-9_-]+)(?:\[[^\]]*\])?\s*-->(?:\s*\|[^|]*\|)?\s*([A-Za-z0-9_-]+)/;
2405
2405
  for (const n of e.split(`
2406
2406
  `)) {
2407
- const o = n.trim();
2408
- if (!o.includes("-->")) continue;
2409
- const r = s.exec(o);
2410
- r?.[1] && r[2] && t.push({ from: r[1], to: r[2] });
2407
+ const r = n.trim();
2408
+ if (!r.includes("-->")) continue;
2409
+ const o = s.exec(r);
2410
+ o?.[1] && o[2] && t.push({ from: o[1], to: o[2] });
2411
2411
  }
2412
2412
  return t;
2413
2413
  }
2414
- const Ys = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", "coverage", ".next", "out"]), Hs = /\.(js|jsx|ts|tsx)$/, qs = [
2414
+ const qs = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", "coverage", ".next", "out"]), Ws = /\.(js|jsx|ts|tsx)$/, Ks = [
2415
2415
  "tsconfig.json",
2416
2416
  "eslint.config.js",
2417
2417
  "eslint.config.mjs",
@@ -2431,29 +2431,29 @@ const Ys = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", "co
2431
2431
  "jest.config.js",
2432
2432
  "jest.config.ts"
2433
2433
  ];
2434
- function et(e, t, s) {
2434
+ function st(e, t, s) {
2435
2435
  let n;
2436
2436
  try {
2437
- n = $(e, { withFileTypes: !0 });
2437
+ n = B(e, { withFileTypes: !0 });
2438
2438
  } catch {
2439
2439
  return;
2440
2440
  }
2441
- for (const o of n) {
2442
- const r = o.name;
2443
- if (o.isDirectory()) {
2444
- if (Ys.has(r) || r.startsWith(".")) continue;
2445
- et(h(e, r), t, s);
2446
- } else if (Hs.test(r)) {
2441
+ for (const r of n) {
2442
+ const o = r.name;
2443
+ if (r.isDirectory()) {
2444
+ if (qs.has(o) || o.startsWith(".")) continue;
2445
+ st(h(e, o), t, s);
2446
+ } else if (Ws.test(o)) {
2447
2447
  s.count++;
2448
- const i = h(e, r).slice(t.length + 1);
2448
+ const i = h(e, o).slice(t.length + 1);
2449
2449
  s.dirs.add(i.includes("/") ? i.slice(0, i.indexOf("/")) : ".");
2450
2450
  }
2451
2451
  }
2452
2452
  }
2453
- function Lo(e) {
2453
+ function $o(e) {
2454
2454
  const t = { count: 0, dirs: /* @__PURE__ */ new Set() };
2455
- et(e, e, t);
2456
- const s = qs.filter((n) => R(h(e, n)));
2455
+ st(e, e, t);
2456
+ const s = Ks.filter((n) => R(h(e, n)));
2457
2457
  return {
2458
2458
  codePresent: t.count > 0,
2459
2459
  codeFileCount: t.count,
@@ -2462,160 +2462,309 @@ function Lo(e) {
2462
2462
  configFiles: s
2463
2463
  };
2464
2464
  }
2465
- function Ws(e) {
2465
+ function Xs(e) {
2466
2466
  try {
2467
- return oe(h(e, "tasks")).isDirectory() ? "v1" : "v2";
2467
+ return ie(h(e, "tasks")).isDirectory() ? "v1" : "v2";
2468
2468
  } catch {
2469
2469
  return "v2";
2470
2470
  }
2471
2471
  }
2472
- function bo(e, t) {
2473
- if (Ws(e) === "v2") return "v2";
2472
+ function xo(e, t) {
2473
+ if (Xs(e) === "v2") return "v2";
2474
2474
  try {
2475
- if (oe(h(e, "tasks", t)).isDirectory()) return "v1";
2475
+ if (ie(h(e, "tasks", t)).isDirectory()) return "v1";
2476
2476
  } catch {
2477
2477
  }
2478
2478
  try {
2479
- return oe(h(e, "specs", t, `${t}.3-tasks.md`)).isFile() ? "v2" : "v1";
2479
+ return ie(h(e, "specs", t, `${t}.3-tasks.md`)).isFile() ? "v2" : "v1";
2480
2480
  } catch {
2481
2481
  return "v1";
2482
2482
  }
2483
2483
  }
2484
- function Mo(e) {
2484
+ const Zs = /* @__PURE__ */ new Set(["node_modules", ".git"]);
2485
+ function Bo(e) {
2486
+ let t = 0;
2487
+ function s(n) {
2488
+ let r;
2489
+ try {
2490
+ r = B(n, { withFileTypes: !0 });
2491
+ } catch {
2492
+ return;
2493
+ }
2494
+ for (const o of r)
2495
+ if (o.isDirectory()) {
2496
+ if (Zs.has(o.name)) continue;
2497
+ s(h(n, o.name));
2498
+ } else if (o.name.endsWith(".spec.md"))
2499
+ try {
2500
+ C(h(n, o.name), "utf-8").includes("<!--SECTION:MODULE_VISION-->") && t++;
2501
+ } catch {
2502
+ }
2503
+ }
2504
+ return s(e), t;
2505
+ }
2506
+ function nt(e) {
2507
+ const t = e.match(/\*{0,2}Task-ID:\*{0,2}\s*`?([A-Za-z0-9][A-Za-z0-9_-]*)`?/), s = e.match(/\*{0,2}Status:\*{0,2}\s*(\[.\]\s*[A-Z_]+)/);
2508
+ return {
2509
+ taskId: t?.[1] ?? null,
2510
+ status: s?.[1] ?? null
2511
+ };
2512
+ }
2513
+ function K(e) {
2514
+ return e.replace(/`/g, "").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").trim();
2515
+ }
2516
+ function U(e) {
2517
+ return e.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((t) => t.trim());
2518
+ }
2519
+ function Uo(e, t, s) {
2520
+ const n = e.split(`
2521
+ `), r = ot(n);
2522
+ if (!r) return { ok: !1, reason: "no_table" };
2523
+ const { headerIdx: o, idCol: i, statusCol: a } = r;
2524
+ for (let c = o + 1; c < n.length; c++) {
2525
+ const l = n[c];
2526
+ if (l === void 0 || !l.trimStart().startsWith("|")) break;
2527
+ const f = U(l);
2528
+ if (/^\|?\s*-+\s*\|/.test(l) || K(f[i] ?? "") !== t) continue;
2529
+ const d = l.split("|"), u = a + 1;
2530
+ if (d[u] === void 0) return { ok: !1, reason: "no_table" };
2531
+ const p = d[u];
2532
+ return d[u] = ` ${s} `, d[u] === p ? { ok: !0, text: e, changed: !1 } : (n[c] = d.join("|"), { ok: !0, text: n.join(`
2533
+ `), changed: !0 });
2534
+ }
2535
+ return { ok: !1, reason: "task_not_found" };
2536
+ }
2537
+ function ot(e) {
2538
+ for (let t = 0; t < e.length; t++) {
2539
+ const s = e[t];
2540
+ if (s === void 0 || !s.trimStart().startsWith("|")) continue;
2541
+ const n = U(s).map((i) => i.toLowerCase()), r = n.indexOf("task-id"), o = n.indexOf("status");
2542
+ if (r !== -1 && o !== -1) return { headerIdx: t, idCol: r, statusCol: o };
2543
+ }
2544
+ return null;
2545
+ }
2546
+ function Fo(e) {
2547
+ const t = e.split(`
2548
+ `), s = ot(t);
2549
+ if (!s) return [];
2550
+ const n = [];
2551
+ for (let r = s.headerIdx + 1; r < t.length; r++) {
2552
+ const o = t[r];
2553
+ if (o === void 0 || !o.trimStart().startsWith("|")) break;
2554
+ if (/^\|?\s*-+\s*\|/.test(o)) continue;
2555
+ const i = U(o), a = K(i[s.idCol] ?? "");
2556
+ a && n.push({ taskId: a, status: (i[s.statusCol] ?? "").trim() });
2557
+ }
2558
+ return n;
2559
+ }
2560
+ function zs(e) {
2561
+ return /^\[x\]/i.test(e.trim());
2562
+ }
2563
+ function rt(e) {
2564
+ for (let t = 0; t < e.length; t++) {
2565
+ const s = e[t];
2566
+ if (s === void 0 || !s.trimStart().startsWith("|")) continue;
2567
+ const n = U(s).map((a) => a.toLowerCase()), r = n.indexOf("index"), o = n.indexOf("tasks"), i = n.indexOf("done") !== -1 ? n.indexOf("done") : n.indexOf("progress");
2568
+ if (r !== -1 && o !== -1 && i !== -1)
2569
+ return { headerIdx: t, indexCol: r, tasksCol: o, doneCol: i };
2570
+ }
2571
+ return null;
2572
+ }
2573
+ function Qs(e) {
2574
+ return e.match(/\[[^\]]*\]\(([^)]+)\)/)?.[1] ?? null;
2575
+ }
2576
+ function Go(e, t) {
2577
+ const s = e.split(`
2578
+ `), n = rt(s);
2579
+ if (!n) return { text: e, updated: [] };
2580
+ const r = [];
2581
+ for (let o = n.headerIdx + 1; o < s.length; o++) {
2582
+ const i = s[o];
2583
+ if (i === void 0 || !i.trimStart().startsWith("|")) break;
2584
+ if (/^\|?\s*-+\s*\|/.test(i)) continue;
2585
+ const a = U(i), c = Qs(a[n.indexCol] ?? "");
2586
+ if (!c) continue;
2587
+ const l = t(c);
2588
+ if (!l) continue;
2589
+ const f = l.filter((_) => zs(_.status)).length, d = l.length, u = i.split("|"), p = n.tasksCol + 1, m = n.doneCol + 1;
2590
+ if (u[p] === void 0 || u[m] === void 0) continue;
2591
+ const E = ` ${d} `, S = ` ${f}/${d} `;
2592
+ u[p] === E && u[m] === S || (u[p] = E, u[m] = S, s[o] = u.join("|"), r.push(c));
2593
+ }
2594
+ return { text: s.join(`
2595
+ `), updated: r };
2596
+ }
2597
+ function Vo(e) {
2598
+ const t = e.split(`
2599
+ `), s = rt(t);
2600
+ if (!s) return null;
2601
+ let n = 0, r = 0;
2602
+ for (let o = s.headerIdx + 1; o < t.length; o++) {
2603
+ const i = t[o];
2604
+ if (i === void 0 || !i.trimStart().startsWith("|")) break;
2605
+ if (/^\|?\s*-+\s*\|/.test(i)) continue;
2606
+ const a = U(i), c = Number.parseInt(K(a[s.tasksCol] ?? ""), 10), l = K(a[s.doneCol] ?? "").match(/^(\d+)/);
2607
+ Number.isFinite(c) && (n += c), l?.[1] && (r += Number.parseInt(l[1], 10));
2608
+ }
2609
+ return { totalTasks: n, totalDone: r };
2610
+ }
2611
+ const Js = 17;
2612
+ function M(e) {
2613
+ return e ? "✅" : "⬜";
2614
+ }
2615
+ function jo(e) {
2616
+ const t = e.portalPresent, s = e.scopesTotal > 0 && e.scopesApproved === e.scopesTotal, n = e.moduleSpecCount > 0, r = e.packageJsonPresent && e.gates.typecheck && e.gates.test && e.gates.lint, o = e.tasksTotal !== null && e.tasksTotal > 0 && e.tasksDone !== null && e.tasksDone === e.tasksTotal, i = t ? `specs/README.md — скоупов в графе: ${e.scopesTotal}` : "specs/README.md — отсутствует", a = e.scopesTotal === 0 ? "нет ни одной" : `approved: ${e.scopesApproved} из ${e.scopesTotal}`, c = e.moduleSpecCount > 0 ? `модульных спек: ${e.moduleSpecCount}` : "—", l = e.packageJsonPresent ? `гейты: type-check ${M(e.gates.typecheck)} · test ${M(e.gates.test)} · lint ${M(e.gates.lint)}` : "не настроена", f = e.tasksTotal === null ? "tasks/ отсутствует" : `тикетов: ${e.tasksTotal} · done: ${e.tasksDone ?? 0}`, d = e.portalPresent && e.projectName ? e.projectName : "«пустой репозиторий»";
2617
+ let u;
2618
+ t ? s ? n ? r ? o ? u = "всё закрыто — следующий цикл /sdd-execute" : u = e.tasksTotal === null ? "разбить спеки на задачи — /sdd-scaffold" : "выполнить следующую задачу — /sdd-execute" : u = "настроить инфраструктуру (гейты) перед scaffold" : u = "разбить скоуп на модули — /sdd" : u = "написать и approve скоуп-спеку — /sdd" : u = "создать проект — /sdd";
2619
+ const p = (m) => m.padEnd(Js);
2620
+ return [
2621
+ `🏗 SDD · ${d}`,
2622
+ "",
2623
+ ` ${M(t)} 1. ${p("Портал")}${i}`,
2624
+ ` ${M(s)} 2. ${p("Скоупы")}${a}`,
2625
+ ` ${M(n)} 3. ${p("Модули")}${c}`,
2626
+ ` ${M(r)} 4. ${p("Инфраструктура")}${l}`,
2627
+ ` ${M(o)} 5. ${p("Задачи")}${f}`,
2628
+ "",
2629
+ ` 👉 Следующий шаг: ${u}`
2630
+ ].join(`
2631
+ `);
2632
+ }
2633
+ function Yo(e) {
2485
2634
  const t = P(`git -C ${JSON.stringify(e)} diff --name-only HEAD 2>/dev/null`), s = P(
2486
2635
  `git -C ${JSON.stringify(e)} ls-files --others --exclude-standard 2>/dev/null`
2487
2636
  );
2488
2637
  return [...new Set(
2489
2638
  [...t.split(`
2490
2639
  `), ...s.split(`
2491
- `)].map((o) => o.trim()).filter(Boolean)
2640
+ `)].map((r) => r.trim()).filter(Boolean)
2492
2641
  )].filter(
2493
- (o) => /\.(ts|tsx|js)$/.test(o) && !/\.(test|spec)\.[jt]sx?$/.test(o) && !o.includes("node_modules/")
2642
+ (r) => /\.(ts|tsx|js)$/.test(r) && !/\.(test|spec)\.[jt]sx?$/.test(r) && !r.includes("node_modules/")
2494
2643
  );
2495
2644
  }
2496
- function xo(e, t) {
2645
+ function Ho(e, t) {
2497
2646
  const s = P(
2498
2647
  `git -C ${JSON.stringify(e)} show HEAD:${JSON.stringify(t)} 2>/dev/null`,
2499
2648
  { expectedExitCodes: [128] }
2500
2649
  );
2501
2650
  return s || null;
2502
2651
  }
2503
- function M(e, t) {
2652
+ function $(e, t) {
2504
2653
  const s = new RegExp(`\\*\\*${t}:\\*\\*\\s*(.+)`);
2505
2654
  return e.match(s)?.[1]?.trim() ?? null;
2506
2655
  }
2507
- function ie(e, t) {
2656
+ function ce(e, t) {
2508
2657
  const s = e.split(`
2509
2658
  `), n = [];
2510
- let o = !1;
2511
- for (const r of s) {
2512
- const i = /^\s*-?\s*\*\*([^:*]+):\*\*/.exec(r);
2659
+ let r = !1;
2660
+ for (const o of s) {
2661
+ const i = /^\s*-?\s*\*\*([^:*]+):\*\*/.exec(o);
2513
2662
  if (i) {
2514
- o = i[1]?.trim().toLowerCase() === t.toLowerCase();
2663
+ r = i[1]?.trim().toLowerCase() === t.toLowerCase();
2515
2664
  continue;
2516
2665
  }
2517
- if (o && r.trim() !== "")
2518
- if (/^\s*-\s+/.test(r)) n.push(r.trim().replace(/^-\s+/, "").trim());
2666
+ if (r && o.trim() !== "")
2667
+ if (/^\s*-\s+/.test(o)) n.push(o.trim().replace(/^-\s+/, "").trim());
2519
2668
  else break;
2520
2669
  }
2521
2670
  return n;
2522
2671
  }
2523
- function ae(e) {
2672
+ function le(e) {
2524
2673
  const t = e.match(/\[([^\]]+)\]\(([^)]+)\)/);
2525
2674
  return t && t[1] && t[2] ? { name: t[1], anchor: t[2] } : { name: e.trim(), anchor: "" };
2526
2675
  }
2527
- function me(e) {
2528
- const t = e.match(/\*\*Task-ID:\*\*\s*`?([A-Za-z0-9][\w-]*)`?/)?.[1] ?? null, s = e.match(/\*\*Status:\*\*\s*(\[.\]\s*[A-Z_]+)/)?.[1] ?? null, n = M(e, "Dependencies"), o = !n || /^none$/i.test(n.trim()) ? [] : n.split(",").map((i) => i.trim()).filter(Boolean), r = ie(e, "Spec References").map((i) => {
2529
- const a = i.indexOf(":"), c = a !== -1 && a < i.indexOf("["), l = c ? i.slice(0, a).trim() : "", { name: f, anchor: d } = ae(c ? i.slice(a + 1) : i);
2676
+ function he(e) {
2677
+ const t = e.match(/\*\*Task-ID:\*\*\s*`?([A-Za-z0-9][\w-]*)`?/)?.[1] ?? null, s = e.match(/\*\*Status:\*\*\s*(\[.\]\s*[A-Z_]+)/)?.[1] ?? null, n = $(e, "Dependencies"), r = !n || /^none$/i.test(n.trim()) ? [] : n.split(",").map((i) => i.trim()).filter(Boolean), o = ce(e, "Spec References").map((i) => {
2678
+ const a = i.indexOf(":"), c = a !== -1 && a < i.indexOf("["), l = c ? i.slice(0, a).trim() : "", { name: f, anchor: d } = le(c ? i.slice(a + 1) : i);
2530
2679
  return { role: l, name: f, anchor: d };
2531
2680
  });
2532
2681
  return {
2533
2682
  taskId: t,
2534
2683
  status: s,
2535
- purpose: M(e, "Purpose"),
2536
- scope: M(e, "Scope"),
2537
- module: M(e, "Module"),
2538
- dependencies: o,
2539
- specRefs: r
2684
+ purpose: $(e, "Purpose"),
2685
+ scope: $(e, "Scope"),
2686
+ module: $(e, "Module"),
2687
+ dependencies: r,
2688
+ specRefs: o
2540
2689
  };
2541
2690
  }
2542
- function tt(e) {
2691
+ function it(e) {
2543
2692
  return e.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((t) => t.trim());
2544
2693
  }
2545
- function st(e) {
2694
+ function at(e) {
2546
2695
  return /^\|?\s*:?-{2,}/.test(e.trim());
2547
2696
  }
2548
- function Ks(e) {
2697
+ function en(e) {
2549
2698
  const t = [];
2550
2699
  for (const s of e.split(`
2551
2700
  `)) {
2552
- if (!s.trimStart().startsWith("|") || st(s)) continue;
2553
- const n = tt(s);
2701
+ if (!s.trimStart().startsWith("|") || at(s)) continue;
2702
+ const n = it(s);
2554
2703
  if (n.length < 4 || n[0]?.toLowerCase() === "id") continue;
2555
- const [o, r, i, a] = n;
2556
- o && t.push({
2557
- id: o,
2558
- kind: r ?? "",
2704
+ const [r, o, i, a] = n;
2705
+ r && t.push({
2706
+ id: r,
2707
+ kind: o ?? "",
2559
2708
  deps: !i || i === "—" ? [] : i.split(",").map((c) => c.trim()).filter(Boolean),
2560
2709
  status: a ?? ""
2561
2710
  });
2562
2711
  }
2563
2712
  return t;
2564
2713
  }
2565
- function $o(e) {
2714
+ function qo(e) {
2566
2715
  return {
2567
- objective: M(e, "Objective"),
2568
- rules: ie(e, "Rules").map((t) => ae(t).anchor || ae(t).name),
2569
- targetFiles: ie(e, "Target Files").map((t) => t.replace(/[`*]/g, "").trim()),
2570
- inputs: M(e, "Inputs"),
2571
- exit: M(e, "Exit")
2716
+ objective: $(e, "Objective"),
2717
+ rules: ce(e, "Rules").map((t) => le(t).anchor || le(t).name),
2718
+ targetFiles: ce(e, "Target Files").map((t) => t.replace(/[`*]/g, "").trim()),
2719
+ inputs: $(e, "Inputs"),
2720
+ exit: $(e, "Exit")
2572
2721
  };
2573
2722
  }
2574
- function Bo(e) {
2723
+ function Wo(e) {
2575
2724
  const t = [];
2576
2725
  for (const s of e.split(`
2577
2726
  `)) {
2578
- if (!s.trimStart().startsWith("|") || st(s)) continue;
2579
- const n = tt(s);
2727
+ if (!s.trimStart().startsWith("|") || at(s)) continue;
2728
+ const n = it(s);
2580
2729
  if (n.length < 2 || n[0]?.toLowerCase() === "command") continue;
2581
- const [o, r] = n;
2582
- o && t.push({
2583
- command: o.replace(/`/g, "").trim(),
2584
- requiredBy: (r ?? "").split(",").map((i) => i.trim()).filter(Boolean)
2730
+ const [r, o] = n;
2731
+ r && t.push({
2732
+ command: r.replace(/`/g, "").trim(),
2733
+ requiredBy: (o ?? "").split(",").map((i) => i.trim()).filter(Boolean)
2585
2734
  });
2586
2735
  }
2587
2736
  return t;
2588
2737
  }
2589
- function Xs(e, t) {
2738
+ function tn(e, t) {
2590
2739
  const s = t.trim(), n = /^P(\d+)(\b|_FIX\b)/i.exec(s);
2591
2740
  if (e === 3 && n) return `PHASE_P${n[1]}${/_FIX/i.test(s) ? "_FIX" : ""}`;
2592
2741
  if (e !== 2) return null;
2593
- const o = s.toLowerCase();
2594
- return /\bmeta\b/.test(o) ? "META" : /phases overview/.test(o) ? "PHASES_OVERVIEW" : /acceptance criteria|\bbdd\b/.test(o) ? "BDD" : /\bverification\b/.test(o) ? "VERIFICATION" : /test scenario coverage|test coverage/.test(o) ? "TEST_COVERAGE" : /execution log/.test(o) ? "EXECUTION_LOG" : /decision log/.test(o) ? "DECISION_LOG" : null;
2742
+ const r = s.toLowerCase();
2743
+ return /\bmeta\b/.test(r) ? "META" : /phases overview/.test(r) ? "PHASES_OVERVIEW" : /acceptance criteria|\bbdd\b/.test(r) ? "BDD" : /\bverification\b/.test(r) ? "VERIFICATION" : /test scenario coverage|test coverage/.test(r) ? "TEST_COVERAGE" : /execution log/.test(r) ? "EXECUTION_LOG" : /decision log/.test(r) ? "DECISION_LOG" : null;
2595
2744
  }
2596
- function nt(e) {
2745
+ function ct(e) {
2597
2746
  const t = [];
2598
2747
  return e.forEach((s, n) => {
2599
- const o = /^(#{2,3})\s+(.+?)\s*$/.exec(s);
2600
- o && o[1] && o[2] && t.push({ idx: n, level: o[1].length, name: Xs(o[1].length, o[2]) });
2748
+ const r = /^(#{2,3})\s+(.+?)\s*$/.exec(s);
2749
+ r && r[1] && r[2] && t.push({ idx: n, level: r[1].length, name: tn(r[1].length, r[2]) });
2601
2750
  }), t;
2602
2751
  }
2603
- function W(e, t) {
2752
+ function X(e, t) {
2604
2753
  const s = e.split(`
2605
- `), n = nt(s), o = n.find((i) => i.name === t);
2606
- if (!o) return null;
2607
- let r = s.length;
2754
+ `), n = ct(s), r = n.find((i) => i.name === t);
2755
+ if (!r) return null;
2756
+ let o = s.length;
2608
2757
  for (const i of n)
2609
- if (i.idx > o.idx && i.level <= o.level) {
2610
- r = i.idx;
2758
+ if (i.idx > r.idx && i.level <= r.level) {
2759
+ o = i.idx;
2611
2760
  break;
2612
2761
  }
2613
- return s.slice(o.idx + 1, r).join(`
2762
+ return s.slice(r.idx + 1, o).join(`
2614
2763
  `);
2615
2764
  }
2616
- function Uo(e) {
2765
+ function Ko(e) {
2617
2766
  const t = e.split(`
2618
- `), s = nt(t), n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), r = [];
2767
+ `), s = ct(t), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), o = [];
2619
2768
  for (let a = 0; a < s.length; a++) {
2620
2769
  const c = s[a];
2621
2770
  if (!c || c.name === null || e.includes(`<!--SECTION:${c.name}-->`)) continue;
@@ -2627,23 +2776,23 @@ function Uo(e) {
2627
2776
  break;
2628
2777
  }
2629
2778
  }
2630
- n.set(c.idx, c.name), o.set(l, c.name), r.push(c.name);
2779
+ n.set(c.idx, c.name), r.set(l, c.name), o.push(c.name);
2631
2780
  }
2632
- if (r.length === 0) return { text: e, injected: [] };
2781
+ if (o.length === 0) return { text: e, injected: [] };
2633
2782
  const i = [];
2634
2783
  for (let a = 0; a <= t.length; a++) {
2635
- const c = o.get(a);
2784
+ const c = r.get(a);
2636
2785
  c && i.push(`<!--/SECTION:${c}-->`);
2637
2786
  const l = n.get(a);
2638
2787
  l && i.push(`<!--SECTION:${l}-->`), a < t.length && i.push(t[a]);
2639
2788
  }
2640
2789
  return { text: i.join(`
2641
- `), injected: r };
2790
+ `), injected: o };
2642
2791
  }
2643
- function Go(e, t) {
2644
- const s = e.includes("<!--SECTION:META-->") || W(e, "META") !== null, n = e.includes("<!--SECTION:EXECUTION_LOG-->");
2792
+ function Xo(e, t) {
2793
+ const s = e.includes("<!--SECTION:META-->") || X(e, "META") !== null, n = e.includes("<!--SECTION:EXECUTION_LOG-->");
2645
2794
  if (!s || n) return { text: e, scaffolded: !1 };
2646
- const o = [
2795
+ const r = [
2647
2796
  "",
2648
2797
  "## Execution Log",
2649
2798
  "<!--SECTION:EXECUTION_LOG-->",
@@ -2653,33 +2802,33 @@ function Go(e, t) {
2653
2802
  `);
2654
2803
  return { text: `${e.endsWith(`
2655
2804
  `) ? e.slice(0, -1) : e}
2656
- ${o}
2805
+ ${r}
2657
2806
  `, scaffolded: !0 };
2658
2807
  }
2659
- const ke = /<[A-Za-z…][^>\s]*>/, Zs = /`[^`]*`/g;
2660
- function Fo(e) {
2808
+ const we = /<[A-Za-z…][^>\s]*>/, sn = /`[^`]*`/g;
2809
+ function Zo(e) {
2661
2810
  return e.includes("<!--SECTION:META-->") && e.includes("<!--SECTION:EXECUTION_LOG-->");
2662
2811
  }
2663
- function Vo(e) {
2664
- return W(e, "META") !== null && W(e, "EXECUTION_LOG") !== null;
2812
+ function zo(e) {
2813
+ return X(e, "META") !== null && X(e, "EXECUTION_LOG") !== null;
2665
2814
  }
2666
- function ot(e) {
2815
+ function lt(e) {
2667
2816
  const t = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
2668
- for (const o of e.split(`
2817
+ for (const r of e.split(`
2669
2818
  `)) {
2670
- const r = o.trim(), i = /^<!--SECTION:([A-Z][A-Z0-9_]*)-->$/.exec(r), a = /^<!--\/SECTION:([A-Z][A-Z0-9_]*)-->$/.exec(r);
2819
+ const o = r.trim(), i = /^<!--SECTION:([A-Z][A-Z0-9_]*)-->$/.exec(o), a = /^<!--\/SECTION:([A-Z][A-Z0-9_]*)-->$/.exec(o);
2671
2820
  i?.[1] && t.set(i[1], (t.get(i[1]) ?? 0) + 1), a?.[1] && s.set(a[1], (s.get(a[1]) ?? 0) + 1);
2672
2821
  }
2673
- return [.../* @__PURE__ */ new Set([...t.keys(), ...s.keys()])].filter((o) => (t.get(o) ?? 0) !== (s.get(o) ?? 0));
2822
+ return [.../* @__PURE__ */ new Set([...t.keys(), ...s.keys()])].filter((r) => (t.get(r) ?? 0) !== (s.get(r) ?? 0));
2674
2823
  }
2675
- function rt(e) {
2824
+ function dt(e) {
2676
2825
  const t = [], s = [];
2677
2826
  for (const n of e.split(`
2678
2827
  `)) {
2679
- const o = n.trim(), r = /^<!--SECTION:([A-Z][A-Z0-9_]*)-->$/.exec(o), i = /^<!--\/SECTION:([A-Z][A-Z0-9_]*)-->$/.exec(o);
2680
- if (r?.[1]) {
2828
+ const r = n.trim(), o = /^<!--SECTION:([A-Z][A-Z0-9_]*)-->$/.exec(r), i = /^<!--\/SECTION:([A-Z][A-Z0-9_]*)-->$/.exec(r);
2829
+ if (o?.[1]) {
2681
2830
  const a = s[s.length - 1];
2682
- a && t.push(`${r[1]} opens while ${a} is still open — sections must be flat, not nested`), s.push(r[1]);
2831
+ a && t.push(`${o[1]} opens while ${a} is still open — sections must be flat, not nested`), s.push(o[1]);
2683
2832
  } else if (i?.[1]) {
2684
2833
  const a = s[s.length - 1];
2685
2834
  if (a === i[1]) s.pop();
@@ -2693,56 +2842,56 @@ function rt(e) {
2693
2842
  }
2694
2843
  return t;
2695
2844
  }
2696
- function zs(e) {
2845
+ function nn(e) {
2697
2846
  const t = e.split(`
2698
2847
  `);
2699
2848
  let s = -1, n = -1;
2700
- return t.forEach((o, r) => {
2701
- /🛑|BLOCKED/.test(o) && (s = r), /✅|RESOLVED/.test(o) && (n = r);
2849
+ return t.forEach((r, o) => {
2850
+ /🛑|BLOCKED/.test(r) && (s = o), /✅|RESOLVED/.test(r) && (n = o);
2702
2851
  }), s !== -1 && s > n;
2703
2852
  }
2704
- function jo(e, t) {
2705
- const s = [], n = (l, f) => void s.push({ severity: "error", code: l, file: e, message: f }), o = (l, f) => void s.push({ severity: "warn", code: l, file: e, message: f });
2706
- for (const l of ot(t))
2853
+ function Qo(e, t) {
2854
+ const s = [], n = (l, f) => void s.push({ severity: "error", code: l, file: e, message: f }), r = (l, f) => void s.push({ severity: "warn", code: l, file: e, message: f });
2855
+ for (const l of lt(t))
2707
2856
  n("SDD_ANCHOR_UNBALANCED", `Section ${l}: open/close markers do not balance.`);
2708
- for (const l of rt(t))
2857
+ for (const l of dt(t))
2709
2858
  n("SDD_SECTION_OVERLAP", `${l}. sdd-extract pulls one flat section — fix the marker order.`);
2710
- const r = g(t, "META"), i = g(t, "EXECUTION_LOG");
2711
- r.status !== "ok" && n("SDD_MISSING_META", "No usable META section."), i.status !== "ok" && n("SDD_MISSING_EXECUTION_LOG", "No usable EXECUTION_LOG section.");
2859
+ const o = g(t, "META"), i = g(t, "EXECUTION_LOG");
2860
+ o.status !== "ok" && n("SDD_MISSING_META", "No usable META section."), i.status !== "ok" && n("SDD_MISSING_EXECUTION_LOG", "No usable EXECUTION_LOG section.");
2712
2861
  let a = !1;
2713
- if (r.status === "ok") {
2714
- const l = me(r.content);
2715
- l.taskId || o("SDD_MISSING_TASK_ID", "Meta has no parseable Task-ID."), l.status || o("SDD_STATUS_UNPARSEABLE", "Meta Status is missing or not in `[x] STATE` form."), a = l.status?.includes("[x]") ?? !1;
2862
+ if (o.status === "ok") {
2863
+ const l = he(o.content);
2864
+ l.taskId || r("SDD_MISSING_TASK_ID", "Meta has no parseable Task-ID."), l.status || r("SDD_STATUS_UNPARSEABLE", "Meta Status is missing or not in `[x] STATE` form."), a = l.status?.includes("[x]") ?? !1;
2716
2865
  }
2717
2866
  if (i.status === "ok") {
2718
2867
  const l = i.content.split(`
2719
2868
  `);
2720
2869
  for (const f of l) {
2721
- const d = f.replace(Zs, "");
2722
- /\[x\]/.test(d) && ke.test(f) && n(
2870
+ const d = f.replace(sn, "");
2871
+ /\[x\]/.test(d) && we.test(f) && n(
2723
2872
  "SDD_FABRICATED_DONE",
2724
2873
  `Checked [x] line with an unreplaced placeholder: "${f.trim()}"`
2725
2874
  );
2726
2875
  }
2727
- zs(i.content) && (a ? n(
2876
+ nn(i.content) && (a ? n(
2728
2877
  "SDD_DONE_WITH_ACTIVE_BLOCKER",
2729
2878
  "Status is DONE but the Execution Log ends with an unresolved BLOCKED."
2730
- ) : o(
2879
+ ) : r(
2731
2880
  "SDD_BLOCKER_OPEN",
2732
2881
  "Execution Log ends with an unresolved 🛑 BLOCKED — no later ✅ RESOLVED. Resolve or explicitly reopen before the orchestrator relies on this ticket."
2733
2882
  ));
2734
2883
  }
2735
- a && ke.test(t) && o(
2884
+ a && we.test(t) && r(
2736
2885
  "SDD_DONE_WITH_PLACEHOLDERS",
2737
2886
  "Status is DONE but unreplaced <…> scaffold placeholders remain."
2738
2887
  );
2739
2888
  const c = g(t, "PHASES_OVERVIEW");
2740
2889
  if (c.status === "ok") {
2741
- const l = Ks(c.content), f = new Set(l.map((u) => u.id));
2890
+ const l = en(c.content), f = new Set(l.map((u) => u.id));
2742
2891
  for (const u of l)
2743
2892
  for (const p of u.deps)
2744
2893
  f.has(p) || n("SDD_PHASE_DEP_UNRESOLVED", `Phase ${u.id} depends on unknown phase ${p}.`);
2745
- J(l.flatMap((u) => u.deps.map((p) => ({ from: u.id, to: p })))) && n("SDD_PHASE_DAG_CYCLE", "Phase dependency graph has a cycle.");
2894
+ te(l.flatMap((u) => u.deps.map((p) => ({ from: u.id, to: p })))) && n("SDD_PHASE_DAG_CYCLE", "Phase dependency graph has a cycle.");
2746
2895
  const d = /* @__PURE__ */ new Set();
2747
2896
  for (const u of t.matchAll(/<!--SECTION:PHASE_(P[0-9]+)-->/g))
2748
2897
  d.add(u[1]);
@@ -2759,27 +2908,27 @@ function jo(e, t) {
2759
2908
  }
2760
2909
  return s;
2761
2910
  }
2762
- function J(e) {
2911
+ function te(e) {
2763
2912
  const t = /* @__PURE__ */ new Map();
2764
- for (const o of e) {
2765
- const r = t.get(o.from);
2766
- r ? r.push(o.to) : t.set(o.from, [o.to]);
2913
+ for (const r of e) {
2914
+ const o = t.get(r.from);
2915
+ o ? o.push(r.to) : t.set(r.from, [r.to]);
2767
2916
  }
2768
- const s = /* @__PURE__ */ new Map(), n = (o) => {
2769
- s.set(o, 1);
2770
- for (const r of t.get(o) ?? []) {
2771
- const i = s.get(r);
2772
- if (i === 1 || i === void 0 && n(r)) return !0;
2917
+ const s = /* @__PURE__ */ new Map(), n = (r) => {
2918
+ s.set(r, 1);
2919
+ for (const o of t.get(r) ?? []) {
2920
+ const i = s.get(o);
2921
+ if (i === 1 || i === void 0 && n(o)) return !0;
2773
2922
  }
2774
- return s.set(o, 2), !1;
2923
+ return s.set(r, 2), !1;
2775
2924
  };
2776
- for (const o of t.keys())
2777
- if (s.get(o) === void 0 && n(o)) return !0;
2925
+ for (const r of t.keys())
2926
+ if (s.get(r) === void 0 && n(r)) return !0;
2778
2927
  return !1;
2779
2928
  }
2780
- function Yo(e) {
2781
- const { scopes: t, edges: s, specDirs: n } = e, o = "specs/README.md", r = [], i = (c, l) => void r.push({ severity: "error", code: c, file: o, message: l }), a = new Set(t.map((c) => c.name));
2782
- J(s) && i("SDD_PORTAL_GRAPH_CYCLE", "Scope Graph has a dependency cycle.");
2929
+ function Jo(e) {
2930
+ const { scopes: t, edges: s, specDirs: n } = e, r = "specs/README.md", o = [], i = (c, l) => void o.push({ severity: "error", code: c, file: r, message: l }), a = new Set(t.map((c) => c.name));
2931
+ te(s) && i("SDD_PORTAL_GRAPH_CYCLE", "Scope Graph has a dependency cycle.");
2783
2932
  for (const c of s)
2784
2933
  a.has(c.from) || i(
2785
2934
  "SDD_PORTAL_DANGLING_DEP",
@@ -2792,29 +2941,29 @@ function Yo(e) {
2792
2941
  a.has(c) || i("SDD_PORTAL_ORPHAN_SPEC", `Spec dir has no row in the portal Scopes table: specs/${c}/`);
2793
2942
  for (const c of t)
2794
2943
  c.status === "done" && !n.includes(c.name) && i("SDD_PORTAL_SPEC_MISSING", `Scope marked done has no spec on disk: ${c.name}`);
2795
- return r;
2944
+ return o;
2796
2945
  }
2797
- function Ho(e, t, s) {
2798
- const n = g(t, "META"), o = n.status === "ok" ? me(n.content) : null;
2946
+ function er(e, t, s) {
2947
+ const n = g(t, "META"), r = n.status === "ok" ? he(n.content) : null;
2799
2948
  return {
2800
2949
  file: e,
2801
- taskId: o?.taskId ?? null,
2802
- status: o?.status ?? null,
2803
- dependencies: o?.dependencies ?? [],
2950
+ taskId: r?.taskId ?? null,
2951
+ status: r?.status ?? null,
2952
+ dependencies: r?.dependencies ?? [],
2804
2953
  flowVersion: s
2805
2954
  };
2806
2955
  }
2807
- function qo(e, t, s) {
2808
- const n = W(t, "META"), o = n !== null ? me(n) : null;
2956
+ function tr(e, t, s) {
2957
+ const n = X(t, "META"), r = n !== null ? he(n) : null;
2809
2958
  return {
2810
2959
  file: e,
2811
- taskId: o?.taskId ?? null,
2812
- status: o?.status ?? null,
2813
- dependencies: o?.dependencies ?? [],
2960
+ taskId: r?.taskId ?? null,
2961
+ status: r?.status ?? null,
2962
+ dependencies: r?.dependencies ?? [],
2814
2963
  flowVersion: s
2815
2964
  };
2816
2965
  }
2817
- function Wo(e) {
2966
+ function sr(e) {
2818
2967
  return [
2819
2968
  {
2820
2969
  severity: "warn",
@@ -2824,49 +2973,49 @@ function Wo(e) {
2824
2973
  }
2825
2974
  ];
2826
2975
  }
2827
- function Qs(e) {
2976
+ function on(e) {
2828
2977
  return e != null && /\bDONE\b/i.test(e);
2829
2978
  }
2830
- function Ko(e) {
2979
+ function nr(e) {
2831
2980
  const t = new Map(
2832
2981
  e.filter((n) => n.taskId).map((n) => [n.taskId, n.status])
2833
- ), s = (n) => n.filter((o) => !/^(none|n\/a|[—-])\b/i.test(o.trim()));
2982
+ ), s = (n) => n.filter((r) => !/^(none|n\/a|[—-])\b/i.test(r.trim()));
2834
2983
  return e.filter(
2835
- (n) => n.taskId != null && /\bTODO\b/i.test(n.status ?? "") && s(n.dependencies).every((o) => Qs(t.get(o)))
2984
+ (n) => n.taskId != null && /\bTODO\b/i.test(n.status ?? "") && s(n.dependencies).every((r) => on(t.get(r)))
2836
2985
  );
2837
2986
  }
2838
- function Xo(e) {
2987
+ function or(e) {
2839
2988
  const t = [], s = /* @__PURE__ */ new Map();
2840
- for (const o of e) {
2841
- if (!o.taskId) continue;
2842
- const r = s.get(o.taskId);
2843
- r ? r.push(o.file) : s.set(o.taskId, [o.file]);
2989
+ for (const r of e) {
2990
+ if (!r.taskId) continue;
2991
+ const o = s.get(r.taskId);
2992
+ o ? o.push(r.file) : s.set(r.taskId, [r.file]);
2844
2993
  }
2845
- for (const [o, r] of s)
2846
- r.length > 1 && t.push({
2994
+ for (const [r, o] of s)
2995
+ o.length > 1 && t.push({
2847
2996
  severity: "error",
2848
2997
  code: "SDD_TASK_ID_COLLISION",
2849
- file: r[0],
2850
- message: `Task-ID ${o} is used by ${r.length} tickets: ${r.join(", ")}.`
2998
+ file: o[0],
2999
+ message: `Task-ID ${r} is used by ${o.length} tickets: ${o.join(", ")}.`
2851
3000
  });
2852
- for (const o of e)
2853
- for (const r of o.dependencies)
2854
- s.has(r) || t.push({
3001
+ for (const r of e)
3002
+ for (const o of r.dependencies)
3003
+ s.has(o) || t.push({
2855
3004
  severity: "error",
2856
3005
  code: "SDD_DEP_UNRESOLVED",
2857
- file: o.file,
2858
- message: `Dependency ${r} resolves to no ticket in the tree.`
3006
+ file: r.file,
3007
+ message: `Dependency ${o} resolves to no ticket in the tree.`
2859
3008
  });
2860
- const n = e.filter((o) => o.taskId).flatMap((o) => o.dependencies.map((r) => ({ from: o.taskId, to: r })));
2861
- return J(n) && t.push({
3009
+ const n = e.filter((r) => r.taskId).flatMap((r) => r.dependencies.map((o) => ({ from: r.taskId, to: o })));
3010
+ return te(n) && t.push({
2862
3011
  severity: "error",
2863
3012
  code: "SDD_DAG_CYCLE",
2864
3013
  file: "(task graph)",
2865
3014
  message: "Task dependency graph has a cycle."
2866
3015
  }), t;
2867
3016
  }
2868
- function Zo(e, t) {
2869
- const s = [], n = (a) => a.replace(/`/g, "").replace(/\s+/g, " ").trim(), o = (a) => a === "v2" ? "error" : "warn", r = new Set(e.map((a) => a.taskId).filter((a) => a !== null)), i = /* @__PURE__ */ new Map();
3017
+ function rr(e, t) {
3018
+ const s = [], n = (a) => a.replace(/`/g, "").replace(/\s+/g, " ").trim(), r = (a) => a === "v2" ? "error" : "warn", o = new Set(e.map((a) => a.taskId).filter((a) => a !== null)), i = /* @__PURE__ */ new Map();
2870
3019
  for (const a of t) {
2871
3020
  const c = i.get(a.taskId);
2872
3021
  c ? c.push(a) : i.set(a.taskId, [a]);
@@ -2876,7 +3025,7 @@ function Zo(e, t) {
2876
3025
  const c = i.get(a.taskId);
2877
3026
  if (!c) {
2878
3027
  s.push({
2879
- severity: o(a.flowVersion),
3028
+ severity: r(a.flowVersion),
2880
3029
  code: "SDD_TRACKER_MISSING_ROW",
2881
3030
  file: a.file,
2882
3031
  message: `Ticket ${a.taskId} has no row in any Tracker Index.`
@@ -2893,23 +3042,23 @@ function Zo(e, t) {
2893
3042
  });
2894
3043
  }
2895
3044
  for (const a of t)
2896
- r.has(a.taskId) || s.push({
2897
- severity: o(a.flowVersion),
3045
+ o.has(a.taskId) || s.push({
3046
+ severity: r(a.flowVersion),
2898
3047
  code: "SDD_TRACKER_ORPHAN_ROW",
2899
3048
  file: a.file,
2900
3049
  message: `Tracker row ${a.taskId} points to no ticket on disk.`
2901
3050
  });
2902
3051
  return s;
2903
3052
  }
2904
- const ce = Object.fromEntries(
2905
- je.map((e) => [e, Ye(e)])
2906
- ), it = Ye("module"), le = Array.from(
2907
- new Set([...je, "module"].flatMap((e) => Ns(e)))
2908
- ), ve = 120, we = 120, Pe = 6, Js = /[.!?]\s+[A-ZА-ЯЁ]/;
2909
- function en(e) {
3053
+ const de = Object.fromEntries(
3054
+ He.map((e) => [e, qe(e)])
3055
+ ), ut = qe("module"), ue = Array.from(
3056
+ new Set([...He, "module"].flatMap((e) => Ds(e)))
3057
+ ), Pe = 120, Le = 120, be = 6, rn = /[.!?]\s+[A-ZА-ЯЁ]/;
3058
+ function an(e) {
2910
3059
  return (e.match(/^```/gm) ?? []).length >= 2;
2911
3060
  }
2912
- const tn = [
3061
+ const cn = [
2913
3062
  { re: /аппрув[а-яё]*/giu, say: "подтверждение" },
2914
3063
  { re: /реифицир[а-яё]*/giu, say: "вынести в данные" },
2915
3064
  { re: /чек(ать|нуть|аем|ается)[а-яё]*/giu, say: "проверить" },
@@ -2927,7 +3076,7 @@ const tn = [
2927
3076
  { re: /подня[а-яё]*\s+сервис[а-яё]*/giu, say: "запустить сервис" },
2928
3077
  { re: /на\s+проводе/giu, say: "в ответе / запросе сервера" },
2929
3078
  { re: /разв(о|е)д[а-яё]*\s+провод[а-яё]*/giu, say: "явно связать зависимости" }
2930
- ], sn = [
3079
+ ], ln = [
2931
3080
  {
2932
3081
  re: /осуществля[а-яё]*/giu,
2933
3082
  say: "подставить подлежащее и обычный глагол, напр. «модуль делает X»"
@@ -2939,50 +3088,50 @@ const tn = [
2939
3088
  },
2940
3089
  { re: /имеет\s+место\s+быть/giu, say: "есть / происходит" }
2941
3090
  ];
2942
- function zo(e, t) {
3091
+ function ir(e, t) {
2943
3092
  const s = [];
2944
- for (const { re: n, say: o } of tn) {
2945
- const r = [...t.matchAll(n)].map((i) => i[0]);
2946
- r.length !== 0 && s.push({
3093
+ for (const { re: n, say: r } of cn) {
3094
+ const o = [...t.matchAll(n)].map((i) => i[0]);
3095
+ o.length !== 0 && s.push({
2947
3096
  severity: "warn",
2948
3097
  code: "SDD_LANGUAGE_CALQUE",
2949
3098
  file: e,
2950
- message: `«${r[0]}»${r.length > 1 ? ` (×${r.length})` : ""} — англицизм-калька; по-русски: ${o} (AX_OPERATOR_DIALOGUE_STYLE).`
3099
+ message: `«${o[0]}»${o.length > 1 ? ` (×${o.length})` : ""} — англицизм-калька; по-русски: ${r} (AX_OPERATOR_DIALOGUE_STYLE).`
2951
3100
  });
2952
3101
  }
2953
- for (const { re: n, say: o } of sn) {
2954
- const r = [...t.matchAll(n)].map((i) => i[0]);
2955
- r.length !== 0 && s.push({
3102
+ for (const { re: n, say: r } of ln) {
3103
+ const o = [...t.matchAll(n)].map((i) => i[0]);
3104
+ o.length !== 0 && s.push({
2956
3105
  severity: "warn",
2957
3106
  code: "SDD_LANGUAGE_CALQUE",
2958
3107
  file: e,
2959
- message: `«${r[0]}»${r.length > 1 ? ` (×${r.length})` : ""} — канцелярит; по-русски: ${o} (AX_OPERATOR_DIALOGUE_STYLE).`
3108
+ message: `«${o[0]}»${o.length > 1 ? ` (×${o.length})` : ""} — канцелярит; по-русски: ${r} (AX_OPERATOR_DIALOGUE_STYLE).`
2960
3109
  });
2961
3110
  }
2962
3111
  return s;
2963
3112
  }
2964
- const Le = 20, be = 750;
2965
- function nn(e) {
3113
+ const Me = 20, $e = 750;
3114
+ function dn(e) {
2966
3115
  const t = e.split(`
2967
3116
  `).map((s) => s.trim()).filter((s) => s.startsWith("|") && !/^\|[\s:|-]+$/.test(s));
2968
3117
  return Math.max(0, t.length - 1);
2969
3118
  }
2970
- function Qo(e, t, s = "v1") {
2971
- const n = ot(t).map((a) => ({
3119
+ function ar(e, t, s = "v1") {
3120
+ const n = lt(t).map((a) => ({
2972
3121
  severity: "error",
2973
3122
  code: "SDD_ANCHOR_UNBALANCED",
2974
3123
  file: e,
2975
3124
  message: `Section ${a}: open/close markers do not balance.`
2976
3125
  }));
2977
- for (const a of rt(t))
3126
+ for (const a of dt(t))
2978
3127
  n.push({
2979
3128
  severity: "error",
2980
3129
  code: "SDD_SECTION_OVERLAP",
2981
3130
  file: e,
2982
3131
  message: `${a}. sdd-extract pulls one flat section — fix the marker order.`
2983
3132
  });
2984
- const o = /<!--SECTION:MODULE_VISION-->/.test(t), r = /<!--SECTION:SCOPE_TYPE-->/.test(t) && !o;
2985
- if (r)
3133
+ const r = /<!--SECTION:MODULE_VISION-->/.test(t), o = /<!--SECTION:SCOPE_TYPE-->/.test(t) && !r;
3134
+ if (o)
2986
3135
  for (const a of ["ENTITY_INVENTORY", "MODULE_CONTRACTS"])
2987
3136
  new RegExp(`<!--SECTION:${a}-->`).test(t) && n.push({
2988
3137
  severity: "warn",
@@ -2990,32 +3139,32 @@ function Qo(e, t, s = "v1") {
2990
3139
  file: e,
2991
3140
  message: `Scope spec carries module-level section ${a} — move that detail into a module spec; a scope stays a thin index of modules (AX_SCOPE_STAYS_THIN).`
2992
3141
  });
2993
- if (o) {
2994
- const a = g(t, "ENTITY_INVENTORY"), c = a.status === "ok" ? nn(a.content) : 0;
2995
- c > Le ? n.push({
3142
+ if (r) {
3143
+ const a = g(t, "ENTITY_INVENTORY"), c = a.status === "ok" ? dn(a.content) : 0;
3144
+ c > Me ? n.push({
2996
3145
  severity: "warn",
2997
3146
  code: "SDD_MODULE_OVERSIZED",
2998
3147
  file: e,
2999
- message: `Entity Inventory has ${c} entities (> ${Le}) — decompose into sub-modules (AX_HIERARCHICAL_SPECS).`
3148
+ message: `Entity Inventory has ${c} entities (> ${Me}) — decompose into sub-modules (AX_HIERARCHICAL_SPECS).`
3000
3149
  }) : t.split(`
3001
- `).length > be && n.push({
3150
+ `).length > $e && n.push({
3002
3151
  severity: "warn",
3003
3152
  code: "SDD_MODULE_SPEC_VERBOSE",
3004
3153
  file: e,
3005
3154
  message: `Module spec is ${t.split(`
3006
- `).length} lines (> ${be}) with a cohesive inventory — compress the spec (AX_HIERARCHICAL_SPECS).`
3155
+ `).length} lines (> ${$e}) with a cohesive inventory — compress the spec (AX_HIERARCHICAL_SPECS).`
3007
3156
  });
3008
3157
  }
3009
3158
  const i = g(t, "SCOPE_TYPE");
3010
- if (i.status === "ok" && !o) {
3011
- const a = Object.keys(ce).find(
3159
+ if (i.status === "ok" && !r) {
3160
+ const a = Object.keys(de).find(
3012
3161
  (c) => new RegExp(`\\b${c}\\b`).test(i.content)
3013
3162
  );
3014
3163
  if (a) {
3015
3164
  const c = new Set(
3016
3165
  [...t.matchAll(/<!--SECTION:([A-Z_]+)-->/g)].map((l) => l[1])
3017
3166
  );
3018
- for (const l of ce[a])
3167
+ for (const l of de[a])
3019
3168
  c.has(l) || n.push({
3020
3169
  severity: "error",
3021
3170
  code: "SDD_SPEC_SECTION_MISSING",
@@ -3028,30 +3177,30 @@ function Qo(e, t, s = "v1") {
3028
3177
  const a = new Set(
3029
3178
  [...t.matchAll(/<!--SECTION:([A-Z_]+)-->/g)].map((c) => c[1])
3030
3179
  );
3031
- if (o)
3032
- for (const c of it)
3180
+ if (r)
3181
+ for (const c of ut)
3033
3182
  a.has(c) || n.push({
3034
3183
  severity: "error",
3035
3184
  code: "SDD_SPEC_SECTION_MISSING",
3036
3185
  file: e,
3037
3186
  message: `module spec is missing required section ${c}.`
3038
3187
  });
3039
- if (r || o) {
3188
+ if (o || r) {
3040
3189
  const c = g(t, "OVERVIEW");
3041
3190
  c.status !== "ok" ? n.push({
3042
3191
  severity: "error",
3043
3192
  code: "SDD_NO_DIAGRAM_BLOCK",
3044
3193
  file: e,
3045
3194
  message: "Spec has no Overview section — every spec opens with an Overview carrying at least one diagram (AX_SPEC_MANDATORY_DIAGRAM)."
3046
- }) : en(c.content) || n.push({
3195
+ }) : an(c.content) || n.push({
3047
3196
  severity: "error",
3048
3197
  code: "SDD_DIAGRAM_BLOCK_EMPTY",
3049
3198
  file: e,
3050
3199
  message: "Overview section has no diagram — add at least one fenced mermaid or ASCII diagram (AX_SPEC_MANDATORY_DIAGRAM)."
3051
3200
  });
3052
3201
  }
3053
- if (o || r)
3054
- for (const c of le) {
3202
+ if (r || o)
3203
+ for (const c of ue) {
3055
3204
  const l = g(t, c);
3056
3205
  l.status === "ok" && !/<details[\s>]/i.test(l.content) && n.push({
3057
3206
  severity: "error",
@@ -3060,52 +3209,52 @@ function Qo(e, t, s = "v1") {
3060
3209
  message: `Section ${c} does not fold its detail under \`<details>\` — collapse the contract body so the summary stays readable (AX_SPEC_PROGRESSIVE_DISCLOSURE).`
3061
3210
  });
3062
3211
  }
3063
- if (o || r)
3212
+ if (r || o)
3064
3213
  for (const c of a) {
3065
- if (le.includes(c)) continue;
3214
+ if (ue.includes(c)) continue;
3066
3215
  const l = g(t, c);
3067
3216
  if (l.status !== "ok") continue;
3068
3217
  const f = l.content.split(`
3069
3218
  `).length;
3070
- f > ve && n.push({
3219
+ f > Pe && n.push({
3071
3220
  severity: "error",
3072
3221
  code: "SDD_SECTION_TOO_LONG",
3073
3222
  file: e,
3074
- message: `Section ${c} is ${f} lines (> ${ve}) — decompose (split into a module/sub-scope) or fold the reference detail into a foldable section (AX_SPEC_PROGRESSIVE_DISCLOSURE).`
3223
+ message: `Section ${c} is ${f} lines (> ${Pe}) — decompose (split into a module/sub-scope) or fold the reference detail into a foldable section (AX_SPEC_PROGRESSIVE_DISCLOSURE).`
3075
3224
  });
3076
3225
  }
3077
- n.push(...on(e, t));
3226
+ n.push(...un(e, t));
3078
3227
  }
3079
3228
  return n;
3080
3229
  }
3081
- function Me(e) {
3230
+ function xe(e) {
3082
3231
  return /^\|[\s:|-]+\|$/.test(e);
3083
3232
  }
3084
- function xe(e) {
3233
+ function Be(e) {
3085
3234
  return e.slice(1, -1).split("|").map((t) => t.trim()).filter((t) => t.length > 0);
3086
3235
  }
3087
- function on(e, t) {
3236
+ function un(e, t) {
3088
3237
  const s = [], n = t.split(`
3089
3238
  `);
3090
- let o = !1;
3091
- for (let r = 0; r < n.length; r++) {
3092
- const i = n[r].trim();
3239
+ let r = !1;
3240
+ for (let o = 0; o < n.length; o++) {
3241
+ const i = n[o].trim();
3093
3242
  if (i.startsWith("```")) {
3094
- o = !o;
3243
+ r = !r;
3095
3244
  continue;
3096
3245
  }
3097
- if (o || !i.startsWith("|") || !i.endsWith("|") || Me(i)) continue;
3098
- const a = (n[r + 1] ?? "").trim();
3099
- if (Me(a)) {
3100
- const c = xe(i).length;
3101
- c > Pe && s.push({
3246
+ if (r || !i.startsWith("|") || !i.endsWith("|") || xe(i)) continue;
3247
+ const a = (n[o + 1] ?? "").trim();
3248
+ if (xe(a)) {
3249
+ const c = Be(i).length;
3250
+ c > be && s.push({
3102
3251
  severity: "error",
3103
3252
  code: "SDD_TABLE_TOO_MANY_COLUMNS",
3104
3253
  file: e,
3105
- message: `Table header has ${c} columns (> ${Pe}) — a table is an index; split it or move detail into a subsection (AX_SPEC_TABLE_IS_INDEX).`
3254
+ message: `Table header has ${c} columns (> ${be}) — a table is an index; split it or move detail into a subsection (AX_SPEC_TABLE_IS_INDEX).`
3106
3255
  });
3107
3256
  }
3108
- for (const c of xe(i)) {
3257
+ for (const c of Be(i)) {
3109
3258
  if (/<br/i.test(c)) {
3110
3259
  s.push({
3111
3260
  severity: "error",
@@ -3115,12 +3264,12 @@ function on(e, t) {
3115
3264
  });
3116
3265
  continue;
3117
3266
  }
3118
- c.length > we ? s.push({
3267
+ c.length > Le ? s.push({
3119
3268
  severity: "error",
3120
3269
  code: "SDD_TABLE_CELL_TOO_LONG",
3121
3270
  file: e,
3122
- message: `Table cell is ${c.length} chars (> ${we}) — a cell is one short line; move the detail into a subsection below the table (AX_SPEC_TABLE_IS_INDEX): "${c.slice(0, 60)}..."`
3123
- }) : Js.test(c) && s.push({
3271
+ message: `Table cell is ${c.length} chars (> ${Le}) — a cell is one short line; move the detail into a subsection below the table (AX_SPEC_TABLE_IS_INDEX): "${c.slice(0, 60)}..."`
3272
+ }) : rn.test(c) && s.push({
3124
3273
  severity: "error",
3125
3274
  code: "SDD_TABLE_CELL_MULTI_SENTENCE",
3126
3275
  file: e,
@@ -3130,34 +3279,34 @@ function on(e, t) {
3130
3279
  }
3131
3280
  return s;
3132
3281
  }
3133
- function Jo(e) {
3282
+ function cr(e) {
3134
3283
  const t = g(e, "INTER_MODULE_DEPENDENCIES");
3135
- return t.status === "ok" ? js(t.content) : [];
3284
+ return t.status === "ok" ? Hs(t.content) : [];
3136
3285
  }
3137
- function rn(e) {
3286
+ function fn(e) {
3138
3287
  const t = /\*\*Depends on:\*\*\s*(.*)/i.exec(e);
3139
3288
  return t?.[1] ? [...t[1].matchAll(/[a-z][a-z0-9-]*\*?/gi)].map((s) => s[0]) : [];
3140
3289
  }
3141
- function an(e, t) {
3290
+ function pn(e, t) {
3142
3291
  return e.some((s) => s.endsWith("*") ? t.startsWith(s.slice(0, -1)) : s === t);
3143
3292
  }
3144
- function er(e, t, s) {
3293
+ function lr(e, t, s) {
3145
3294
  const n = g(t, "SCOPE_DEPENDENCIES");
3146
3295
  if (n.status !== "ok") return [];
3147
- const o = /([^/\\]+)\.(?:spec|1-spec)\.md$/.exec(e)?.[1];
3148
- if (!o) return [];
3149
- const r = rn(n.content), i = [];
3296
+ const r = /([^/\\]+)\.(?:spec|1-spec)\.md$/.exec(e)?.[1];
3297
+ if (!r) return [];
3298
+ const o = fn(n.content), i = [];
3150
3299
  for (const a of s)
3151
- a.from === o && !an(r, a.to) && i.push({
3300
+ a.from === r && !pn(o, a.to) && i.push({
3152
3301
  severity: "warn",
3153
3302
  code: "SDD_SCOPE_DEP_UNDECLARED",
3154
3303
  file: e,
3155
- message: `Portal Scope Graph has \`${o} --> ${a.to}\` but the scope spec's Scope Dependencies does not list ${a.to} (AX_SCOPE_GRAPH_DISCIPLINE). Add it under "Depends on" (a name or a \`prefix-*\` wildcard), or fix the portal graph.`
3304
+ message: `Portal Scope Graph has \`${r} --> ${a.to}\` but the scope spec's Scope Dependencies does not list ${a.to} (AX_SCOPE_GRAPH_DISCIPLINE). Add it under "Depends on" (a name or a \`prefix-*\` wildcard), or fix the portal graph.`
3156
3305
  });
3157
3306
  return i;
3158
3307
  }
3159
- function tr(e, t, s) {
3160
- return J(s) ? [
3308
+ function dr(e, t, s) {
3309
+ return te(s) ? [
3161
3310
  {
3162
3311
  severity: "error",
3163
3312
  code: "SDD_MODULE_DAG_CYCLE",
@@ -3166,47 +3315,47 @@ function tr(e, t, s) {
3166
3315
  }
3167
3316
  ] : [];
3168
3317
  }
3169
- function $e(e) {
3318
+ function Ue(e) {
3170
3319
  const t = /<!--SECTION:MODULE_VISION-->/.test(e), s = /<!--SECTION:SCOPE_TYPE-->/.test(e) && !t;
3171
3320
  return t ? "module" : s ? "scope" : "other";
3172
3321
  }
3173
- function cn(e, t) {
3322
+ function mn(e, t) {
3174
3323
  let s = w(w(e)), n = "";
3175
3324
  for (; s !== n; ) {
3176
- const o = h(s, `${G(s)}.spec.md`);
3177
- if (o !== e && t.has(o)) return o;
3325
+ const r = h(s, `${V(s)}.spec.md`);
3326
+ if (r !== e && t.has(r)) return r;
3178
3327
  n = s, s = w(s);
3179
3328
  }
3180
3329
  return null;
3181
3330
  }
3182
- function ln(e, t, s) {
3331
+ function En(e, t, s) {
3183
3332
  for (const n of e.matchAll(/\]\(([^)`#]+\.spec\.md)(?:#[^)]*)?\)/g)) {
3184
- const o = n[1];
3185
- if (o && y(t, o) === y(s)) return !0;
3333
+ const r = n[1];
3334
+ if (r && y(t, r) === y(s)) return !0;
3186
3335
  }
3187
3336
  return !1;
3188
3337
  }
3189
- function sr(e) {
3190
- const t = [], s = new Map(e.map((a) => [a.file, a])), n = new Set(e.map((a) => a.file)), o = e.filter((a) => $e(a.content) === "module"), r = /* @__PURE__ */ new Map();
3191
- for (const a of o) {
3192
- const c = cn(a.file, n);
3193
- c && r.set(a.file, c);
3338
+ function ur(e) {
3339
+ const t = [], s = new Map(e.map((a) => [a.file, a])), n = new Set(e.map((a) => a.file)), r = e.filter((a) => Ue(a.content) === "module"), o = /* @__PURE__ */ new Map();
3340
+ for (const a of r) {
3341
+ const c = mn(a.file, n);
3342
+ c && o.set(a.file, c);
3194
3343
  }
3195
- for (const a of o) {
3196
- const c = r.get(a.file);
3344
+ for (const a of r) {
3345
+ const c = o.get(a.file);
3197
3346
  if (!c) continue;
3198
3347
  const l = s.get(c);
3199
- l && (ln(l.content, w(c), a.file) || t.push({
3348
+ l && (En(l.content, w(c), a.file) || t.push({
3200
3349
  severity: a.flowVersion === "v2" ? "error" : "warn",
3201
3350
  code: "SDD_MODULE_NOT_IN_INDEX",
3202
3351
  file: c,
3203
3352
  message: `Module spec ${a.file} is not linked from its parent index ${c} — every module must appear in the parent's Module Map / links (AX_HIERARCHICAL_SPECS).`
3204
3353
  }));
3205
3354
  }
3206
- const i = new Set(r.values());
3355
+ const i = new Set(o.values());
3207
3356
  for (const a of i) {
3208
3357
  const c = s.get(a);
3209
- if (!(!c || $e(c.content) !== "module"))
3358
+ if (!(!c || Ue(c.content) !== "module"))
3210
3359
  for (const l of ["ENTITY_INVENTORY", "MODULE_CONTRACTS"])
3211
3360
  new RegExp(`<!--SECTION:${l}-->`).test(c.content) && t.push({
3212
3361
  severity: c.flowVersion === "v2" ? "error" : "warn",
@@ -3217,15 +3366,15 @@ function sr(e) {
3217
3366
  }
3218
3367
  return t;
3219
3368
  }
3220
- const dn = /^[ \t]*✚ /m;
3221
- function nr(e, t) {
3222
- const s = [], n = g(t, "CHANGE_MANIFEST"), o = n.status === "ok";
3223
- return dn.test(t) && !o && s.push({
3369
+ const hn = /^[ \t]*✚ /m;
3370
+ function fr(e, t) {
3371
+ const s = [], n = g(t, "CHANGE_MANIFEST"), r = n.status === "ok";
3372
+ return hn.test(t) && !r && s.push({
3224
3373
  severity: "error",
3225
3374
  code: "SDD_REVIEW_INCONSISTENT",
3226
3375
  file: e,
3227
3376
  message: "Found a ✚ change-mark but no CHANGE_MANIFEST — review-state is malformed (compress half-ran, or marks added without entering review-state). Add the manifest (CHANGE_MANIFEST_FORMAT) or strip the marks. AX_SPEC_LIFECYCLE."
3228
- }), o && (/ТИП ИЗМЕНЕНИЯ/.test(n.content) || s.push({
3377
+ }), r && (/ТИП ИЗМЕНЕНИЯ/.test(n.content) || s.push({
3229
3378
  severity: "error",
3230
3379
  code: "SDD_REVIEW_INCONSISTENT",
3231
3380
  file: e,
@@ -3237,35 +3386,35 @@ function nr(e, t) {
3237
3386
  message: "Spec is in review-state (CHANGE_MANIFEST present). Finalize it: once external review approves («no comments»), run compress — remove the manifest + ✚/~ marks; if the change was abandoned, remove the manifest. A spec must not linger in review-state. AX_SPEC_LIFECYCLE."
3238
3387
  })), s;
3239
3388
  }
3240
- let H = null;
3241
- async function un() {
3242
- if (H) return H;
3389
+ let q = null;
3390
+ async function Sn() {
3391
+ if (q) return q;
3243
3392
  const { JSDOM: e } = await import("jsdom"), t = new e("<!DOCTYPE html><html><body></body></html>"), s = globalThis;
3244
3393
  s.window ??= t.window, s.document ??= t.window.document, s.navigator ??= t.window.navigator;
3245
3394
  const n = (await import("mermaid")).default;
3246
- return n.initialize({ startOnLoad: !1 }), H = (o) => n.parse(o), H;
3395
+ return n.initialize({ startOnLoad: !1 }), q = (r) => n.parse(r), q;
3247
3396
  }
3248
- function fn(e) {
3397
+ function gn(e) {
3249
3398
  const t = [], s = e.split(`
3250
3399
  `);
3251
- let n = !1, o = [];
3252
- for (const r of s) {
3253
- const i = r.trim();
3400
+ let n = !1, r = [];
3401
+ for (const o of s) {
3402
+ const i = o.trim();
3254
3403
  if (!n && i.startsWith("```mermaid")) {
3255
- n = !0, o = [];
3404
+ n = !0, r = [];
3256
3405
  continue;
3257
3406
  }
3258
3407
  if (n && i === "```") {
3259
- t.push(o.join(`
3408
+ t.push(r.join(`
3260
3409
  `)), n = !1;
3261
3410
  continue;
3262
3411
  }
3263
- n && o.push(r);
3412
+ n && r.push(o);
3264
3413
  }
3265
3414
  return t;
3266
3415
  }
3267
- async function pn(e) {
3268
- const t = await un();
3416
+ async function In(e) {
3417
+ const t = await Sn();
3269
3418
  try {
3270
3419
  return await t(e), null;
3271
3420
  } catch (s) {
@@ -3273,129 +3422,38 @@ async function pn(e) {
3273
3422
  `)[0] ?? "invalid" : String(s);
3274
3423
  }
3275
3424
  }
3276
- async function or(e, t) {
3277
- const s = fn(t);
3425
+ async function pr(e, t) {
3426
+ const s = gn(t);
3278
3427
  if (s.length === 0) return [];
3279
3428
  const n = [];
3280
- for (const o of s) {
3281
- const r = await pn(o);
3282
- r !== null && n.push({
3429
+ for (const r of s) {
3430
+ const o = await In(r);
3431
+ o !== null && n.push({
3283
3432
  severity: "error",
3284
3433
  code: "SDD_DIAGRAM_INVALID",
3285
3434
  file: e,
3286
- message: `mermaid diagram does not parse: ${r}`
3435
+ message: `mermaid diagram does not parse: ${o}`
3287
3436
  });
3288
3437
  }
3289
3438
  return n;
3290
3439
  }
3291
- function at(e) {
3292
- const t = e.match(/\*{0,2}Task-ID:\*{0,2}\s*`?([A-Za-z0-9][A-Za-z0-9_-]*)`?/), s = e.match(/\*{0,2}Status:\*{0,2}\s*(\[.\]\s*[A-Z_]+)/);
3293
- return {
3294
- taskId: t?.[1] ?? null,
3295
- status: s?.[1] ?? null
3296
- };
3297
- }
3298
- function ct(e) {
3299
- return e.replace(/`/g, "").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").trim();
3300
- }
3301
- function V(e) {
3302
- return e.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((t) => t.trim());
3303
- }
3304
- function rr(e, t, s) {
3305
- const n = e.split(`
3306
- `), o = lt(n);
3307
- if (!o) return { ok: !1, reason: "no_table" };
3308
- const { headerIdx: r, idCol: i, statusCol: a } = o;
3309
- for (let c = r + 1; c < n.length; c++) {
3310
- const l = n[c];
3311
- if (l === void 0 || !l.trimStart().startsWith("|")) break;
3312
- const f = V(l);
3313
- if (/^\|?\s*-+\s*\|/.test(l) || ct(f[i] ?? "") !== t) continue;
3314
- const d = l.split("|"), u = a + 1;
3315
- if (d[u] === void 0) return { ok: !1, reason: "no_table" };
3316
- const p = d[u];
3317
- return d[u] = ` ${s} `, d[u] === p ? { ok: !0, text: e, changed: !1 } : (n[c] = d.join("|"), { ok: !0, text: n.join(`
3318
- `), changed: !0 });
3319
- }
3320
- return { ok: !1, reason: "task_not_found" };
3321
- }
3322
- function lt(e) {
3323
- for (let t = 0; t < e.length; t++) {
3324
- const s = e[t];
3325
- if (s === void 0 || !s.trimStart().startsWith("|")) continue;
3326
- const n = V(s).map((i) => i.toLowerCase()), o = n.indexOf("task-id"), r = n.indexOf("status");
3327
- if (o !== -1 && r !== -1) return { headerIdx: t, idCol: o, statusCol: r };
3328
- }
3329
- return null;
3330
- }
3331
- function ir(e) {
3332
- const t = e.split(`
3333
- `), s = lt(t);
3334
- if (!s) return [];
3335
- const n = [];
3336
- for (let o = s.headerIdx + 1; o < t.length; o++) {
3337
- const r = t[o];
3338
- if (r === void 0 || !r.trimStart().startsWith("|")) break;
3339
- if (/^\|?\s*-+\s*\|/.test(r)) continue;
3340
- const i = V(r), a = ct(i[s.idCol] ?? "");
3341
- a && n.push({ taskId: a, status: (i[s.statusCol] ?? "").trim() });
3342
- }
3343
- return n;
3344
- }
3345
- function mn(e) {
3346
- return /^\[x\]/i.test(e.trim());
3347
- }
3348
- function En(e) {
3349
- for (let t = 0; t < e.length; t++) {
3350
- const s = e[t];
3351
- if (s === void 0 || !s.trimStart().startsWith("|")) continue;
3352
- const n = V(s).map((a) => a.toLowerCase()), o = n.indexOf("index"), r = n.indexOf("tasks"), i = n.indexOf("done") !== -1 ? n.indexOf("done") : n.indexOf("progress");
3353
- if (o !== -1 && r !== -1 && i !== -1)
3354
- return { headerIdx: t, indexCol: o, tasksCol: r, doneCol: i };
3355
- }
3356
- return null;
3357
- }
3358
- function hn(e) {
3359
- return e.match(/\[[^\]]*\]\(([^)]+)\)/)?.[1] ?? null;
3360
- }
3361
- function ar(e, t) {
3362
- const s = e.split(`
3363
- `), n = En(s);
3364
- if (!n) return { text: e, updated: [] };
3365
- const o = [];
3366
- for (let r = n.headerIdx + 1; r < s.length; r++) {
3367
- const i = s[r];
3368
- if (i === void 0 || !i.trimStart().startsWith("|")) break;
3369
- if (/^\|?\s*-+\s*\|/.test(i)) continue;
3370
- const a = V(i), c = hn(a[n.indexCol] ?? "");
3371
- if (!c) continue;
3372
- const l = t(c);
3373
- if (!l) continue;
3374
- const f = l.filter((_) => mn(_.status)).length, d = l.length, u = i.split("|"), p = n.tasksCol + 1, m = n.doneCol + 1;
3375
- if (u[p] === void 0 || u[m] === void 0) continue;
3376
- const E = ` ${d} `, S = ` ${f}/${d} `;
3377
- u[p] === E && u[m] === S || (u[p] = E, u[m] = S, s[r] = u.join("|"), o.push(c));
3378
- }
3379
- return { text: s.join(`
3380
- `), updated: o };
3381
- }
3382
- function cr(e, t, s) {
3440
+ function mr(e, t, s) {
3383
3441
  const n = y(w(y(e)), s);
3384
3442
  return x(y(t), n).split(b).join("/");
3385
3443
  }
3386
- function lr(e) {
3444
+ function Er(e) {
3387
3445
  const t = /<DependsOn>([\s\S]*?)<\/DependsOn>/.exec(e);
3388
3446
  return t?.[1] ? [...t[1].matchAll(/^\s*-\s+(\S+)/gm)].map((s) => s[1]) : [];
3389
3447
  }
3390
- function dr(e, t, s, n) {
3448
+ function hr(e, t, s, n) {
3391
3449
  if (s.length === 0) return [];
3392
- const o = new Set(s), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = [...s];
3450
+ const r = new Set(s), o = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = [...s];
3393
3451
  for (; a.length; ) {
3394
3452
  const c = a.pop();
3395
- if (!r.has(c)) {
3396
- r.add(c);
3453
+ if (!o.has(c)) {
3454
+ o.add(c);
3397
3455
  for (const l of n.get(c) ?? [])
3398
- o.has(l) || i.add(l), r.has(l) || a.push(l);
3456
+ r.has(l) || i.add(l), o.has(l) || a.push(l);
3399
3457
  }
3400
3458
  }
3401
3459
  return [...i].map((c) => ({
@@ -3405,87 +3463,87 @@ function dr(e, t, s, n) {
3405
3463
  message: `Phase ${t}: rule dependency "${c}" is required transitively but is not in the phase's Rules: list — the closure over <DependsOn> is incomplete.`
3406
3464
  }));
3407
3465
  }
3408
- function Be(e) {
3466
+ function Fe(e) {
3409
3467
  const t = /@tasks:\s*(.+)/.exec(e);
3410
3468
  return t?.[1] ? t[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0 && !/^n\/a$/i.test(s)) : [];
3411
3469
  }
3412
- function ur(e, t, s) {
3470
+ function Sr(e, t, s) {
3413
3471
  if (s === null) return [];
3414
- const n = Be(s), o = new Set(Be(t)), r = n.filter((i) => !o.has(i));
3415
- return r.length === 0 ? [] : [
3472
+ const n = Fe(s), r = new Set(Fe(t)), o = n.filter((i) => !r.has(i));
3473
+ return o.length === 0 ? [] : [
3416
3474
  {
3417
3475
  severity: "error",
3418
3476
  code: "SDD_TASKS_APPEND_ONLY_REGRESSION",
3419
3477
  file: e,
3420
- message: `@tasks: header dropped previously-declared id(s): ${r.join(", ")} — the header is append-only, ids are never removed.`
3478
+ message: `@tasks: header dropped previously-declared id(s): ${o.join(", ")} — the header is append-only, ids are never removed.`
3421
3479
  }
3422
3480
  ];
3423
3481
  }
3424
- function Sn(e) {
3482
+ function On(e) {
3425
3483
  const t = [];
3426
3484
  let s = 0, n = 0;
3427
- for (let o = 0; o < e.length; o++) {
3428
- const r = e[o];
3429
- r === "(" ? s++ : r === ")" ? s = Math.max(0, s - 1) : r === "," && s === 0 && (t.push(e.slice(n, o).trim()), n = o + 1);
3485
+ for (let r = 0; r < e.length; r++) {
3486
+ const o = e[r];
3487
+ o === "(" ? s++ : o === ")" ? s = Math.max(0, s - 1) : o === "," && s === 0 && (t.push(e.slice(n, r).trim()), n = r + 1);
3430
3488
  }
3431
- return t.push(e.slice(n).trim()), t.filter((o) => o.length > 0);
3489
+ return t.push(e.slice(n).trim()), t.filter((r) => r.length > 0);
3432
3490
  }
3433
- function fr(e) {
3491
+ function gr(e) {
3434
3492
  const t = /@consumers:\s*(.+)/.exec(e);
3435
- return t?.[1] ? Sn(t[1]) : [];
3493
+ return t?.[1] ? On(t[1]) : [];
3436
3494
  }
3437
- function pr(e) {
3495
+ function Ir(e) {
3438
3496
  const t = e.trim(), s = t.replace(/\s*\([^)]*\)\s*$/, "").trim(), n = s.length === 0 || /\s/.test(s) || /\bexternal\b/i.test(t);
3439
3497
  return { raw: t, name: s, external: n };
3440
3498
  }
3441
- function mr(e, t, s) {
3499
+ function Or(e, t, s) {
3442
3500
  const n = [];
3443
- for (const o of t)
3444
- o.external || s.has(o.name) || n.push({
3501
+ for (const r of t)
3502
+ r.external || s.has(r.name) || n.push({
3445
3503
  severity: "warn",
3446
3504
  code: "SDD_CONSUMERS_UNRESOLVED",
3447
3505
  file: e,
3448
- message: `@consumers: entry "${o.name}" was not found referenced elsewhere in the codebase (text search) — mark it external in the description if it lives outside this repo, or fix the name.`
3506
+ message: `@consumers: entry "${r.name}" was not found referenced elsewhere in the codebase (text search) — mark it external in the description if it lives outside this repo, or fix the name.`
3449
3507
  });
3450
3508
  return n;
3451
3509
  }
3452
- function dt(e) {
3453
- const t = /^-\s*Deferred Test Ownership:\s*(\S+)\s*(.*)$/.exec(e), s = t?.[1] ?? null, n = t ? t[2] ?? "" : e.replace(/^-\s*/, ""), o = /^(.+?)\s*→\s*`([^`]+)`\s*::\s*(.+?)\.?\s*$/.exec(n);
3454
- if (!o) return null;
3455
- const r = (o[1] ?? "").replace(/`\[[^\]]+\]`|\[[^\]]+\]/g, "").trim(), i = (o[2] ?? "").trim(), a = [...(o[3] ?? "").matchAll(/`([^`]+)`/g)].map((c) => c[1]);
3456
- return !i || a.length === 0 ? null : { scenario: r, testFile: i, caseNames: a, deferred: s };
3510
+ function ft(e) {
3511
+ const t = /^-\s*Deferred Test Ownership:\s*(\S+)\s*(.*)$/.exec(e), s = t?.[1] ?? null, n = t ? t[2] ?? "" : e.replace(/^-\s*/, ""), r = /^(.+?)\s*→\s*`([^`]+)`\s*::\s*(.+?)\.?\s*$/.exec(n);
3512
+ if (!r) return null;
3513
+ const o = (r[1] ?? "").replace(/`\[[^\]]+\]`|\[[^\]]+\]/g, "").trim(), i = (r[2] ?? "").trim(), a = [...(r[3] ?? "").matchAll(/`([^`]+)`/g)].map((c) => c[1]);
3514
+ return !i || a.length === 0 ? null : { scenario: o, testFile: i, caseNames: a, deferred: s };
3457
3515
  }
3458
- function Er(e) {
3516
+ function Tr(e) {
3459
3517
  const t = [];
3460
3518
  for (const s of e.split(`
3461
3519
  `)) {
3462
3520
  const n = s.trim();
3463
3521
  if (!n.startsWith("-")) continue;
3464
- const o = dt(n);
3465
- o && t.push(o);
3522
+ const r = ft(n);
3523
+ r && t.push(r);
3466
3524
  }
3467
3525
  return t;
3468
3526
  }
3469
- function gn(e) {
3527
+ function Tn(e) {
3470
3528
  const t = [];
3471
3529
  for (const s of e.split(`
3472
3530
  `)) {
3473
3531
  const n = s.trim();
3474
- n.startsWith("-") && (dt(n) || t.push(n));
3532
+ n.startsWith("-") && (ft(n) || t.push(n));
3475
3533
  }
3476
3534
  return t;
3477
3535
  }
3478
- function hr(e) {
3536
+ function _r(e) {
3479
3537
  const t = [], s = /\b(?:it|test)(?:\.\w+)?\s*\(\s*(['"`])((?:\\.|(?!\1).)*)\1/g;
3480
3538
  for (const n of e.matchAll(s))
3481
3539
  n[2] !== void 0 && t.push(n[2]);
3482
3540
  return t;
3483
3541
  }
3484
- function Sr(e, t) {
3542
+ function Nr(e, t) {
3485
3543
  const s = t.replace(/\\/g, "/"), n = `/${s}`;
3486
- return e.filter((o) => o === s || o.endsWith(n));
3544
+ return e.filter((r) => r === s || r.endsWith(n));
3487
3545
  }
3488
- function gr(e, t, s) {
3546
+ function Cr(e, t, s) {
3489
3547
  return s.length <= 1 ? [] : [
3490
3548
  {
3491
3549
  severity: "warn",
@@ -3495,31 +3553,31 @@ function gr(e, t, s) {
3495
3553
  }
3496
3554
  ];
3497
3555
  }
3498
- function Ir(e, t, s, n = "v1", o = null) {
3499
- const r = [], i = n === "v2" ? "error" : "warn";
3556
+ function Dr(e, t, s, n = "v1", r = null) {
3557
+ const o = [], i = n === "v2" ? "error" : "warn";
3500
3558
  for (const a of t) {
3501
3559
  if (a.deferred !== null) {
3502
- o !== null && a.deferred === o && r.push({
3560
+ r !== null && a.deferred === r && o.push({
3503
3561
  severity: "error",
3504
3562
  code: "SDD_BDD_DEFERRED_TO_SELF",
3505
3563
  file: e,
3506
- message: `Scenario "${a.scenario}" defers test ownership to this ticket's own Task-ID (${o}) — that hides missing coverage instead of delegating it to another ticket.`
3564
+ message: `Scenario "${a.scenario}" defers test ownership to this ticket's own Task-ID (${r}) — that hides missing coverage instead of delegating it to another ticket.`
3507
3565
  });
3508
3566
  continue;
3509
3567
  }
3510
3568
  const c = s.get(a.testFile) ?? [];
3511
3569
  for (const l of a.caseNames)
3512
- c.includes(l) || r.push({
3570
+ c.includes(l) || o.push({
3513
3571
  severity: i,
3514
3572
  code: "SDD_BDD_SCENARIO_UNTESTED",
3515
3573
  file: e,
3516
3574
  message: `Scenario "${a.scenario}" claims case "${l}" in ${a.testFile}, but no it()/test() with that exact name was found there.`
3517
3575
  });
3518
3576
  }
3519
- return r;
3577
+ return o;
3520
3578
  }
3521
- function Or(e, t) {
3522
- return gn(t).map(
3579
+ function Ar(e, t) {
3580
+ return Tn(t).map(
3523
3581
  (s) => ({
3524
3582
  severity: "warn",
3525
3583
  code: "SDD_BDD_COVERAGE_ROW_UNPARSED",
@@ -3528,7 +3586,7 @@ function Or(e, t) {
3528
3586
  })
3529
3587
  );
3530
3588
  }
3531
- const Ee = ["PLANNED", "MAPPED", "APPROVED", "DONE"], de = ["keep", "rename", "merge", "split", "create", "drop"], K = "UNMAPPED", In = [
3589
+ const Se = ["PLANNED", "MAPPED", "APPROVED", "DONE"], fe = ["keep", "rename", "merge", "split", "create", "drop"], Z = "UNMAPPED", _n = [
3532
3590
  { match: /^scope-type$/i, section: "SCOPE_TYPE" },
3533
3591
  { match: /^vision(\s*&\s*primary goal)?$/i, section: "VISION" },
3534
3592
  { match: /^module vision$/i, section: "MODULE_VISION" },
@@ -3559,27 +3617,27 @@ const Ee = ["PLANNED", "MAPPED", "APPROVED", "DONE"], de = ["keep", "rename", "m
3559
3617
  { match: /^module contracts(\s*\(.*\))?$/i, section: "MODULE_CONTRACTS" },
3560
3618
  { match: /^public options(\s*&\s*policies)?$/i, section: "PUBLIC_OPTIONS" }
3561
3619
  ];
3562
- function On(e) {
3620
+ function Nn(e) {
3563
3621
  const t = e.replace(/^#{2,3}\s*/, "").replace(/^\d+(\.\d+)*\.?\s+/, "").trim();
3564
- for (const s of In)
3622
+ for (const s of _n)
3565
3623
  if (s.match.test(t)) return s.section;
3566
- return K;
3624
+ return Z;
3567
3625
  }
3568
- const Tn = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", "out", "coverage"]);
3569
- function ue(e, t, s) {
3626
+ const Cn = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", "out", "coverage"]);
3627
+ function pe(e, t, s) {
3570
3628
  let n;
3571
3629
  try {
3572
- n = $(e, { withFileTypes: !0 });
3630
+ n = B(e, { withFileTypes: !0 });
3573
3631
  } catch {
3574
3632
  return;
3575
3633
  }
3576
- for (const o of n) {
3577
- if (o.name.startsWith(".") || Tn.has(o.name) || o.isSymbolicLink()) continue;
3578
- const r = h(e, o.name);
3579
- o.isDirectory() ? ue(r, t, s) : o.isFile() && t(o.name) && s.push(r);
3634
+ for (const r of n) {
3635
+ if (r.name.startsWith(".") || Cn.has(r.name) || r.isSymbolicLink()) continue;
3636
+ const o = h(e, r.name);
3637
+ r.isDirectory() ? pe(o, t, s) : r.isFile() && t(r.name) && s.push(o);
3580
3638
  }
3581
3639
  }
3582
- function _n(e) {
3640
+ function Dn(e) {
3583
3641
  const t = [];
3584
3642
  let s = !1;
3585
3643
  for (const n of e.split(`
@@ -3592,42 +3650,42 @@ function _n(e) {
3592
3650
  }
3593
3651
  return t;
3594
3652
  }
3595
- function Nn(e) {
3653
+ function An(e) {
3596
3654
  const t = /* @__PURE__ */ new Set();
3597
3655
  for (const s of e.matchAll(/<!--SECTION:([A-Z][A-Z0-9_]*)-->/g))
3598
3656
  s[1] && t.add(s[1]);
3599
3657
  return [...t];
3600
3658
  }
3601
- function Cn(e) {
3659
+ function yn(e) {
3602
3660
  const t = g(e, "SCOPE_TYPE");
3603
3661
  return t.status !== "ok" ? null : /\b(product|library|infrastructure|interface)\b/.exec(t.content)?.[1] ?? null;
3604
3662
  }
3605
- function Dn(e, t) {
3663
+ function Rn(e, t) {
3606
3664
  let s = "";
3607
3665
  try {
3608
- s = D(t, "utf-8");
3666
+ s = C(t, "utf-8");
3609
3667
  } catch {
3610
3668
  }
3611
- const n = g(s, "META"), o = n.status === "ok" ? n.content : /##[^\n]*\bMeta\b[^\n]*\n([\s\S]*?)(?=\n## |$)/.exec(s)?.[1] ?? "", r = at(o), i = /\*{0,2}Purpose:\*{0,2}\s*([^\n]+)/.exec(o)?.[1]?.trim() ?? null, a = /\*{0,2}Scope:\*{0,2}\s*`?([\w./-]+)`?/.exec(o)?.[1] ?? null, c = /\*{0,2}Module:\*{0,2}\s*`?([\w./-]+)`?/.exec(o)?.[1] ?? null;
3669
+ const n = g(s, "META"), r = n.status === "ok" ? n.content : /##[^\n]*\bMeta\b[^\n]*\n([\s\S]*?)(?=\n## |$)/.exec(s)?.[1] ?? "", o = nt(r), i = /\*{0,2}Purpose:\*{0,2}\s*([^\n]+)/.exec(r)?.[1]?.trim() ?? null, a = /\*{0,2}Scope:\*{0,2}\s*`?([\w./-]+)`?/.exec(r)?.[1] ?? null, c = /\*{0,2}Module:\*{0,2}\s*`?([\w./-]+)`?/.exec(r)?.[1] ?? null;
3612
3670
  return {
3613
3671
  ticket: {
3614
3672
  file: x(e, t),
3615
- taskId: r.taskId,
3616
- status: r.status,
3673
+ taskId: o.taskId,
3674
+ status: o.status,
3617
3675
  purpose: i
3618
3676
  },
3619
3677
  scope: a,
3620
3678
  module: c
3621
3679
  };
3622
3680
  }
3623
- function he(e) {
3681
+ function ge(e) {
3624
3682
  const t = h(e, "specs"), s = [];
3625
- ue(t, (i) => i.endsWith(".spec.md") || i.endsWith(".1-spec.md"), s), s.sort();
3683
+ pe(t, (i) => i.endsWith(".spec.md") || i.endsWith(".1-spec.md"), s), s.sort();
3626
3684
  const n = [];
3627
3685
  for (const i of s) {
3628
3686
  const a = x(e, i), c = a.split(b), l = c[1];
3629
3687
  if (!l || c.length < 3) continue;
3630
- const f = c.length >= 4 ? c[c.length - 2] ?? null : null, d = D(i, "utf-8"), u = f !== null, p = Cn(d), m = u ? ["MODULE_VISION", "OVERVIEW", ...it.filter((E) => E !== "MODULE_VISION")] : ["OVERVIEW", ...p ? ce[p] ?? [] : []];
3688
+ const f = c.length >= 4 ? c[c.length - 2] ?? null : null, d = C(i, "utf-8"), u = f !== null, p = yn(d), m = u ? ["MODULE_VISION", "OVERVIEW", ...ut.filter((E) => E !== "MODULE_VISION")] : ["OVERVIEW", ...p ? de[p] ?? [] : []];
3631
3689
  n.push({
3632
3690
  specFile: a,
3633
3691
  scope: l,
@@ -3636,27 +3694,27 @@ function he(e) {
3636
3694
  lines: d.split(`
3637
3695
  `).length,
3638
3696
  mermaidCount: (d.match(/^\s*```mermaid/gm) ?? []).length,
3639
- anchors: Nn(d),
3640
- headings: _n(d),
3697
+ anchors: An(d),
3698
+ headings: Dn(d),
3641
3699
  tickets: [],
3642
3700
  targetSections: [...new Set(m)],
3643
- foldSections: u ? [...le] : []
3701
+ foldSections: u ? [...ue] : []
3644
3702
  });
3645
3703
  }
3646
- const o = [];
3647
- ue(h(e, "tasks"), (i) => /\.task-[0-9]+\.md$/.test(i), o), o.sort();
3648
3704
  const r = [];
3649
- for (const i of o) {
3650
- const a = x(e, i), c = a.split(b)[1] ?? "", { ticket: l, scope: f, module: d } = Dn(e, i), u = a.split(b).length >= 4 ? a.split(b)[2] : null, p = n.filter((I) => I.scope === c), m = d ? p.find((I) => I.module === d) : void 0, E = u ? p.find((I) => I.module === u) : void 0, S = f ? p.find((I) => I.module === f) : void 0, _ = p.find((I) => I.module === null), N = m ?? E ?? S ?? _;
3651
- N ? N.tickets.push(l) : r.push(l);
3705
+ pe(h(e, "tasks"), (i) => /\.task-[0-9]+\.md$/.test(i), r), r.sort();
3706
+ const o = [];
3707
+ for (const i of r) {
3708
+ const a = x(e, i), c = a.split(b)[1] ?? "", { ticket: l, scope: f, module: d } = Rn(e, i), u = a.split(b).length >= 4 ? a.split(b)[2] : null, p = n.filter((I) => I.scope === c), m = d ? p.find((I) => I.module === d) : void 0, E = u ? p.find((I) => I.module === u) : void 0, S = f ? p.find((I) => I.module === f) : void 0, _ = p.find((I) => I.module === null), N = m ?? E ?? S ?? _;
3709
+ N ? N.tickets.push(l) : o.push(l);
3652
3710
  }
3653
- return { units: n, orphanTickets: r };
3711
+ return { units: n, orphanTickets: o };
3654
3712
  }
3655
- function ee(e) {
3656
- const t = w(e.specFile).split(b).slice(1).join(b), s = G(e.specFile).replace(/\.md$/, ".migration.md");
3713
+ function se(e) {
3714
+ const t = w(e.specFile).split(b).slice(1).join(b), s = V(e.specFile).replace(/\.md$/, ".migration.md");
3657
3715
  return h("migration", t, s);
3658
3716
  }
3659
- function ut(e) {
3717
+ function pt(e) {
3660
3718
  const t = [
3661
3719
  "## Inventory",
3662
3720
  "",
@@ -3677,29 +3735,29 @@ function ut(e) {
3677
3735
  return e.tickets.length === 0 && t.push(" - (нет)"), t.join(`
3678
3736
  `);
3679
3737
  }
3680
- function An(e) {
3738
+ function kn(e) {
3681
3739
  const t = [
3682
3740
  "## Section Map",
3683
3741
  "",
3684
3742
  "<!-- Предзаполнено `sdd-migrate plan` по курируемым правилам (mapHeadingToSection). Агент правит",
3685
3743
  " только строки с целью UNMAPPED — остальные пересматривает лишь если правило ошиблось.",
3686
- ` Действия: ${de.join(" | ")}. Каждая обязательная целевая секция должна появиться в колонке «Цель».`,
3744
+ ` Действия: ${fe.join(" | ")}. Каждая обязательная целевая секция должна появиться в колонке «Цель».`,
3687
3745
  " Полный целевой порядок секций — в format-файле структуры (ai/directives/sdd-v2/formats/*-spec-structure.xml). -->",
3688
3746
  "",
3689
3747
  "| Источник | Действие | Цель (SECTION) | Комментарий |",
3690
3748
  "|---|---|---|---|"
3691
3749
  ], s = /* @__PURE__ */ new Set();
3692
3750
  for (const n of e.headings) {
3693
- const o = On(n);
3694
- o === K ? t.push(`| \`${n}\` | ? | ${K} | не распознано правилом — решает агент |`) : (s.add(o), t.push(`| \`${n}\` | keep | ${o} | предзаполнено правилом |`));
3751
+ const r = Nn(n);
3752
+ r === Z ? t.push(`| \`${n}\` | ? | ${Z} | не распознано правилом — решает агент |`) : (s.add(r), t.push(`| \`${n}\` | keep | ${r} | предзаполнено правилом |`));
3695
3753
  }
3696
3754
  for (const n of e.targetSections)
3697
3755
  s.has(n) || t.push(`| — | create | ${n} | если не покрыта строками выше — создать |`);
3698
3756
  return t.join(`
3699
3757
  `);
3700
3758
  }
3701
- function yn(e) {
3702
- const t = G(e.specFile).replace(/\.(1-spec|spec)\.md$/, ""), n = [
3759
+ function vn(e) {
3760
+ const t = V(e.specFile).replace(/\.(1-spec|spec)\.md$/, ""), n = [
3703
3761
  "## Ticket Map",
3704
3762
  "",
3705
3763
  "<!-- Новый ID: `<ACR>-<slug>` — kebab-case, слаг из Meta.Purpose, уникален в рамках всего репо.",
@@ -3708,11 +3766,11 @@ function yn(e) {
3708
3766
  "| Файл | Task-ID | Новый ID | Назначение |",
3709
3767
  "|---|---|---|---|"
3710
3768
  ];
3711
- for (const o of e.tickets) n.push(`| \`${o.file}\` | ${o.taskId ?? "—"} | ? | ? |`);
3769
+ for (const r of e.tickets) n.push(`| \`${r.file}\` | ${r.taskId ?? "—"} | ? | ? |`);
3712
3770
  return e.tickets.length === 0 && n.push("| (нет тикетов) | — | — | — |"), n.join(`
3713
3771
  `);
3714
3772
  }
3715
- function Rn(e) {
3773
+ function wn(e) {
3716
3774
  return [
3717
3775
  "## Diagram Plan",
3718
3776
  "",
@@ -3725,7 +3783,7 @@ function Rn(e) {
3725
3783
  ].join(`
3726
3784
  `);
3727
3785
  }
3728
- function kn(e) {
3786
+ function Pn(e) {
3729
3787
  return [
3730
3788
  "## Steps",
3731
3789
  "",
@@ -3742,37 +3800,37 @@ function kn(e) {
3742
3800
  ].join(`
3743
3801
  `);
3744
3802
  }
3745
- function Tr(e) {
3803
+ function yr(e) {
3746
3804
  return [
3747
3805
  `# План миграции: ${e.specFile}`,
3748
3806
  "",
3749
- `- **Status:** PLANNED <!-- ${Ee.join(" → ")} -->`,
3807
+ `- **Status:** PLANNED <!-- ${Se.join(" → ")} -->`,
3750
3808
  `- **Scope:** ${e.scope}${e.module ? ` | **Module:** ${e.module}` : ""}`,
3751
3809
  "",
3752
3810
  "<!--SECTION:INVENTORY-->",
3753
- ut(e),
3811
+ pt(e),
3754
3812
  "<!--/SECTION:INVENTORY-->",
3755
3813
  "",
3756
3814
  "<!--SECTION:SECTION_MAP-->",
3757
- An(e),
3815
+ kn(e),
3758
3816
  "<!--/SECTION:SECTION_MAP-->",
3759
3817
  "",
3760
3818
  "<!--SECTION:TICKET_MAP-->",
3761
- yn(e),
3819
+ vn(e),
3762
3820
  "<!--/SECTION:TICKET_MAP-->",
3763
3821
  "",
3764
3822
  "<!--SECTION:DIAGRAM_PLAN-->",
3765
- Rn(e),
3823
+ wn(e),
3766
3824
  "<!--/SECTION:DIAGRAM_PLAN-->",
3767
3825
  "",
3768
3826
  "<!--SECTION:STEPS-->",
3769
- kn(e),
3827
+ Pn(e),
3770
3828
  "<!--/SECTION:STEPS-->",
3771
3829
  ""
3772
3830
  ].join(`
3773
3831
  `);
3774
3832
  }
3775
- function _r(e) {
3833
+ function Rr(e) {
3776
3834
  const t = [
3777
3835
  "# Миграция v1 → v2 — план",
3778
3836
  "",
@@ -3796,7 +3854,7 @@ function _r(e) {
3796
3854
  "|---|---|---|"
3797
3855
  ];
3798
3856
  for (const s of e.units)
3799
- t.push(`| \`${ee(s)}\` | \`${s.specFile}\` | ${s.tickets.length} |`);
3857
+ t.push(`| \`${se(s)}\` | \`${s.specFile}\` | ${s.tickets.length} |`);
3800
3858
  if (e.orphanTickets.length > 0) {
3801
3859
  t.push("", "## ⚠ Тикеты без юнита", ""), t.push("Их scope не имеет спеки — решить с оператором до старта:", "");
3802
3860
  for (const s of e.orphanTickets) t.push(`- \`${s.file}\` (${s.taskId ?? "—"})`);
@@ -3804,14 +3862,14 @@ function _r(e) {
3804
3862
  return t.push(""), t.join(`
3805
3863
  `);
3806
3864
  }
3807
- function vn(e) {
3865
+ function Ln(e) {
3808
3866
  const s = /\*\*Status:\*\*\s*([A-Z]+)/.exec(e)?.[1];
3809
- return s && Ee.includes(s) ? s : null;
3867
+ return s && Se.includes(s) ? s : null;
3810
3868
  }
3811
- function wn(e) {
3869
+ function bn(e) {
3812
3870
  return e.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((t) => t.trim());
3813
3871
  }
3814
- function X(e) {
3872
+ function z(e) {
3815
3873
  const t = [];
3816
3874
  let s = !1;
3817
3875
  for (const n of e.split(`
@@ -3821,67 +3879,67 @@ function X(e) {
3821
3879
  s = !0;
3822
3880
  continue;
3823
3881
  }
3824
- /^\|?\s*-+\s*\|/.test(n) || t.push(wn(n));
3882
+ /^\|?\s*-+\s*\|/.test(n) || t.push(bn(n));
3825
3883
  }
3826
3884
  return t;
3827
3885
  }
3828
- function C(e) {
3886
+ function D(e) {
3829
3887
  return e.replace(/^`|`$/g, "").trim();
3830
3888
  }
3831
- const ft = /^[A-Z][A-Z0-9]*(-[a-z0-9]+)+$/;
3832
- function Ue(e) {
3889
+ const mt = /^[A-Z][A-Z0-9]*(-[a-z0-9]+)+$/;
3890
+ function Ge(e) {
3833
3891
  return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3834
3892
  }
3835
- function Pn(e, t, s) {
3836
- const n = [], o = (d, u) => {
3893
+ function Mn(e, t, s) {
3894
+ const n = [], r = (d, u) => {
3837
3895
  n.push({ severity: "error", code: d, file: e, message: u });
3838
- }, r = vn(t);
3839
- if (r === null)
3840
- return o(
3896
+ }, o = Ln(t);
3897
+ if (o === null)
3898
+ return r(
3841
3899
  "MIG_STATUS_INVALID",
3842
- `Строка **Status:** отсутствует или несёт неизвестный токен — допустимо: ${Ee.join(" / ")}.`
3900
+ `Строка **Status:** отсутствует или несёт неизвестный токен — допустимо: ${Se.join(" / ")}.`
3843
3901
  ), n;
3844
- const i = r !== "PLANNED", a = g(t, "INVENTORY");
3845
- a.status !== "ok" ? o("MIG_INVENTORY_MISSING", "Секция INVENTORY отсутствует или разбалансирована.") : a.content.trim() !== ut(s).trim() && o(
3902
+ const i = o !== "PLANNED", a = g(t, "INVENTORY");
3903
+ a.status !== "ok" ? r("MIG_INVENTORY_MISSING", "Секция INVENTORY отсутствует или разбалансирована.") : a.content.trim() !== pt(s).trim() && r(
3846
3904
  "MIG_INVENTORY_DRIFT",
3847
3905
  "Inventory разошёлся с реальностью (спека или тикеты изменились после генерации плана) — перегенерируй юнит: sdd-migrate plan --all --write."
3848
3906
  );
3849
3907
  const c = g(t, "SECTION_MAP");
3850
3908
  if (c.status !== "ok")
3851
- o("MIG_SECTION_MAP_MISSING", "Секция SECTION_MAP отсутствует или разбалансирована.");
3909
+ r("MIG_SECTION_MAP_MISSING", "Секция SECTION_MAP отсутствует или разбалансирована.");
3852
3910
  else {
3853
- const d = X(c.content), p = d.filter((m) => C(m[0] ?? "") !== "—").map((m) => C(m[0] ?? ""));
3911
+ const d = z(c.content), p = d.filter((m) => D(m[0] ?? "") !== "—").map((m) => D(m[0] ?? ""));
3854
3912
  for (const m of s.headings) {
3855
3913
  const E = p.filter((S) => S === m).length;
3856
- E === 0 && o("MIG_SECTION_UNMAPPED", `Заголовок из Inventory без строки в Section Map: \`${m}\`.`), E > 1 && o(
3914
+ E === 0 && r("MIG_SECTION_UNMAPPED", `Заголовок из Inventory без строки в Section Map: \`${m}\`.`), E > 1 && r(
3857
3915
  "MIG_SECTION_DUPLICATED",
3858
3916
  `Заголовок отображён ${E} раз(а): \`${m}\` — нужна ровно одна строка.`
3859
3917
  );
3860
3918
  }
3861
3919
  for (const m of p)
3862
- s.headings.includes(m) || o(
3920
+ s.headings.includes(m) || r(
3863
3921
  "MIG_SECTION_UNKNOWN",
3864
3922
  `Строка Section Map ссылается на несуществующий заголовок: \`${m}\`.`
3865
3923
  );
3866
3924
  for (const m of d)
3867
- C(m[2] ?? "") === K && o(
3925
+ D(m[2] ?? "") === Z && r(
3868
3926
  "MIG_SECTION_UNMAPPED_TARGET",
3869
- `Заголовок «${C(m[0] ?? "")}» остался нераспознанным (UNMAPPED) — реши действие и цель вручную.`
3927
+ `Заголовок «${D(m[0] ?? "")}» остался нераспознанным (UNMAPPED) — реши действие и цель вручную.`
3870
3928
  );
3871
3929
  for (const m of d) {
3872
3930
  const E = (m[1] ?? "").trim();
3873
- de.includes(E) || !i && E === "?" || o(
3931
+ fe.includes(E) || !i && E === "?" || r(
3874
3932
  "MIG_BAD_ACTION",
3875
- `Недопустимое действие «${E}» — словарь: ${de.join(" | ")}${i ? "" : " (или ? до заполнения)"}.`
3876
- ), i && (m[2] ?? "").trim() === "?" && o(
3933
+ `Недопустимое действие «${E}» — словарь: ${fe.join(" | ")}${i ? "" : " (или ? до заполнения)"}.`
3934
+ ), i && (m[2] ?? "").trim() === "?" && r(
3877
3935
  "MIG_TARGET_UNSET",
3878
- `Цель не заполнена для строки «${C(m[0] ?? "")}» при Status ≥ MAPPED.`
3936
+ `Цель не заполнена для строки «${D(m[0] ?? "")}» при Status ≥ MAPPED.`
3879
3937
  );
3880
3938
  }
3881
3939
  if (i) {
3882
3940
  const m = d.map((E) => (E[2] ?? "").trim());
3883
3941
  for (const E of s.targetSections)
3884
- m.includes(E) || o(
3942
+ m.includes(E) || r(
3885
3943
  "MIG_TARGET_MISSING",
3886
3944
  `Обязательная целевая секция не производится ни одной строкой: \`${E}\`.`
3887
3945
  );
@@ -3889,82 +3947,82 @@ function Pn(e, t, s) {
3889
3947
  }
3890
3948
  const l = g(t, "TICKET_MAP");
3891
3949
  if (l.status !== "ok")
3892
- o("MIG_TICKET_MAP_MISSING", "Секция TICKET_MAP отсутствует или разбалансирована.");
3950
+ r("MIG_TICKET_MAP_MISSING", "Секция TICKET_MAP отсутствует или разбалансирована.");
3893
3951
  else {
3894
- const d = X(l.content).filter((p) => C(p[0] ?? "") !== "(нет тикетов)"), u = d.map((p) => C(p[0] ?? ""));
3952
+ const d = z(l.content).filter((p) => D(p[0] ?? "") !== "(нет тикетов)"), u = d.map((p) => D(p[0] ?? ""));
3895
3953
  for (const p of s.tickets)
3896
- u.includes(p.file) || o("MIG_TICKET_UNMAPPED", `Тикет из Inventory без строки в Ticket Map: \`${p.file}\`.`);
3954
+ u.includes(p.file) || r("MIG_TICKET_UNMAPPED", `Тикет из Inventory без строки в Ticket Map: \`${p.file}\`.`);
3897
3955
  for (const p of d) {
3898
- const m = C(p[0] ?? "");
3956
+ const m = D(p[0] ?? "");
3899
3957
  if (!s.tickets.find((I) => I.file === m)) {
3900
- o(
3958
+ r(
3901
3959
  "MIG_TICKET_UNKNOWN",
3902
3960
  `Строка Ticket Map ссылается на несуществующий тикет: \`${m}\`.`
3903
3961
  );
3904
3962
  continue;
3905
3963
  }
3906
- const S = C(p[1] ?? "");
3907
- (S === "" || S === "—") && o(
3964
+ const S = D(p[1] ?? "");
3965
+ (S === "" || S === "—") && r(
3908
3966
  "MIG_TICKET_ID_UNREADABLE",
3909
3967
  `Старый Task-ID не прочитан из тикета \`${m}\` (parseMeta вернул null — проверь формат строки Task-ID в Meta) — заменять нечего, sdd-migrate ids промолчит.`
3910
3968
  );
3911
- const _ = C(p[2] ?? ""), N = C(p[3] ?? "");
3912
- i && (ft.test(_) ? new RegExp(
3913
- `^specs/${Ue(s.scope)}/.*\\.task\\.${Ue(_)}\\.md$`
3914
- ).test(N.split(b).join("/")) || o(
3969
+ const _ = D(p[2] ?? ""), N = D(p[3] ?? "");
3970
+ i && (mt.test(_) ? new RegExp(
3971
+ `^specs/${Ge(s.scope)}/.*\\.task\\.${Ge(_)}\\.md$`
3972
+ ).test(N.split(b).join("/")) || r(
3915
3973
  "MIG_BAD_DESTINATION",
3916
3974
  `Назначение «${N}» не подходит форме \`specs/${s.scope}/**/*.task.${_}.md\` — тикет \`${m}\`.`
3917
- ) : o(
3975
+ ) : r(
3918
3976
  "MIG_BAD_SLUG",
3919
3977
  `Новый ID «${_}» не соответствует грамматике \`<ACR>-<slug>\` (ACR — верхний регистр, slug — kebab-case, ≥ 2 слова) — тикет \`${m}\`.`
3920
3978
  ));
3921
3979
  }
3922
3980
  }
3923
3981
  const f = g(t, "DIAGRAM_PLAN");
3924
- return f.status !== "ok" ? o("MIG_DIAGRAM_PLAN_MISSING", "Секция DIAGRAM_PLAN отсутствует или разбалансирована.") : i && /Overview-диаграмма:\s*\?/.test(f.content) && o(
3982
+ return f.status !== "ok" ? r("MIG_DIAGRAM_PLAN_MISSING", "Секция DIAGRAM_PLAN отсутствует или разбалансирована.") : i && /Overview-диаграмма:\s*\?/.test(f.content) && r(
3925
3983
  "MIG_DIAGRAM_PLAN_EMPTY",
3926
3984
  "Diagram Plan не заполнен (Overview-диаграмма: ?) при Status ≥ MAPPED."
3927
3985
  ), n;
3928
3986
  }
3929
- function Nr(e) {
3930
- const t = [], s = he(e), n = /* @__PURE__ */ new Map();
3931
- for (const o of s.units) {
3932
- const r = ee(o), i = h(e, r);
3987
+ function kr(e) {
3988
+ const t = [], s = ge(e), n = /* @__PURE__ */ new Map();
3989
+ for (const r of s.units) {
3990
+ const o = se(r), i = h(e, o);
3933
3991
  if (!R(i)) {
3934
3992
  t.push({
3935
3993
  severity: "error",
3936
3994
  code: "MIG_UNIT_FILE_MISSING",
3937
- file: r,
3938
- message: `Нет файла плана для спеки \`${o.specFile}\` — сгенерируй: sdd-migrate plan --all --write.`
3995
+ file: o,
3996
+ message: `Нет файла плана для спеки \`${r.specFile}\` — сгенерируй: sdd-migrate plan --all --write.`
3939
3997
  });
3940
3998
  continue;
3941
3999
  }
3942
- const a = D(i, "utf-8");
3943
- t.push(...Pn(r, a, o));
4000
+ const a = C(i, "utf-8");
4001
+ t.push(...Mn(o, a, r));
3944
4002
  const c = g(a, "TICKET_MAP");
3945
4003
  if (c.status === "ok")
3946
- for (const l of X(c.content)) {
3947
- const f = C(l[2] ?? "");
3948
- if (!ft.test(f)) continue;
4004
+ for (const l of z(c.content)) {
4005
+ const f = D(l[2] ?? "");
4006
+ if (!mt.test(f)) continue;
3949
4007
  const d = n.get(f);
3950
- d && d !== r ? t.push({
4008
+ d && d !== o ? t.push({
3951
4009
  severity: "error",
3952
4010
  code: "MIG_SLUG_COLLISION",
3953
- file: r,
4011
+ file: o,
3954
4012
  message: `Новый ID «${f}» уже занят в \`${d}\` — слаг уникален в рамках репо.`
3955
- }) : n.set(f, r);
4013
+ }) : n.set(f, o);
3956
4014
  }
3957
4015
  }
3958
- for (const o of s.orphanTickets)
4016
+ for (const r of s.orphanTickets)
3959
4017
  t.push({
3960
4018
  severity: "error",
3961
4019
  code: "MIG_TICKET_ORPHAN",
3962
- file: o.file,
4020
+ file: r.file,
3963
4021
  message: "Тикет без юнита: его scope не имеет спеки — решить с оператором до миграции."
3964
4022
  });
3965
4023
  return t;
3966
4024
  }
3967
- const pt = ["specs", "tasks", "cli", "shared", "services", "ai", "e2e"], Ln = /* @__PURE__ */ new Set([
4025
+ const Et = ["specs", "tasks", "cli", "shared", "services", "ai", "e2e"], $n = /* @__PURE__ */ new Set([
3968
4026
  ".md",
3969
4027
  ".ts",
3970
4028
  ".tsx",
@@ -3979,48 +4037,48 @@ const pt = ["specs", "tasks", "cli", "shared", "services", "ai", "e2e"], Ln = /*
3979
4037
  ".sh",
3980
4038
  ".hbs",
3981
4039
  ".txt"
3982
- ]), bn = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", "out", "coverage"]), Z = /^[A-Za-z][A-Za-z0-9_-]*$/;
3983
- function Cr(e) {
3984
- const t = [], s = [], n = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Set();
4040
+ ]), xn = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", "out", "coverage"]), Q = /^[A-Za-z][A-Za-z0-9_-]*$/;
4041
+ function vr(e) {
4042
+ const t = [], s = [], n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
3985
4043
  e.split(`
3986
- `).forEach((r, i) => {
3987
- const a = r.trim();
4044
+ `).forEach((o, i) => {
4045
+ const a = o.trim();
3988
4046
  if (a === "" || a.startsWith("#")) return;
3989
- const c = r.split(" ").map((d) => d.trim()), [l, f] = c;
4047
+ const c = o.split(" ").map((d) => d.trim()), [l, f] = c;
3990
4048
  if (c.length !== 2 || !l || !f) {
3991
4049
  t.push(`строка ${i + 1}: ожидаю ровно две TAB-колонки \`<old>\\t<new>\``);
3992
4050
  return;
3993
4051
  }
3994
- Z.test(l) || t.push(`строка ${i + 1}: old «${l}» вне грамматики ID`), Z.test(f) || t.push(`строка ${i + 1}: new «${f}» вне грамматики ID`), l === f && t.push(`строка ${i + 1}: old и new совпадают («${l}»)`), n.has(l) && t.push(`строка ${i + 1}: old «${l}» встречается повторно`), o.has(f) && t.push(`строка ${i + 1}: new «${f}» встречается повторно`), n.add(l), o.add(f), s.push({ old: l, next: f });
4052
+ Q.test(l) || t.push(`строка ${i + 1}: old «${l}» вне грамматики ID`), Q.test(f) || t.push(`строка ${i + 1}: new «${f}» вне грамматики ID`), l === f && t.push(`строка ${i + 1}: old и new совпадают («${l}»)`), n.has(l) && t.push(`строка ${i + 1}: old «${l}» встречается повторно`), r.has(f) && t.push(`строка ${i + 1}: new «${f}» встречается повторно`), n.add(l), r.add(f), s.push({ old: l, next: f });
3995
4053
  });
3996
- for (const r of s)
3997
- n.has(r.next) && t.push(
3998
- `цепочка: new «${r.next}» одновременно чей-то old — переименования нельзя упорядочить безопасно`
4054
+ for (const o of s)
4055
+ n.has(o.next) && t.push(
4056
+ `цепочка: new «${o.next}» одновременно чей-то old — переименования нельзя упорядочить безопасно`
3999
4057
  );
4000
4058
  return t.length > 0 ? { ok: !1, errors: t } : { ok: !0, map: s };
4001
4059
  }
4002
- function ne(e) {
4060
+ function re(e) {
4003
4061
  return (e ?? "").replace(/`/g, "").trim();
4004
4062
  }
4005
- function Dr(e) {
4006
- const t = he(e), s = [], n = /* @__PURE__ */ new Set(), o = [];
4007
- for (const r of t.units) {
4008
- const i = ee(r);
4063
+ function wr(e) {
4064
+ const t = ge(e), s = [], n = /* @__PURE__ */ new Set(), r = [];
4065
+ for (const o of t.units) {
4066
+ const i = se(o);
4009
4067
  let a;
4010
4068
  try {
4011
- a = D(h(e, i), "utf-8");
4069
+ a = C(h(e, i), "utf-8");
4012
4070
  } catch {
4013
4071
  continue;
4014
4072
  }
4015
4073
  const c = g(a, "TICKET_MAP");
4016
4074
  if (c.status === "ok")
4017
- for (const l of X(c.content)) {
4018
- const f = ne(l[0]);
4075
+ for (const l of z(c.content)) {
4076
+ const f = re(l[0]);
4019
4077
  if (f === "(нет тикетов)") continue;
4020
- const d = ne(l[1]), u = ne(l[2]);
4078
+ const d = re(l[1]), u = re(l[2]);
4021
4079
  if (d === "?" || u === "?") continue;
4022
- if (!Z.test(d) || !Z.test(u)) {
4023
- o.push(
4080
+ if (!Q.test(d) || !Q.test(u)) {
4081
+ r.push(
4024
4082
  `${i}: строка Ticket Map тикета \`${f}\` невалидна — old=«${d}» new=«${u}» вне грамматики ID (не «?», значит не заглушка).`
4025
4083
  );
4026
4084
  continue;
@@ -4029,89 +4087,89 @@ function Dr(e) {
4029
4087
  n.has(p) || (n.add(p), s.push(p));
4030
4088
  }
4031
4089
  }
4032
- return o.length > 0 ? { ok: !1, errors: o } : { ok: !0, tsv: s.sort().join(`
4090
+ return r.length > 0 ? { ok: !1, errors: r } : { ok: !0, tsv: s.sort().join(`
4033
4091
  `) + (s.length > 0 ? `
4034
4092
  ` : "") };
4035
4093
  }
4036
- function mt(e) {
4094
+ function ht(e) {
4037
4095
  return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4038
4096
  }
4039
- function Et(e, t) {
4040
- const s = [], n = (o) => {
4041
- let r;
4097
+ function St(e, t) {
4098
+ const s = [], n = (r) => {
4099
+ let o;
4042
4100
  try {
4043
- r = $(o, { withFileTypes: !0 });
4101
+ o = B(r, { withFileTypes: !0 });
4044
4102
  } catch {
4045
4103
  return;
4046
4104
  }
4047
- for (const i of r) {
4048
- if (i.name.startsWith(".") || bn.has(i.name) || i.isSymbolicLink()) continue;
4049
- const a = h(o, i.name);
4050
- i.isDirectory() ? n(a) : i.isFile() && Ln.has(_t(i.name)) && s.push(a);
4105
+ for (const i of o) {
4106
+ if (i.name.startsWith(".") || xn.has(i.name) || i.isSymbolicLink()) continue;
4107
+ const a = h(r, i.name);
4108
+ i.isDirectory() ? n(a) : i.isFile() && $n.has(Ct(i.name)) && s.push(a);
4051
4109
  }
4052
4110
  };
4053
- for (const o of t) n(h(e, o));
4111
+ for (const r of t) n(h(e, r));
4054
4112
  return s.sort();
4055
4113
  }
4056
- function Ar(e, t, s, n = pt) {
4057
- const o = [], r = t.map((i) => ({
4058
- re: new RegExp(`\\b${mt(i.old)}\\b`, "g"),
4114
+ function Pr(e, t, s, n = Et) {
4115
+ const r = [], o = t.map((i) => ({
4116
+ re: new RegExp(`\\b${ht(i.old)}\\b`, "g"),
4059
4117
  next: i.next
4060
4118
  }));
4061
- for (const i of Et(e, n)) {
4119
+ for (const i of St(e, n)) {
4062
4120
  let a;
4063
4121
  try {
4064
- a = D(i, "utf-8");
4122
+ a = C(i, "utf-8");
4065
4123
  } catch {
4066
4124
  continue;
4067
4125
  }
4068
4126
  let c = a, l = 0;
4069
- for (const { re: f, next: d } of r)
4127
+ for (const { re: f, next: d } of o)
4070
4128
  c = c.replace(f, () => (l++, d));
4071
- l > 0 && (s && q(i, c, "utf-8"), o.push({ file: x(e, i), count: l }));
4129
+ l > 0 && (s && W(i, c, "utf-8"), r.push({ file: x(e, i), count: l }));
4072
4130
  }
4073
- return o;
4131
+ return r;
4074
4132
  }
4075
- function yr(e, t, s = pt) {
4076
- const n = [], o = t.map((r) => ({ re: new RegExp(`\\b${mt(r.old)}\\b`), id: r.old }));
4077
- for (const r of Et(e, s)) {
4133
+ function Lr(e, t, s = Et) {
4134
+ const n = [], r = t.map((o) => ({ re: new RegExp(`\\b${ht(o.old)}\\b`), id: o.old }));
4135
+ for (const o of St(e, s)) {
4078
4136
  let i;
4079
4137
  try {
4080
- i = D(r, "utf-8");
4138
+ i = C(o, "utf-8");
4081
4139
  } catch {
4082
4140
  continue;
4083
4141
  }
4084
- for (const { re: a, id: c } of o)
4085
- a.test(i) && n.push({ file: x(e, r), id: c });
4142
+ for (const { re: a, id: c } of r)
4143
+ a.test(i) && n.push({ file: x(e, o), id: c });
4086
4144
  }
4087
4145
  return n;
4088
4146
  }
4089
- function Mn(e) {
4147
+ function Bn(e) {
4090
4148
  const t = /\*\*Dependencies:\*\*\s*([^\n]+)/.exec(e);
4091
4149
  return !t || !t[1] || /^\s*(none|—|-)\s*$/i.test(t[1]) ? [] : [...t[1].replace(/\([^)]*\)/g, " ").matchAll(/\b([A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)+)\b/g)].map(
4092
4150
  (n) => n[1]
4093
4151
  );
4094
4152
  }
4095
- function xn(e) {
4153
+ function Un(e) {
4096
4154
  const t = /^#\s+Task:\s*([^\n]+)/m.exec(e);
4097
4155
  if (!t || !t[1]) return "—";
4098
4156
  const s = t[1].trim(), n = s.split("—");
4099
4157
  return (n.length > 1 ? n.slice(1).join("—") : s).trim() || "—";
4100
4158
  }
4101
- function $n(e, t) {
4102
- const s = [], o = he(e).units.filter((a) => a.scope === t);
4103
- if (o.length === 0)
4159
+ function Fn(e, t) {
4160
+ const s = [], r = ge(e).units.filter((a) => a.scope === t);
4161
+ if (r.length === 0)
4104
4162
  return { ok: !1, errors: [`scope «${t}» не найден среди юнитов миграции`] };
4105
- const r = [], i = [];
4106
- for (const a of o) {
4107
- const c = ee(a), l = h(e, c);
4163
+ const o = [], i = [];
4164
+ for (const a of r) {
4165
+ const c = se(a), l = h(e, c);
4108
4166
  if (!R(l)) {
4109
4167
  a.tickets.length > 0 && s.push(
4110
4168
  `нет файла плана ${c} — сгенерируй слой: sdd-migrate plan --all --write`
4111
4169
  ), i.push({ unit: a, tickets: [] });
4112
4170
  continue;
4113
4171
  }
4114
- const f = g(D(l, "utf-8"), "TICKET_MAP"), d = /* @__PURE__ */ new Map();
4172
+ const f = g(C(l, "utf-8"), "TICKET_MAP"), d = /* @__PURE__ */ new Map();
4115
4173
  if (f.status === "ok")
4116
4174
  for (const p of f.content.split(`
4117
4175
  `)) {
@@ -4133,44 +4191,44 @@ function $n(e, t) {
4133
4191
  );
4134
4192
  continue;
4135
4193
  }
4136
- r.push({ from: p.file, to: m.dest, newId: m.newId });
4137
- const S = D(E, "utf-8"), _ = g(S, "META"), N = _.status === "ok" ? _.content : S, I = at(N);
4194
+ o.push({ from: p.file, to: m.dest, newId: m.newId });
4195
+ const S = C(E, "utf-8"), _ = g(S, "META"), N = _.status === "ok" ? _.content : S, I = nt(N);
4138
4196
  u.push({
4139
4197
  newId: m.newId,
4140
- title: xn(S),
4198
+ title: Un(S),
4141
4199
  status: I.status ?? "[ ] TODO",
4142
- deps: Mn(N),
4200
+ deps: Bn(N),
4143
4201
  destDir: w(m.dest)
4144
4202
  });
4145
4203
  }
4146
4204
  i.push({ unit: a, tickets: u });
4147
4205
  }
4148
- return s.length > 0 ? { ok: !1, errors: s } : { ok: !0, moves: r, units: i };
4206
+ return s.length > 0 ? { ok: !1, errors: s } : { ok: !0, moves: o, units: i };
4149
4207
  }
4150
- function Bn(e, t) {
4151
- const s = new Set(t.map((r) => r.newId)), n = [
4208
+ function Gn(e, t) {
4209
+ const s = new Set(t.map((o) => o.newId)), n = [
4152
4210
  `# ${e} — Tasks`,
4153
4211
  "",
4154
4212
  "## Tracker Index",
4155
4213
  "| Task-ID | Title | Dependencies | Status | Reopens |",
4156
4214
  "|---------|-------|--------------|--------|---------|"
4157
4215
  ];
4158
- for (const r of t)
4216
+ for (const o of t)
4159
4217
  n.push(
4160
- `| ${r.newId} | ${r.title} | ${r.deps.length > 0 ? r.deps.join(", ") : "—"} | ${r.status} | — |`
4218
+ `| ${o.newId} | ${o.title} | ${o.deps.length > 0 ? o.deps.join(", ") : "—"} | ${o.status} | — |`
4161
4219
  );
4162
4220
  n.push("", "## Slug Registry"), n.push(
4163
4221
  "<!-- один ID на строку; уникальность держится этим списком — одинаковый ID в двух ветках сталкивается здесь при merge. Только добавление. -->"
4164
4222
  );
4165
- for (const r of t) n.push(`- ${r.newId}`);
4223
+ for (const o of t) n.push(`- ${o.newId}`);
4166
4224
  n.push("", "## Intra-Module DAG", "```mermaid", "graph TD");
4167
- let o = 0;
4168
- for (const r of t)
4169
- for (const i of r.deps)
4225
+ let r = 0;
4226
+ for (const o of t)
4227
+ for (const i of o.deps)
4170
4228
  s.has(i) && (n.push(
4171
- ` ${r.newId.replace(/[^A-Za-z0-9]/g, "_")}[${r.newId}] --> ${i.replace(/[^A-Za-z0-9]/g, "_")}[${i}]`
4172
- ), o++);
4173
- return o === 0 && n.push(" %% зависимостей внутри модуля нет"), n.push(
4229
+ ` ${o.newId.replace(/[^A-Za-z0-9]/g, "_")}[${o.newId}] --> ${i.replace(/[^A-Za-z0-9]/g, "_")}[${i}]`
4230
+ ), r++);
4231
+ return r === 0 && n.push(" %% зависимостей внутри модуля нет"), n.push(
4174
4232
  "```",
4175
4233
  "<!-- ребро A → B = «A зависит от B». Кросс-модульные рёбра живут уровнем выше. -->"
4176
4234
  ), n.push(
@@ -4185,11 +4243,11 @@ function Bn(e, t) {
4185
4243
  ), n.join(`
4186
4244
  `);
4187
4245
  }
4188
- function Un(e, t) {
4189
- const s = h("specs", e), n = (c) => c === s ? e : G(c), o = /* @__PURE__ */ new Map(), r = [];
4246
+ function Vn(e, t) {
4247
+ const s = h("specs", e), n = (c) => c === s ? e : V(c), r = /* @__PURE__ */ new Map(), o = [];
4190
4248
  for (const c of t)
4191
4249
  for (const l of c.tickets)
4192
- o.set(l.newId, n(l.destDir)), r.push(l);
4250
+ r.set(l.newId, n(l.destDir)), o.push(l);
4193
4251
  const i = [
4194
4252
  `# Tasks: ${e}`,
4195
4253
  "",
@@ -4203,10 +4261,10 @@ function Un(e, t) {
4203
4261
  "```mermaid",
4204
4262
  "graph TD"
4205
4263
  ], a = /* @__PURE__ */ new Set();
4206
- for (const c of r) {
4264
+ for (const c of o) {
4207
4265
  const l = n(c.destDir);
4208
4266
  for (const f of c.deps) {
4209
- const d = o.get(f);
4267
+ const d = r.get(f);
4210
4268
  if (d && d !== l) {
4211
4269
  const u = `${l}-->${d}`;
4212
4270
  a.has(u) || (a.add(u), i.push(
@@ -4222,7 +4280,7 @@ function Un(e, t) {
4222
4280
  "| Task-ID | Title | Module | Dependencies | Status | Reopens |",
4223
4281
  "|---------|-------|--------|--------------|--------|---------|"
4224
4282
  );
4225
- for (const c of r) {
4283
+ for (const c of o) {
4226
4284
  const l = n(c.destDir);
4227
4285
  i.push(
4228
4286
  `| ${c.newId} | ${c.title} | ${l === e ? "—" : l} | ${c.deps.length > 0 ? c.deps.join(", ") : "—"} | ${c.status} | — |`
@@ -4236,85 +4294,85 @@ function Un(e, t) {
4236
4294
  ), i.join(`
4237
4295
  `);
4238
4296
  }
4239
- const Gn = ["specs", "tasks"];
4240
- function Fn(e) {
4297
+ const jn = ["specs", "tasks"];
4298
+ function Yn(e) {
4241
4299
  const t = e.indexOf("#");
4242
4300
  return t >= 0 ? { path: e.slice(0, t), fragment: e.slice(t) } : { path: e, fragment: "" };
4243
4301
  }
4244
- function Vn(e, t, s, n) {
4302
+ function Hn(e, t, s, n) {
4245
4303
  if (n.size === 0) return { text: e, count: 0 };
4246
- const o = B.dirname(t), r = B.dirname(s);
4304
+ const r = F.dirname(t), o = F.dirname(s);
4247
4305
  let i = 0;
4248
4306
  return { text: e.replace(
4249
4307
  /\]\(([^)\s]+)([^)]*)\)/g,
4250
4308
  (c, l, f) => {
4251
4309
  if (l === "" || /^[a-z][a-z0-9+.-]*:\/\//i.test(l)) return c;
4252
- const { path: d, fragment: u } = Fn(l);
4310
+ const { path: d, fragment: u } = Yn(l);
4253
4311
  if (d === "") return c;
4254
- const p = B.normalize(B.join(o, d)), m = n.get(p);
4312
+ const p = F.normalize(F.join(r, d)), m = n.get(p);
4255
4313
  if (!m) return c;
4256
4314
  i++;
4257
- let E = B.relative(r, m);
4315
+ let E = F.relative(o, m);
4258
4316
  return E.startsWith(".") || (E = "./" + E), `](${E}${u}${f})`;
4259
4317
  }
4260
4318
  ), count: i };
4261
4319
  }
4262
- function jn(e, t) {
4263
- const s = [], n = (o) => {
4264
- let r;
4320
+ function qn(e, t) {
4321
+ const s = [], n = (r) => {
4322
+ let o;
4265
4323
  try {
4266
- r = $(o, { withFileTypes: !0 });
4324
+ o = B(r, { withFileTypes: !0 });
4267
4325
  } catch {
4268
4326
  return;
4269
4327
  }
4270
- for (const i of r) {
4328
+ for (const i of o) {
4271
4329
  if (i.name.startsWith(".") || i.isSymbolicLink()) continue;
4272
- const a = h(o, i.name);
4330
+ const a = h(r, i.name);
4273
4331
  i.isDirectory() ? n(a) : i.isFile() && i.name.endsWith(".md") && s.push(a);
4274
4332
  }
4275
4333
  };
4276
- for (const o of t) n(h(e, o));
4334
+ for (const r of t) n(h(e, r));
4277
4335
  return s.sort();
4278
4336
  }
4279
- function Yn(e, t, s) {
4280
- Fe(w(h(e, s)), { recursive: !0 });
4337
+ function Wn(e, t, s) {
4338
+ je(w(h(e, s)), { recursive: !0 });
4281
4339
  try {
4282
- Ot("git", ["mv", t, s], { cwd: e, stdio: "pipe" });
4340
+ _t("git", ["mv", t, s], { cwd: e, stdio: "pipe" });
4283
4341
  } catch {
4284
- Tt(h(e, t), h(e, s));
4342
+ Nt(h(e, t), h(e, s));
4285
4343
  }
4286
4344
  }
4287
- function Hn(e) {
4345
+ function Kn(e) {
4288
4346
  const t = [], s = (n) => {
4289
- let o;
4347
+ let r;
4290
4348
  try {
4291
- o = $(n, { withFileTypes: !0 });
4349
+ r = B(n, { withFileTypes: !0 });
4292
4350
  } catch {
4293
4351
  return;
4294
4352
  }
4295
- for (const r of o) {
4296
- const i = h(n, r.name);
4297
- r.isDirectory() ? s(i) : /\.task-[0-9]+\.md$/.test(r.name) && t.push(i);
4353
+ for (const o of r) {
4354
+ const i = h(n, o.name);
4355
+ o.isDirectory() ? s(i) : /\.task-[0-9]+\.md$/.test(o.name) && t.push(i);
4298
4356
  }
4299
4357
  };
4300
4358
  return s(e), t.length === 0;
4301
4359
  }
4302
- function Rr(e, t, s) {
4303
- const n = $n(e, t);
4360
+ function br(e, t, s) {
4361
+ const n = Fn(e, t);
4304
4362
  if (!n.ok) return n;
4305
- const o = s ? "" : "would ", r = [], i = new Map(n.moves.map((u) => [u.from, u.to]));
4363
+ const r = s ? "" : "would ", o = [], i = new Map(n.moves.map((u) => [u.from, u.to]));
4306
4364
  if (i.size > 0)
4307
- for (const u of jn(e, Gn)) {
4308
- const p = x(e, u), m = i.get(p) ?? p, { text: E, count: S } = Vn(
4309
- D(u, "utf-8"),
4365
+ for (const u of qn(e, jn)) {
4366
+ const p = x(e, u), m = i.get(p) ?? p, { text: E, count: S } = Hn(
4367
+ C(u, "utf-8"),
4310
4368
  p,
4311
4369
  m,
4312
4370
  i
4313
4371
  );
4314
- S > 0 && (s && q(u, E, "utf-8"), r.push(` ${o}link ${p} — ${S} ссылк(и) на переезжающие тикеты`));
4372
+ S > 0 && (s && W(u, E, "utf-8"), o.push(` ${r}link ${p} — ${S} ссылк(и) на переезжающие тикеты`));
4315
4373
  }
4316
4374
  for (const u of n.moves)
4317
- s && Yn(e, u.from, u.to), r.push(` ${o}mv ${u.from} → ${u.to}`);
4375
+ s && Wn(e, u.from, u.to), o.push(` ${r}mv ${u.from} → ${u.to}`);
4318
4376
  const a = h("specs", t), c = /* @__PURE__ */ new Map();
4319
4377
  for (const u of n.units)
4320
4378
  for (const p of u.tickets) {
@@ -4323,42 +4381,42 @@ function Rr(e, t, s) {
4323
4381
  }
4324
4382
  for (const u of [...c.keys()].sort()) {
4325
4383
  if (u === a) continue;
4326
- const p = c.get(u), m = G(u), E = h(u, `${m}.3-tasks.md`);
4327
- s && q(h(e, E), Bn(m, p), "utf-8"), r.push(` ${o}index ${E} — ${p.length} тикет(ов)`);
4384
+ const p = c.get(u), m = V(u), E = h(u, `${m}.3-tasks.md`);
4385
+ s && W(h(e, E), Gn(m, p), "utf-8"), o.push(` ${r}index ${E} — ${p.length} тикет(ов)`);
4328
4386
  }
4329
4387
  const l = h("specs", t, `${t}.3-tasks.md`);
4330
- s && q(h(e, l), Un(t, n.units), "utf-8"), r.push(` ${o}index ${l} — сводный трекер scope`);
4388
+ s && W(h(e, l), Vn(t, n.units), "utf-8"), o.push(` ${r}index ${l} — сводный трекер scope`);
4331
4389
  const f = h(e, "tasks", t);
4332
- R(f) && (s ? Hn(f) ? (Se(f, { recursive: !0, force: !0 }), r.push(` rm -r tasks/${t}/ — пусто, scope переключён на v2`)) : r.push(` ⚠ tasks/${t}/ НЕ удалён — там остались *.task-*.md вне плана`) : r.push(` would rm -r tasks/${t}/ (если не останется тикетов)`));
4390
+ R(f) && (s ? Kn(f) ? (Ie(f, { recursive: !0, force: !0 }), o.push(` rm -r tasks/${t}/ — пусто, scope переключён на v2`)) : o.push(` ⚠ tasks/${t}/ НЕ удалён — там остались *.task-*.md вне плана`) : o.push(` would rm -r tasks/${t}/ (если не останется тикетов)`));
4333
4391
  const d = h(e, "tasks");
4334
- return R(d) && $(d, { withFileTypes: !0 }).filter(
4392
+ return R(d) && B(d, { withFileTypes: !0 }).filter(
4335
4393
  (p) => p.name !== "README.md"
4336
- ).length === 0 && (s ? (Se(d, { recursive: !0, force: !0 }), r.push(
4394
+ ).length === 0 && (s ? (Ie(d, { recursive: !0, force: !0 }), o.push(
4337
4395
  " rm -r tasks/ — последний scope мигрирован, репо переключён на v2 (FLOW_VERSION)"
4338
- )) : r.push(" would rm -r tasks/ (последний scope — репо переключится на v2)")), { ok: !0, report: r };
4396
+ )) : o.push(" would rm -r tasks/ (последний scope — репо переключится на v2)")), { ok: !0, report: o };
4339
4397
  }
4340
- const qn = "ERR_CLI_YAGNI_UNDERUSED", Wn = "ERR_CLI_YAGNI_WAIVER_DECISION_MISSING", Kn = 2;
4341
- function kr(e) {
4398
+ const Xn = "ERR_CLI_YAGNI_UNDERUSED", Zn = "ERR_CLI_YAGNI_WAIVER_DECISION_MISSING", zn = 2;
4399
+ function Mr(e) {
4342
4400
  return e.replace(/^[ \t]*export\s*(?:\*|\{[^}]*\})\s*from\s*['"][^'"]+['"];?[ \t]*$/gm, "");
4343
4401
  }
4344
- const Xn = ["MODULE_CONTRACTS", "ENTITY_SURFACES", "PUBLIC_API_SURFACE"];
4345
- function Zn(e, t) {
4402
+ const Qn = ["MODULE_CONTRACTS", "ENTITY_SURFACES", "PUBLIC_API_SURFACE"];
4403
+ function Jn(e, t) {
4346
4404
  const s = [];
4347
4405
  for (const n of t) {
4348
- const o = new RegExp(
4406
+ const r = new RegExp(
4349
4407
  "<!--SECTION:" + n + "-->([\\s\\S]*?)<!--/SECTION:" + n + "-->",
4350
4408
  "g"
4351
4409
  );
4352
- for (const r of e.matchAll(o))
4353
- s.push([r.index, r.index + r[0].length]);
4410
+ for (const o of e.matchAll(r))
4411
+ s.push([o.index, o.index + o[0].length]);
4354
4412
  }
4355
4413
  return s;
4356
4414
  }
4357
- function vr(e, t) {
4358
- const n = /<!--SECTION:[A-Z_]+-->/.test(e) ? Zn(e, Xn) : null, o = (I) => !n || n.some(([ht, St]) => I >= ht && I < St), r = t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), i = new RegExp("^(#{2,6})[ \\t]+.*`" + r + "`.*$", "gm");
4415
+ function $r(e, t) {
4416
+ const n = /<!--SECTION:[A-Z_]+-->/.test(e) ? Jn(e, Qn) : null, r = (I) => !n || n.some(([gt, It]) => I >= gt && I < It), o = t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), i = new RegExp("^(#{2,6})[ \\t]+.*`" + o + "`.*$", "gm");
4359
4417
  let a, c = null;
4360
4418
  for (; a = i.exec(e); )
4361
- if (o(a.index)) {
4419
+ if (r(a.index)) {
4362
4420
  c = a;
4363
4421
  break;
4364
4422
  }
@@ -4372,138 +4430,141 @@ function vr(e, t) {
4372
4430
  const S = m[1]?.trim(), _ = m[2], N = _ ? { decision: _, reason: E } : { reason: E };
4373
4431
  return S ? { ...N, external: S } : N;
4374
4432
  }
4375
- function wr(e, t) {
4433
+ function xr(e, t) {
4376
4434
  const s = t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4377
4435
  return new RegExp("^###\\s*" + s + "\\b", "m").test(e);
4378
4436
  }
4379
- function Pr(e, t, s, n) {
4380
- const o = [];
4381
- for (const r of e) {
4382
- const i = t.get(r.name) ?? 0;
4383
- if (i >= Kn) continue;
4384
- const a = s.get(r.name);
4437
+ function Br(e, t, s, n) {
4438
+ const r = [];
4439
+ for (const o of e) {
4440
+ const i = t.get(o.name) ?? 0;
4441
+ if (i >= zn) continue;
4442
+ const a = s.get(o.name);
4385
4443
  if (!a) {
4386
- o.push({
4444
+ r.push({
4387
4445
  severity: "error",
4388
- code: qn,
4389
- file: r.file,
4390
- symbol: r.name,
4391
- message: `\`${r.name}\` (${r.kind}) has ${i} usage(s) in production code (< 2) — YAGNI suspect. Fix: remove it, or — if genuinely needed — add \`- **Usage Waiver:** <reason>\` to its contract/surface entry (cite \`D-NNN — <reason>\` instead only when a Decision Log entry actually backs the reason, and then it must exist; for a public API named to an external consumer use the \`(external: <consumer>)\` variant) and log \`yagni ${r.name} ← <reason>\` in the Execution Log.`
4446
+ code: Xn,
4447
+ file: o.file,
4448
+ symbol: o.name,
4449
+ message: `\`${o.name}\` (${o.kind}) has ${i} usage(s) in production code (< 2) — YAGNI suspect. Fix: remove it, or — if genuinely needed — add \`- **Usage Waiver:** <reason>\` to its contract/surface entry (cite \`D-NNN — <reason>\` instead only when a Decision Log entry actually backs the reason, and then it must exist; for a public API named to an external consumer use the \`(external: <consumer>)\` variant) and log \`yagni ${o.name} ← <reason>\` in the Execution Log.`
4392
4450
  });
4393
4451
  continue;
4394
4452
  }
4395
- a.decision && !n.has(a.decision) && o.push({
4453
+ a.decision && !n.has(a.decision) && r.push({
4396
4454
  severity: "error",
4397
- code: Wn,
4398
- file: r.file,
4399
- symbol: r.name,
4400
- message: `\`${r.name}\` has a Usage Waiver citing ${a.decision}, but no Decision Log entry with that id was found anywhere in the repo — an unresolvable citation does not gate the finding. Fix: add the ${a.decision} entry to a Decision Log, correct the citation, or drop the citation if the reason does not need one.`
4455
+ code: Zn,
4456
+ file: o.file,
4457
+ symbol: o.name,
4458
+ message: `\`${o.name}\` has a Usage Waiver citing ${a.decision}, but no Decision Log entry with that id was found anywhere in the repo — an unresolvable citation does not gate the finding. Fix: add the ${a.decision} entry to a Decision Log, correct the citation, or drop the citation if the reason does not need one.`
4401
4459
  });
4402
4460
  }
4403
- return o;
4461
+ return r;
4404
4462
  }
4405
4463
  export {
4406
- fr as $,
4407
- Io as A,
4408
- Jo as B,
4409
- ir as C,
4410
- Fo as D,
4411
- Ho as E,
4412
- Vo as F,
4413
- re as G,
4414
- Wo as H,
4415
- qo as I,
4416
- Xo as J,
4417
- Zo as K,
4418
- sr as L,
4419
- tr as M,
4420
- g as N,
4421
- Ks as O,
4422
- $o as P,
4423
- cr as Q,
4424
- dr as R,
4425
- Or as S,
4426
- pe as T,
4427
- Er as U,
4464
+ he as $,
4465
+ _o as A,
4466
+ ar as B,
4467
+ fr as C,
4468
+ lr as D,
4469
+ cr as E,
4470
+ Fo as F,
4471
+ ae as G,
4472
+ Zo as H,
4473
+ er as I,
4474
+ zo as J,
4475
+ sr as K,
4476
+ tr as L,
4477
+ or as M,
4478
+ rr as N,
4479
+ ur as O,
4480
+ dr as P,
4481
+ g as Q,
4482
+ en as R,
4483
+ qo as S,
4484
+ Ee as T,
4485
+ mr as U,
4428
4486
  A as V,
4429
- Sr as W,
4430
- gr as X,
4431
- me as Y,
4432
- Ir as Z,
4433
- bo as _,
4434
- oo as a,
4435
- pr as a0,
4436
- P as a1,
4437
- mr as a2,
4438
- hr as a3,
4439
- lr as a4,
4440
- ys as a5,
4441
- qe as a6,
4442
- _o as a7,
4443
- at as a8,
4444
- rr as a9,
4445
- co as aA,
4446
- Ae as aB,
4447
- go as aC,
4448
- So as aD,
4449
- ho as aE,
4450
- No as aF,
4451
- po as aG,
4452
- Te as aH,
4453
- ao as aI,
4454
- $t as aJ,
4455
- Ft as aK,
4456
- mo as aL,
4457
- Oo as aM,
4458
- ar as aa,
4459
- Bo as ab,
4460
- Ko as ac,
4461
- Rr as ad,
4462
- Uo as ae,
4463
- Go as af,
4464
- Nr as ag,
4465
- he as ah,
4466
- ee as ai,
4467
- Tr as aj,
4468
- _r as ak,
4469
- Dr as al,
4470
- Cr as am,
4471
- Ar as an,
4472
- yr as ao,
4473
- Pr as ap,
4474
- Ce as aq,
4475
- kr as ar,
4476
- vr as as,
4477
- wr as at,
4478
- Ao as au,
4479
- Do as av,
4480
- Co as aw,
4481
- yo as ax,
4482
- ko as ay,
4483
- Ro as az,
4484
- lo as b,
4485
- Cs as c,
4486
- vo as d,
4487
- Ws as e,
4488
- To as f,
4489
- uo as g,
4490
- Po as h,
4491
- wo as i,
4492
- Lo as j,
4493
- jo as k,
4494
- or as l,
4495
- zo as m,
4496
- Mo as n,
4497
- ur as o,
4498
- io as p,
4499
- xo as q,
4500
- Wt as r,
4501
- ro as s,
4502
- js as t,
4503
- fo as u,
4504
- Yo as v,
4505
- Qo as w,
4506
- Eo as x,
4507
- nr as y,
4508
- er as z
4487
+ hr as W,
4488
+ Ar as X,
4489
+ Tr as Y,
4490
+ Nr as Z,
4491
+ Cr as _,
4492
+ ao as a,
4493
+ Dr as a0,
4494
+ xo as a1,
4495
+ gr as a2,
4496
+ Ir as a3,
4497
+ P as a4,
4498
+ Or as a5,
4499
+ _r as a6,
4500
+ Er as a7,
4501
+ ks as a8,
4502
+ Ke as a9,
4503
+ vo as aA,
4504
+ Po as aB,
4505
+ wo as aC,
4506
+ fo as aD,
4507
+ Re as aE,
4508
+ To as aF,
4509
+ Oo as aG,
4510
+ Io as aH,
4511
+ Ao as aI,
4512
+ ho as aJ,
4513
+ Ne as aK,
4514
+ uo as aL,
4515
+ Ut as aM,
4516
+ jt as aN,
4517
+ So as aO,
4518
+ No as aP,
4519
+ Do as aa,
4520
+ nt as ab,
4521
+ Uo as ac,
4522
+ Go as ad,
4523
+ Wo as ae,
4524
+ nr as af,
4525
+ br as ag,
4526
+ Ko as ah,
4527
+ Xo as ai,
4528
+ kr as aj,
4529
+ ge as ak,
4530
+ se as al,
4531
+ yr as am,
4532
+ Rr as an,
4533
+ wr as ao,
4534
+ vr as ap,
4535
+ Pr as aq,
4536
+ Lr as ar,
4537
+ Br as as,
4538
+ Ae as at,
4539
+ Mr as au,
4540
+ $r as av,
4541
+ xr as aw,
4542
+ ko as ax,
4543
+ Ro as ay,
4544
+ yo as az,
4545
+ po as b,
4546
+ As as c,
4547
+ Lo as d,
4548
+ Xs as e,
4549
+ Co as f,
4550
+ mo as g,
4551
+ Mo as h,
4552
+ bo as i,
4553
+ $o as j,
4554
+ Bo as k,
4555
+ Vo as l,
4556
+ jo as m,
4557
+ Qo as n,
4558
+ pr as o,
4559
+ lo as p,
4560
+ ir as q,
4561
+ Xt as r,
4562
+ co as s,
4563
+ Yo as t,
4564
+ Eo as u,
4565
+ Sr as v,
4566
+ Ho as w,
4567
+ go as x,
4568
+ Hs as y,
4569
+ Jo as z
4509
4570
  };