gennady 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/ai/directives/coding/result-conventions.xml +25 -7
  2. package/ai/directives/sdd/audit.directive.xml +1 -1
  3. package/ai/directives/sdd/critic-protocol.xml +78 -0
  4. package/ai/directives/sdd/critic.directive.xml +158 -0
  5. package/ai/directives/sdd/phase-execution-protocol.xml +11 -9
  6. package/ai/skills/alt-opinion/SKILL.md +79 -0
  7. package/ai/skills/alt-opinion/opinion.prompt.md +11 -0
  8. package/ai/skills/alt-opinion/synth.prompt.md +8 -0
  9. package/ai/skills/sdd-audit/SKILL.md +13 -0
  10. package/ai/skills/sdd-check/SKILL.md +139 -0
  11. package/ai/skills/sdd-continue/SKILL.md +13 -0
  12. package/ai/skills/sdd-critic/SKILL.md +12 -0
  13. package/ai/skills/sdd-discover/SKILL.md +13 -0
  14. package/ai/skills/sdd-execute/SKILL.md +205 -0
  15. package/ai/skills/sdd-execute/scripts/README.md +84 -0
  16. package/ai/skills/sdd-execute/scripts/check-blockers.sh +158 -0
  17. package/ai/skills/sdd-execute/scripts/classify-scripts.js +111 -0
  18. package/ai/skills/sdd-execute/scripts/classify-scripts.ts +133 -0
  19. package/ai/skills/sdd-execute/scripts/extract-section.sh +219 -0
  20. package/ai/skills/sdd-execute/scripts/lint-artifacts.sh +143 -0
  21. package/ai/skills/sdd-execute/scripts/scan.sh +385 -0
  22. package/ai/skills/sdd-execute/scripts/sdd +114 -0
  23. package/ai/skills/sdd-execute/scripts/verify.sh +139 -0
  24. package/ai/skills/sdd-execute-batch/SKILL.md +213 -0
  25. package/ai/skills/sdd-fix/SKILL.md +13 -0
  26. package/ai/skills/sdd-infra/SKILL.md +13 -0
  27. package/ai/skills/sdd-module-decomposition/SKILL.md +13 -0
  28. package/ai/skills/sdd-scaffold/SKILL.md +13 -0
  29. package/ai/skills/sdd-setup/SKILL.md +13 -0
  30. package/dist/ai/directives/coding/result-conventions.xml +25 -7
  31. package/dist/ai/directives/sdd/audit.directive.xml +1 -1
  32. package/dist/ai/directives/sdd/critic-protocol.xml +78 -0
  33. package/dist/ai/directives/sdd/critic.directive.xml +158 -0
  34. package/dist/ai/directives/sdd/phase-execution-protocol.xml +11 -9
  35. package/dist/ai/skills/alt-opinion/SKILL.md +79 -0
  36. package/dist/ai/skills/alt-opinion/opinion.prompt.md +11 -0
  37. package/dist/ai/skills/alt-opinion/synth.prompt.md +8 -0
  38. package/dist/ai/skills/sdd-audit/SKILL.md +13 -0
  39. package/dist/ai/skills/sdd-check/SKILL.md +139 -0
  40. package/dist/ai/skills/sdd-continue/SKILL.md +13 -0
  41. package/dist/ai/skills/sdd-critic/SKILL.md +12 -0
  42. package/dist/ai/skills/sdd-discover/SKILL.md +13 -0
  43. package/dist/ai/skills/sdd-execute/SKILL.md +205 -0
  44. package/dist/ai/skills/sdd-execute/scripts/README.md +84 -0
  45. package/dist/ai/skills/sdd-execute/scripts/check-blockers.sh +158 -0
  46. package/dist/ai/skills/sdd-execute/scripts/classify-scripts.js +111 -0
  47. package/dist/ai/skills/sdd-execute/scripts/classify-scripts.ts +133 -0
  48. package/dist/ai/skills/sdd-execute/scripts/extract-section.sh +219 -0
  49. package/dist/ai/skills/sdd-execute/scripts/lint-artifacts.sh +143 -0
  50. package/dist/ai/skills/sdd-execute/scripts/scan.sh +385 -0
  51. package/dist/ai/skills/sdd-execute/scripts/sdd +114 -0
  52. package/dist/ai/skills/sdd-execute/scripts/verify.sh +139 -0
  53. package/dist/ai/skills/sdd-execute-batch/SKILL.md +213 -0
  54. package/dist/ai/skills/sdd-fix/SKILL.md +13 -0
  55. package/dist/ai/skills/sdd-infra/SKILL.md +13 -0
  56. package/dist/ai/skills/sdd-module-decomposition/SKILL.md +13 -0
  57. package/dist/ai/skills/sdd-scaffold/SKILL.md +13 -0
  58. package/dist/ai/skills/sdd-setup/SKILL.md +13 -0
  59. package/dist/chunks/help-5qCaicff.js +6 -0
  60. package/dist/chunks/help-B2ETH0j6.js +6 -0
  61. package/dist/chunks/help-BCDURaCQ.js +6 -0
  62. package/dist/chunks/help-BvgYOSyQ.js +6 -0
  63. package/dist/chunks/help-CSPhOoI9.js +8 -0
  64. package/dist/chunks/help-CV1vpwrh.js +6 -0
  65. package/dist/chunks/help-CaBNA6Qr.js +12 -0
  66. package/dist/chunks/help-CjkR6SB9.js +6 -0
  67. package/dist/chunks/help-Coi1l5u9.js +8 -0
  68. package/dist/chunks/help-CsuLpZn-.js +8 -0
  69. package/dist/chunks/help-DL_QBMwy.js +8 -0
  70. package/dist/chunks/help-DqBZ2xcp.js +6 -0
  71. package/dist/chunks/help-_Y_TN4DZ.js +6 -0
  72. package/dist/chunks/{help.cmd-B_G7EWzF.js → help.cmd-BseRtoBF.js} +10 -2
  73. package/dist/chunks/{index-DeYzAoxF.js → index-BU1AXJGA.js} +7 -3
  74. package/dist/chunks/{index-CFd_iufb.js → index-BXWDYM_9.js} +1 -1
  75. package/dist/chunks/index-BgKyH0dB.js +658 -0
  76. package/dist/chunks/{index-BCqnKvNZ.js → index-BghL1-Nk.js} +2 -2
  77. package/dist/chunks/{index-BLsDffzZ.js → index-BlqEQEGy.js} +1 -1
  78. package/dist/chunks/{index-BrSutH7l.js → index-CDM74qdR.js} +3 -3
  79. package/dist/chunks/{index-O5kqC9i_.js → index-CGsIRefC.js} +2 -2
  80. package/dist/chunks/{index-Dc44ukmL.js → index-CIvkaAQ3.js} +2 -2
  81. package/dist/chunks/{index-BsD-J44e.js → index-CkczJ__m.js} +10 -10
  82. package/dist/chunks/index-CtJKSOL0.js +21 -0
  83. package/dist/chunks/index-DEzym4Ae.js +369 -0
  84. package/dist/chunks/{index-Bq4d25CK.js → index-DoaxOhQ8.js} +385 -378
  85. package/dist/chunks/index-Du1xR-qO.js +752 -0
  86. package/dist/chunks/{index-CAWs-GED.js → index-OtehG7uM.js} +1 -1
  87. package/dist/chunks/index-ZM_FonZj.js +156 -0
  88. package/dist/chunks/{index-BzBhCTHq.js → index-k0nToACp.js} +2 -2
  89. package/dist/chunks/{run-review-command.logic-CwxYeLby.js → run-review-command.logic-BeYQin-I.js} +9 -9
  90. package/dist/chunks/{services-Dnk3nB2x.js → services-IgZptnTi.js} +7 -7
  91. package/dist/chunks/shared-DL_1LG0K.js +753 -0
  92. package/dist/cli/cmd/agent-mon/help.d.ts +4 -0
  93. package/dist/cli/cmd/agents-rules/agents-rules.cmd.d.ts +8 -0
  94. package/dist/cli/cmd/agents-rules/index.d.ts +1 -0
  95. package/dist/cli/cmd/alt-opinion/help.d.ts +4 -0
  96. package/dist/cli/cmd/cat/help.d.ts +4 -0
  97. package/dist/cli/cmd/commit/help.d.ts +4 -0
  98. package/dist/cli/cmd/lint/checks/anchor-class-body.check.d.ts +11 -0
  99. package/dist/cli/cmd/lint/checks/invariant-count.check.d.ts +11 -0
  100. package/dist/cli/cmd/lint/checks/utils/glob-match.d.ts +15 -0
  101. package/dist/cli/cmd/lint/checks/utils/strip-strings-comments.d.ts +7 -0
  102. package/dist/cli/cmd/lint/help.d.ts +4 -0
  103. package/dist/cli/cmd/lint/lint.cmd.d.ts +1 -1
  104. package/dist/cli/cmd/lint/lint.types.d.ts +6 -0
  105. package/dist/cli/cmd/orient/core/build-index.d.ts +8 -0
  106. package/dist/cli/cmd/orient/core/damerau-levenshtein.d.ts +26 -0
  107. package/dist/cli/cmd/orient/core/extract-header.d.ts +8 -0
  108. package/dist/cli/cmd/orient/core/hints.d.ts +9 -0
  109. package/dist/cli/cmd/orient/core/query-consumer.d.ts +10 -0
  110. package/dist/cli/cmd/orient/core/query-entity.d.ts +11 -0
  111. package/dist/cli/cmd/orient/core/query-graph.d.ts +18 -0
  112. package/dist/cli/cmd/orient/core/query-keyword.d.ts +10 -0
  113. package/dist/cli/cmd/orient/core/query-spec.d.ts +15 -0
  114. package/dist/cli/cmd/orient/core/query-task.d.ts +8 -0
  115. package/dist/cli/cmd/orient/core/scan-files.d.ts +8 -0
  116. package/dist/cli/cmd/orient/help.d.ts +5 -0
  117. package/dist/cli/cmd/orient/index.d.ts +1 -0
  118. package/dist/cli/cmd/orient/orient.cmd.d.ts +7 -0
  119. package/dist/cli/cmd/orient/orient.types.d.ts +136 -0
  120. package/dist/cli/cmd/orient/render/render-detail.d.ts +10 -0
  121. package/dist/cli/cmd/orient/render/render-file-list.d.ts +15 -0
  122. package/dist/cli/cmd/orient/render/render-graph.d.ts +13 -0
  123. package/dist/cli/cmd/orient/render/render-search.d.ts +8 -0
  124. package/dist/cli/cmd/orient/render/render-specs.d.ts +13 -0
  125. package/dist/cli/cmd/orient/render/render-tree.d.ts +13 -0
  126. package/dist/cli/cmd/remote-console/help.d.ts +4 -0
  127. package/dist/cli/cmd/resolve-conflicts/help.d.ts +4 -0
  128. package/dist/cli/cmd/review/help.d.ts +4 -0
  129. package/dist/cli/cmd/review-issues/help.d.ts +4 -0
  130. package/dist/cli/cmd/review-verify/help.d.ts +4 -0
  131. package/dist/cli/cmd/sync/help.d.ts +4 -0
  132. package/dist/cli/cmd/sync/sync-core.d.ts +3 -2
  133. package/dist/cli/cmd/sync/sync-formatter.d.ts +8 -9
  134. package/dist/cli/cmd/sync/sync.cmd.d.ts +2 -21
  135. package/dist/cli/cmd/sync-skills/index.d.ts +1 -0
  136. package/dist/cli/cmd/sync-skills/sync-skills-core.d.ts +50 -0
  137. package/dist/cli/cmd/sync-skills/sync-skills-formatter.d.ts +13 -0
  138. package/dist/cli/cmd/sync-skills/sync-skills.cmd.d.ts +14 -0
  139. package/dist/cli/cmd/sync-skills/sync-skills.types.d.ts +56 -0
  140. package/dist/cli/cmd/vcs-reply/help.d.ts +4 -0
  141. package/dist/gennady.js +73 -18
  142. package/dist/index.js +3 -3
  143. package/dist/shared/common/sync/path-normalizer.d.ts +22 -0
  144. package/dist/shared/common/sync/sync-core.shared.d.ts +14 -0
  145. package/dist/shared/common/sync/sync-deps.type.d.ts +66 -0
  146. package/dist/shared/common/sync/sync-formatter.shared.d.ts +19 -0
  147. package/package.json +6 -5
  148. package/dist/chunks/index-DAU6h0aT.js +0 -178
  149. package/dist/chunks/index-Db09OODV.js +0 -176
  150. package/dist/chunks/index-TX0TmKeu.js +0 -540
  151. package/dist/chunks/shared-COpFaV-w.js +0 -665
@@ -1,176 +0,0 @@
1
- import { existsSync as E, readdirSync as D, statSync as m, mkdirSync as F, writeFileSync as P, readFileSync as C } from "node:fs";
2
- import { join as u, sep as L } from "node:path";
3
- import { fileURLToPath as v } from "node:url";
4
- import { l as O } from "./services-Dnk3nB2x.js";
5
- import { p as x } from "./shared-COpFaV-w.js";
6
- class I {
7
- /** @purpose List of all synced file entries. */
8
- entries;
9
- /**
10
- * @purpose Construct a SyncResult from a list of entries.
11
- * @param entries File entries.
12
- */
13
- constructor(t) {
14
- this.entries = t;
15
- }
16
- /** @purpose Files with status "added". | @returns Array of added entries. */
17
- get added() {
18
- return this.entries.filter((t) => t.status === "added");
19
- }
20
- /** @purpose Files with status "updated". | @returns Array of updated entries. */
21
- get updated() {
22
- return this.entries.filter((t) => t.status === "updated");
23
- }
24
- /** @purpose Files with status "unchanged". | @returns Array of unchanged entries. */
25
- get unchanged() {
26
- return this.entries.filter((t) => t.status === "unchanged");
27
- }
28
- /** @purpose Human-readable summary of added/updated/unchanged counts. | @returns Summary string. */
29
- get summary() {
30
- const t = this.added.length, n = this.updated.length, c = this.unchanged.length;
31
- return `Synced: ${t} added, ${n} updated, ${c} skipped (unchanged)`;
32
- }
33
- /** @purpose Dry-run summary message. | @returns Dry-run message. */
34
- get dryRunSummary() {
35
- return "Dry-run: no files written.";
36
- }
37
- }
38
- const w = "ERR_SYNC_SUBDIR_NOT_FOUND", T = "ERR_SYNC_SOURCE_NOT_FOUND", S = "ai/directives", N = /* @__PURE__ */ new Set([
39
- "architecture",
40
- "dbc-audit.directive.xml",
41
- "dev-review.directive.xml",
42
- "semantic-change-extractor.directive.xml"
43
- ]);
44
- function B(e) {
45
- const t = u(e, "node_modules", "gennady", S);
46
- if (E(t)) return t;
47
- try {
48
- const n = import.meta.resolve("gennady"), s = v(n).replace(/[/\\]dist[/\\].*$/, ""), r = u(s, S);
49
- if (E(r)) return r;
50
- } catch {
51
- }
52
- return null;
53
- }
54
- function b(e, t) {
55
- if (t && t.length > 0) {
56
- const c = D(e).filter(
57
- (r) => !N.has(r) && m(u(e, r)).isDirectory()
58
- );
59
- for (const r of t)
60
- if (!c.includes(r)) {
61
- const o = `ai/directives/${r}/ not found in package.
62
- Available: ${c.join(", ")}`, i = new Error(o);
63
- throw i.code = w, i;
64
- }
65
- const s = [];
66
- for (const r of t)
67
- y(u(e, r), r, s);
68
- return s.sort();
69
- }
70
- const n = [];
71
- return y(e, "", n), n.sort();
72
- }
73
- function y(e, t, n) {
74
- let c;
75
- try {
76
- c = D(e);
77
- } catch {
78
- return;
79
- }
80
- for (const s of c) {
81
- if (s.startsWith(".") || N.has(s)) continue;
82
- const r = u(e, s), o = t ? u(t, s) : s, i = m(r, { throwIfNoEntry: !1 });
83
- i && (i.isDirectory() ? y(r, o, n) : i.isFile() && n.push(o.split(L).join("/")));
84
- }
85
- }
86
- function W(e, t) {
87
- try {
88
- e.stat(t.sourceDir);
89
- } catch {
90
- const s = `Source directory not found: ${t.sourceDir}`, r = new Error(s);
91
- throw r.code = T, r;
92
- }
93
- const n = b(t.sourceDir, t.subdirs), c = [];
94
- for (const s of n) {
95
- const r = u(t.sourceDir, s), o = u(t.targetDir, s), i = e.readFile(r), l = i.length;
96
- let d = null;
97
- try {
98
- d = e.readFile(o);
99
- } catch {
100
- }
101
- let a;
102
- d === null ? a = "added" : Buffer.compare(i, d) === 0 ? a = "unchanged" : a = "updated", c.push({
103
- relativePath: s,
104
- status: a,
105
- sourceSize: l,
106
- targetSize: d?.length
107
- }), !t.dryRun && a !== "unchanged" && (e.mkdir(u(t.targetDir, s, ".."), { recursive: !0 }), e.writeFile(o, i));
108
- }
109
- return new I(c);
110
- }
111
- const K = "+", Y = "~", j = "=", G = "(unchanged)", H = "(would add)", M = "(would update)", z = "(unchanged, skip)";
112
- function V(e, t = {}) {
113
- const n = [];
114
- for (const o of e) {
115
- const { relativePath: i, status: l } = o;
116
- let d, a;
117
- l === "added" ? (d = K, a = t.dryRun ? H : "") : l === "updated" ? (d = Y, a = t.dryRun ? M : "") : (d = j, a = t.dryRun ? z : G);
118
- const g = i.padEnd(64);
119
- a ? n.push(` ${d} ${g} ${a}`) : n.push(` ${d} ${i}`);
120
- }
121
- const c = e.filter((o) => o.status === "added").length, s = e.filter((o) => o.status === "updated").length, r = e.filter((o) => o.status === "unchanged").length;
122
- return t.dryRun ? n.push("Dry-run: no files written.") : n.push(`Synced: ${c} added, ${s} updated, ${r} skipped (unchanged)`), n;
123
- }
124
- function X(e, t, n, c) {
125
- n.write(`Sync${t ? " (dry-run)" : ""}: ${c}
126
- `);
127
- const s = V(e, { dryRun: t });
128
- for (const r of s)
129
- n.write(r + `
130
- `);
131
- }
132
- function A(e, t) {
133
- const n = C, c = P, s = F, r = m, o = D, i = B, l = process.stdout, d = process.stderr, a = x(e, {
134
- dryRun: ["dry-run"]
135
- }), g = a.dryRun === !0 || a.dryRun === "true", _ = a._.filter(
136
- (f) => typeof f == "string" && f !== "sync"
137
- ), p = process.cwd(), R = i(p);
138
- if (!R)
139
- return d.write(`Error: gennady package not found. Install it locally: npm i -D gennady
140
- `), 1;
141
- const U = u(p, "ai", "directives"), $ = {
142
- sourceDir: R,
143
- targetDir: U,
144
- subdirs: _.length > 0 ? _ : void 0,
145
- dryRun: g
146
- };
147
- try {
148
- const h = W({
149
- readFile: n,
150
- writeFile: c,
151
- mkdir: s,
152
- stat: (k) => r(k),
153
- readdir: o,
154
- cwd: p
155
- }, $);
156
- return X(h.entries, g, l, p), 0;
157
- } catch (f) {
158
- const h = f;
159
- if (h.code === w)
160
- return d.write(`Error: ${h.message}
161
- `), 1;
162
- throw h;
163
- }
164
- }
165
- if (process.argv[1]) {
166
- const e = v(import.meta.url);
167
- if (e === process.argv[1] || e.endsWith(process.argv[1]))
168
- try {
169
- const t = A(process.argv);
170
- process.exit(t);
171
- } catch (t) {
172
- const n = new Error("[syncCmd] Self-execution failed", { cause: t });
173
- O.error("[syncCmd#run] [self-executing → failed]", { error: n }), process.exit(1);
174
- }
175
- }
176
- A(process.argv);
@@ -1,540 +0,0 @@
1
- import { execSync as $ } from "node:child_process";
2
- import { existsSync as O, readFileSync as M, readdirSync as y, statSync as P, lstatSync as B } from "node:fs";
3
- import { resolve as _, relative as H, extname as k, join as K } from "node:path";
4
- import { l as d, D as z, a as J, b as Z, s as j } from "./services-Dnk3nB2x.js";
5
- import { p as V } from "./shared-COpFaV-w.js";
6
- class E {
7
- /** @purpose Collected lint errors — empty array when clean. */
8
- errors;
9
- /** @purpose Count of errors auto-fixed by DbcContractCheck. */
10
- autoFixed;
11
- /** @purpose Deduplicated task file paths resolved from @tasks annotations in linted files. */
12
- taskPaths;
13
- /** @purpose Deduplicated spec file paths resolved from task files. */
14
- specPaths;
15
- /**
16
- * @purpose Creates a LintReport with collected errors, autoFixed count, and resolved references.
17
- * @param errors Collected lint errors.
18
- * @param [autoFixed] Count of auto-fixed errors, defaults to 0.
19
- * @param [taskPaths] Resolved task file paths (deduplicated).
20
- * @param [specPaths] Resolved spec file paths (deduplicated).
21
- */
22
- constructor(t, e = 0, s = [], n = []) {
23
- this.errors = t, this.autoFixed = e, this.taskPaths = s, this.specPaths = n;
24
- }
25
- /** @purpose Returns 0 when no errors, 1 otherwise — ESLint convention. | @returns 0 for clean, 1 for errors. */
26
- get exitCode() {
27
- return this.errors.length > 0 ? 1 : 0;
28
- }
29
- /**
30
- * @purpose Formats errors in ESLint-compatible output with resolved task/spec references.
31
- * @returns ESLint-compatible formatted string with References block.
32
- */
33
- format() {
34
- const t = [];
35
- if (this.autoFixed > 0 && t.push(`Auto-fixed: ${this.autoFixed} error(s)`), this.errors.length > 0 && t.push(
36
- ...this.errors.map(
37
- (e) => `${e.file}:${e.line}:${e.col}: ${e.severity}: ${e.code}: ${e.message}`
38
- )
39
- ), this.specPaths.length > 0 || this.taskPaths.length > 0) {
40
- t.push(""), t.push("---"), t.push("References:");
41
- for (const e of this.specPaths)
42
- t.push(` ${e}`);
43
- for (const e of this.taskPaths)
44
- t.push(` ${e}`);
45
- }
46
- return t.join(`
47
- `);
48
- }
49
- }
50
- const x = "ERR_CLI_LINT_MISSING_FILE", A = "ERR_CLI_LINT_MISSING_CONSUMERS", X = "ERR_CLI_LINT_ANCHOR_UNPAIRED_START", Y = "ERR_CLI_LINT_ANCHOR_UNPAIRED_END", q = "ERR_CLI_LINT_ANCHOR_NESTING", C = "ERR_CLI_LINT_ANCHOR_MALFORMED", b = "ERR_CLI_LINT_NON_ENGLISH", Q = "ERR_CLI_LINT_RESOLVE_FAILED", ee = "ERR_CLI_LINT_STAGED_CONFLICT", te = "ERR_CLI_LINT_UNAUTHORIZED_DISABLE", se = "ERR_CLI_LINT_DISABLE_MISSING_PURPOSE";
51
- function ne(i, t) {
52
- const e = [];
53
- if (i.length === 0)
54
- return e.push({
55
- file: t,
56
- line: 1,
57
- col: 1,
58
- severity: "error",
59
- code: x,
60
- message: "[FileHeaderCheck#check] Missing // @file: directive"
61
- }), e.push({
62
- file: t,
63
- line: 1,
64
- col: 1,
65
- severity: "error",
66
- code: A,
67
- message: "[FileHeaderCheck#check] Missing // @consumers: directive"
68
- }), e;
69
- const s = i.split(`
70
- `);
71
- let n = !1, r = !1;
72
- for (const o of s) {
73
- const c = o.trim();
74
- if (c.startsWith("import ") || (c.startsWith("// @file:") && (n = !0), c.startsWith("// @consumers:") && (r = !0), n && r))
75
- break;
76
- }
77
- return n || e.push({
78
- file: t,
79
- line: 1,
80
- col: 1,
81
- severity: "error",
82
- code: x,
83
- message: "[FileHeaderCheck#check] Missing // @file: directive"
84
- }), r || e.push({
85
- file: t,
86
- line: 1,
87
- col: 1,
88
- severity: "error",
89
- code: A,
90
- message: "[FileHeaderCheck#check] Missing // @consumers: directive"
91
- }), e;
92
- }
93
- const re = /\/\/ #(region|endregion)\s+(START|END)_([A-Z0-9_]+)/, oe = /\/\/ #(region|endregion)\s*$/;
94
- function ie(i, t) {
95
- const e = i.split(`
96
- `), s = [], n = [];
97
- for (let r = 0; r < e.length; r++) {
98
- const o = e[r], c = o.match(re);
99
- if (c) {
100
- const a = c[2], l = c[3], h = r + 1, p = c.index ?? 0, I = o.indexOf(a, p), L = (I >= 0 ? I : p) + 1;
101
- if (a === "START") {
102
- n.push({ name: l, line: h, col: L });
103
- continue;
104
- }
105
- const R = ce(n, (u) => u.name === l);
106
- if (R === -1)
107
- s.push({
108
- file: t,
109
- line: h,
110
- col: L,
111
- severity: "error",
112
- code: Y,
113
- message: `END_${l} without matching START_${l} — add the missing opening anchor or remove this closing one`
114
- });
115
- else {
116
- for (let u = n.length - 1; u > R; u--) {
117
- const g = n[u];
118
- s.push({
119
- file: t,
120
- line: h,
121
- col: L,
122
- severity: "error",
123
- code: q,
124
- message: `END_${l} closes parent while START_${g.name} at line ${g.line} is still open — close inner block first`
125
- });
126
- }
127
- n.length = R;
128
- }
129
- continue;
130
- }
131
- const f = o.match(oe);
132
- if (f) {
133
- const a = r + 1, l = (f.index ?? 0) + 1;
134
- if (f[1] === "endregion")
135
- if (n.length > 0) {
136
- const h = n[n.length - 1];
137
- s.push({
138
- file: t,
139
- line: a,
140
- col: l,
141
- severity: "error",
142
- code: C,
143
- message: `#endregion without END_<NAME> — expected END_${h.name} (auto-closed by stack top START_${h.name} at line ${h.line})`
144
- }), n.pop();
145
- } else
146
- s.push({
147
- file: t,
148
- line: a,
149
- col: l,
150
- severity: "error",
151
- code: C,
152
- message: "#endregion without END_<NAME> — no open block to close"
153
- });
154
- else
155
- s.push({
156
- file: t,
157
- line: a,
158
- col: l,
159
- severity: "error",
160
- code: C,
161
- message: "#region without START_<NAME> — add START_ prefix with a block name"
162
- });
163
- }
164
- }
165
- for (const r of n)
166
- s.push({
167
- file: t,
168
- line: r.line,
169
- col: r.col,
170
- severity: "error",
171
- code: X,
172
- message: `START_${r.name} without matching END_${r.name} — add the missing closing anchor`
173
- });
174
- return s.sort((r, o) => r.line - o.line || r.col - o.col), s;
175
- }
176
- function ce(i, t) {
177
- for (let e = i.length - 1; e >= 0; e--)
178
- if (t(i[e])) return e;
179
- return -1;
180
- }
181
- async function ae(i, t, e) {
182
- d.debug(`[DbcContractCheck#check] [idle → creating] ${t}`);
183
- const s = new J(), n = new Z(), r = new z(s, n);
184
- try {
185
- if (!e) {
186
- const c = await r.lint(t, { content: i });
187
- return d.info(
188
- `[DbcContractCheck#check] [creating → linted] ${t} (${c.errors.length} errors)`
189
- ), { errors: c.errors.map(v), autoFixed: 0 };
190
- }
191
- const o = await r.lintAndFix(t, { content: i });
192
- return d.info(
193
- `[DbcContractCheck#check] [creating → fixed] ${t} (autoFixed=${o.autoFixed}, remaining=${o.errors.length})`
194
- ), {
195
- errors: o.errors.map(v),
196
- autoFixed: o.autoFixed
197
- };
198
- } catch (o) {
199
- const c = new Error(`[DbcContractCheck#check] Lint failed for ${t}`, { cause: o });
200
- throw d.error(`[DbcContractCheck#check] [creating → failed] ${t}`, { error: c }), c;
201
- }
202
- }
203
- function v(i) {
204
- return {
205
- file: i.file,
206
- line: i.line,
207
- col: i.col,
208
- severity: "error",
209
- code: i.code,
210
- message: i.message
211
- };
212
- }
213
- const w = 8, le = /@ts-ignore|@ts-nocheck|@ts-expect-error|eslint-disable(?:-next-line|-line)?(?:-[a-z-]+)?\b/, ue = /\bd-\d+\b/i;
214
- function fe(i) {
215
- let t = !1, e = !1, s = !1;
216
- for (let n = 0; n < i.length - 1; n++) {
217
- const r = i[n], o = n > 0 ? i[n - 1] : "";
218
- if (!t && !e && !s) {
219
- if (r === "/" && (i[n + 1] === "/" || i[n + 1] === "*")) return n;
220
- r === "'" ? t = !0 : r === '"' ? e = !0 : r === "`" && (s = !0);
221
- } else o !== "\\" && (t && r === "'" ? t = !1 : e && r === '"' ? e = !1 : s && r === "`" && (s = !1));
222
- }
223
- return -1;
224
- }
225
- function de(i, t) {
226
- const e = i.split(`
227
- `), s = [];
228
- for (let n = 0; n < e.length; n++) {
229
- const r = e[n], o = fe(r);
230
- if (o < 0) continue;
231
- const c = r.slice(o), f = le.exec(c);
232
- if (!f) continue;
233
- const a = f[0], l = o + f.index + 1, h = ue.exec(r);
234
- if (!h) {
235
- s.push({
236
- file: t,
237
- line: n + 1,
238
- col: l,
239
- severity: "error",
240
- code: te,
241
- message: `Unauthorized disable: \`${a}\` has no Decision Log reference. Add \`D-NNN\` (e.g., \`D-042\`) in the same comment line pointing to a Decision Log entry that authorizes this disable. Policy: see specs/cli/cli.spec.md#d-007.`
242
- });
243
- continue;
244
- }
245
- const p = he(c, a, h[0]);
246
- p < w && s.push({
247
- file: t,
248
- line: n + 1,
249
- col: l,
250
- severity: "error",
251
- code: se,
252
- message: `Disable lacks purpose: \`${a}\` cites \`${h[0]}\` but the explanation is too short (${p} non-whitespace chars; need ≥ ${w}). Add a purpose after the D-NNN reference, e.g., \`${a}: ${h[0]} — <why this disable is necessary>\`. Policy: see specs/cli/cli.spec.md#d-007.`
253
- });
254
- }
255
- return s;
256
- }
257
- function he(i, t, e) {
258
- let s = i.replace(t, "");
259
- return s = s.replace(e, ""), s = s.replace(/\*\//g, ""), s = s.replace(/^\/\/|^\/\*/g, ""), s.replace(/\s/g, "").length;
260
- }
261
- const F = new RegExp("\\p{Script=Cyrillic}", "u");
262
- function ge(i, t) {
263
- const e = [], s = i.split(`
264
- `), n = me(s);
265
- for (let r = 0; r < s.length; r++) {
266
- const o = s[r], c = r + 1, f = o.trim();
267
- if (f.startsWith("// @file:") || f.startsWith("// @consumers:")) {
268
- const a = [...o];
269
- for (let l = 0; l < a.length; l++)
270
- F.test(a[l]) && e.push({
271
- file: t,
272
- line: c,
273
- col: l + 1,
274
- severity: "error",
275
- code: b,
276
- message: `[LanguageCheck#check] Cyrillic character '${a[l]}' in file header — use English only`
277
- });
278
- }
279
- if (n.has(r)) {
280
- const a = [...o];
281
- for (let l = 0; l < a.length; l++)
282
- if (F.test(a[l])) {
283
- e.push({
284
- file: t,
285
- line: c,
286
- col: l + 1,
287
- severity: "error",
288
- code: b,
289
- message: `[LanguageCheck#check] Cyrillic character '${a[l]}' in JSDoc contract — use English only`
290
- });
291
- break;
292
- }
293
- }
294
- }
295
- return e;
296
- }
297
- function me(i) {
298
- const t = /* @__PURE__ */ new Set();
299
- let e = !1;
300
- for (let s = 0; s < i.length; s++) {
301
- const n = i[s].trim();
302
- if (n.startsWith("/**")) {
303
- e = !0, t.add(s), n.endsWith("*/") && (e = !1);
304
- continue;
305
- }
306
- e && (t.add(s), n.includes("*/") && (e = !1));
307
- }
308
- return t;
309
- }
310
- function pe(i, t = "tasks") {
311
- const e = /* @__PURE__ */ new Map(), s = _(i, t);
312
- if (!O(s))
313
- return e;
314
- const n = Le(s);
315
- for (const r of n) {
316
- let o;
317
- try {
318
- o = M(r, "utf-8");
319
- } catch {
320
- continue;
321
- }
322
- const c = o.match(/-\s+\*\*Task-ID:\*\*\s+(TSK-\d+)/);
323
- if (!c) continue;
324
- const f = c[1], a = H(i, r), l = _e(o, i);
325
- e.set(f, { taskPath: a, specPaths: l });
326
- }
327
- return e;
328
- }
329
- function _e(i, t) {
330
- const e = /* @__PURE__ */ new Set(), s = i.match(/\*\*Spec References:\*\*[\s\S]*?(?=\n- \*\*|$)/);
331
- if (!s) return [];
332
- const n = s[0], r = /\[([^\]]*)\]\(([^)]+\.md)[^)]*\)/g;
333
- let o;
334
- for (; (o = r.exec(n)) !== null; ) {
335
- const c = o[2].split("/").pop();
336
- if (!c) continue;
337
- const f = Re(_(t, "specs"), c);
338
- if (f) {
339
- const a = H(t, f);
340
- a.startsWith("..") || e.add(a);
341
- }
342
- }
343
- return [...e].sort();
344
- }
345
- function Re(i, t) {
346
- if (!O(i)) return null;
347
- const e = [i];
348
- for (; e.length > 0; ) {
349
- const s = e.pop();
350
- let n;
351
- try {
352
- n = y(s);
353
- } catch {
354
- continue;
355
- }
356
- for (const r of n) {
357
- const o = _(s, r);
358
- try {
359
- const c = P(o);
360
- if (c.isDirectory())
361
- e.push(o);
362
- else if (c.isFile() && r === t)
363
- return o;
364
- } catch {
365
- }
366
- }
367
- }
368
- return null;
369
- }
370
- function Le(i) {
371
- const t = [], e = [i];
372
- for (; e.length > 0; ) {
373
- const s = e.pop();
374
- let n;
375
- try {
376
- n = y(s);
377
- } catch {
378
- continue;
379
- }
380
- for (const r of n) {
381
- const o = _(s, r);
382
- try {
383
- const c = P(o);
384
- c.isDirectory() ? e.push(o) : c.isFile() && r.endsWith(".md") && t.push(o);
385
- } catch {
386
- }
387
- }
388
- }
389
- return t;
390
- }
391
- function Ie(i) {
392
- const t = i.match(/@tasks:\s*(.+)/m);
393
- return t ? t[1].split(/[,;\s]+/).map((e) => e.trim()).filter((e) => /^TSK-\d+$/.test(e)) : [];
394
- }
395
- function Ne(i, t) {
396
- const e = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set();
397
- for (const n of i) {
398
- const r = t.get(n);
399
- if (r) {
400
- e.add(r.taskPath);
401
- for (const o of r.specPaths)
402
- s.add(o);
403
- }
404
- }
405
- return {
406
- taskPaths: [...e].sort(),
407
- specPaths: [...s].sort()
408
- };
409
- }
410
- async function Ee(i) {
411
- const t = V(i, {
412
- autofix: ["autofix"],
413
- staged: ["staged"],
414
- verbose: ["verbose", "v"]
415
- }), e = t._.filter(
416
- (u) => typeof u == "string" && u !== "lint"
417
- ), s = t.autofix === !0 || t.autofix === "true", n = t.staged === !0 || t.staged === "true";
418
- (t.verbose === !0 || t.verbose === "true") && j("debug");
419
- let o;
420
- const c = [];
421
- if (n) {
422
- if (e.length > 0) {
423
- const u = {
424
- file: "",
425
- line: 0,
426
- col: 0,
427
- severity: "error",
428
- code: ee,
429
- message: "--staged and positional targets are mutually exclusive. Use either --staged or provide file/directory paths, not both."
430
- };
431
- return d.warn("[LintCommand#run] --staged and positional targets are mutually exclusive"), new E([u]);
432
- }
433
- d.debug("[LintCommand#run] [idle → collecting] staged mode");
434
- try {
435
- const u = $("git diff --staged --name-only", { encoding: "utf-8" }).trim(), g = $("git ls-files --others --exclude-standard", {
436
- encoding: "utf-8"
437
- }).trim();
438
- o = [...u.split(`
439
- `), ...g.split(`
440
- `)].filter(Boolean).filter((m) => m.endsWith(".ts")), o = [...new Set(o)];
441
- } catch (u) {
442
- const g = new Error("[LintCommand#run] Git scan failed — not a git repository?", {
443
- cause: u
444
- });
445
- throw d.error("[LintCommand#run] [collecting → failed]", { error: g }), g;
446
- }
447
- } else if (e.length > 0) {
448
- d.debug(`[LintCommand#run] [idle → resolving] ${e.length} target(s)`);
449
- const u = ke(e);
450
- o = u.files, c.push(...u.errors);
451
- for (const g of u.errors)
452
- d.warn(`[LintCommand#run] [resolving → failed] ${g.file}: ${g.message}`);
453
- } else
454
- o = [];
455
- if (o.length === 0)
456
- return d.debug("[LintCommand#run] [collecting → done] no files to lint"), new E(c);
457
- d.debug(`[LintCommand#run] [collecting → linting] ${o.length} file(s)`);
458
- const f = [...c];
459
- let a = 0;
460
- const l = _("."), h = pe(l), p = /* @__PURE__ */ new Set();
461
- for (const u of o) {
462
- const g = _(u);
463
- let m;
464
- try {
465
- d.debug(`[LintCommand#run] [linting → reading] ${u}`), m = M(g, "utf-8");
466
- } catch (N) {
467
- const G = new Error(`[LintCommand#run] Cannot read file: ${u}`, { cause: N });
468
- d.error(`[LintCommand#run] [reading → failed] ${u}`, { error: G });
469
- continue;
470
- }
471
- f.push(...ne(m, u)), f.push(...ie(m, u)), f.push(...ge(m, u)), f.push(...de(m, u));
472
- const W = Ie(m);
473
- for (const N of W)
474
- p.add(N);
475
- const D = await ae(m, u, s);
476
- f.push(...D.errors), a += D.autoFixed;
477
- }
478
- const { taskPaths: I, specPaths: L } = Ne([...p], h), R = new E(f, a, I, L);
479
- return R.exitCode === 1 ? console.log(`[LintCommand#run] [linting → failed] ${f.length} error(s)`) : console.log("[LintCommand#run] [linting → clean] no errors"), R;
480
- }
481
- const S = [".ts", ".tsx"], Ce = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage", "build", "out", "__tests__"]);
482
- function ke(i) {
483
- d.debug(`[resolveTargets] [idle → resolving] ${i.length} target(s)`);
484
- const t = /* @__PURE__ */ new Set(), e = [];
485
- for (const n of i) {
486
- const r = k(n).toLowerCase();
487
- if (r && !S.includes(r) && !n.endsWith("/"))
488
- continue;
489
- let o;
490
- try {
491
- o = B(n);
492
- } catch (f) {
493
- const a = f;
494
- e.push({
495
- file: n,
496
- line: 0,
497
- col: 0,
498
- severity: "error",
499
- code: Q,
500
- message: `${n}: ${a.code ?? "UNKNOWN"}: ${a.message}`
501
- });
502
- continue;
503
- }
504
- if (o.isSymbolicLink())
505
- continue;
506
- const c = _(n);
507
- if (o.isDirectory())
508
- U(c, t);
509
- else if (o.isFile()) {
510
- const f = k(n).toLowerCase();
511
- S.includes(f) && t.add(c);
512
- }
513
- }
514
- const s = [...t].sort();
515
- return d.debug(
516
- `[resolveTargets] [resolving → resolved] ${s.length} file(s), ${e.length} error(s)`
517
- ), { files: s, errors: e };
518
- }
519
- function U(i, t) {
520
- let e;
521
- try {
522
- e = y(i, { withFileTypes: !0 });
523
- } catch {
524
- return;
525
- }
526
- for (const s of e) {
527
- const n = K(i, s.name);
528
- if (!s.name.startsWith(".") && !Ce.has(s.name) && !s.isSymbolicLink()) {
529
- if (s.isDirectory())
530
- U(n, t);
531
- else if (s.isFile()) {
532
- const r = k(s.name).toLowerCase();
533
- S.includes(r) && t.add(n);
534
- }
535
- }
536
- }
537
- }
538
- const T = await Ee(process.argv);
539
- T.exitCode === 1 && console.log(T.format());
540
- process.exit(T.exitCode);