archcheck 0.2.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 (251) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +536 -0
  3. package/dist/archcheck.d.ts +99 -0
  4. package/dist/archcheck.d.ts.map +1 -0
  5. package/dist/archcheck.js +339 -0
  6. package/dist/archcheck.js.map +1 -0
  7. package/dist/baseline/index.d.ts +29 -0
  8. package/dist/baseline/index.d.ts.map +1 -0
  9. package/dist/baseline/index.js +116 -0
  10. package/dist/baseline/index.js.map +1 -0
  11. package/dist/cli/args.d.ts +36 -0
  12. package/dist/cli/args.d.ts.map +1 -0
  13. package/dist/cli/args.js +233 -0
  14. package/dist/cli/args.js.map +1 -0
  15. package/dist/cli/index.d.ts +4 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +219 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/version.d.ts +2 -0
  20. package/dist/cli/version.d.ts.map +1 -0
  21. package/dist/cli/version.js +29 -0
  22. package/dist/cli/version.js.map +1 -0
  23. package/dist/contracts/banned-syntax.d.ts +48 -0
  24. package/dist/contracts/banned-syntax.d.ts.map +1 -0
  25. package/dist/contracts/banned-syntax.js +201 -0
  26. package/dist/contracts/banned-syntax.js.map +1 -0
  27. package/dist/contracts/declared-field.d.ts +39 -0
  28. package/dist/contracts/declared-field.d.ts.map +1 -0
  29. package/dist/contracts/declared-field.js +142 -0
  30. package/dist/contracts/declared-field.js.map +1 -0
  31. package/dist/contracts/encapsulation.d.ts +28 -0
  32. package/dist/contracts/encapsulation.d.ts.map +1 -0
  33. package/dist/contracts/encapsulation.js +130 -0
  34. package/dist/contracts/encapsulation.js.map +1 -0
  35. package/dist/contracts/index.d.ts +10 -0
  36. package/dist/contracts/index.d.ts.map +1 -0
  37. package/dist/contracts/index.js +9 -0
  38. package/dist/contracts/index.js.map +1 -0
  39. package/dist/contracts/judgement.d.ts +21 -0
  40. package/dist/contracts/judgement.d.ts.map +1 -0
  41. package/dist/contracts/judgement.js +109 -0
  42. package/dist/contracts/judgement.js.map +1 -0
  43. package/dist/contracts/layers.d.ts +75 -0
  44. package/dist/contracts/layers.d.ts.map +1 -0
  45. package/dist/contracts/layers.js +244 -0
  46. package/dist/contracts/layers.js.map +1 -0
  47. package/dist/contracts/naming.d.ts +21 -0
  48. package/dist/contracts/naming.d.ts.map +1 -0
  49. package/dist/contracts/naming.js +120 -0
  50. package/dist/contracts/naming.js.map +1 -0
  51. package/dist/contracts/registry.d.ts +23 -0
  52. package/dist/contracts/registry.d.ts.map +1 -0
  53. package/dist/contracts/registry.js +48 -0
  54. package/dist/contracts/registry.js.map +1 -0
  55. package/dist/contracts/required-file.d.ts +29 -0
  56. package/dist/contracts/required-file.d.ts.map +1 -0
  57. package/dist/contracts/required-file.js +131 -0
  58. package/dist/contracts/required-file.js.map +1 -0
  59. package/dist/contracts/types.d.ts +61 -0
  60. package/dist/contracts/types.d.ts.map +1 -0
  61. package/dist/contracts/types.js +2 -0
  62. package/dist/contracts/types.js.map +1 -0
  63. package/dist/coverage/index.d.ts +55 -0
  64. package/dist/coverage/index.d.ts.map +1 -0
  65. package/dist/coverage/index.js +68 -0
  66. package/dist/coverage/index.js.map +1 -0
  67. package/dist/emit/collect.d.ts +20 -0
  68. package/dist/emit/collect.d.ts.map +1 -0
  69. package/dist/emit/collect.js +17 -0
  70. package/dist/emit/collect.js.map +1 -0
  71. package/dist/emit/header.d.ts +21 -0
  72. package/dist/emit/header.d.ts.map +1 -0
  73. package/dist/emit/header.js +20 -0
  74. package/dist/emit/header.js.map +1 -0
  75. package/dist/emit/index.d.ts +57 -0
  76. package/dist/emit/index.d.ts.map +1 -0
  77. package/dist/emit/index.js +128 -0
  78. package/dist/emit/index.js.map +1 -0
  79. package/dist/emit/merge.d.ts +23 -0
  80. package/dist/emit/merge.d.ts.map +1 -0
  81. package/dist/emit/merge.js +71 -0
  82. package/dist/emit/merge.js.map +1 -0
  83. package/dist/emit/write.d.ts +20 -0
  84. package/dist/emit/write.d.ts.map +1 -0
  85. package/dist/emit/write.js +61 -0
  86. package/dist/emit/write.js.map +1 -0
  87. package/dist/exceptions/index.d.ts +46 -0
  88. package/dist/exceptions/index.d.ts.map +1 -0
  89. package/dist/exceptions/index.js +117 -0
  90. package/dist/exceptions/index.js.map +1 -0
  91. package/dist/fs/index.d.ts +12 -0
  92. package/dist/fs/index.d.ts.map +1 -0
  93. package/dist/fs/index.js +78 -0
  94. package/dist/fs/index.js.map +1 -0
  95. package/dist/graph/cache.d.ts +12 -0
  96. package/dist/graph/cache.d.ts.map +1 -0
  97. package/dist/graph/cache.js +76 -0
  98. package/dist/graph/cache.js.map +1 -0
  99. package/dist/graph/edges.d.ts +16 -0
  100. package/dist/graph/edges.d.ts.map +1 -0
  101. package/dist/graph/edges.js +161 -0
  102. package/dist/graph/edges.js.map +1 -0
  103. package/dist/graph/index.d.ts +15 -0
  104. package/dist/graph/index.d.ts.map +1 -0
  105. package/dist/graph/index.js +90 -0
  106. package/dist/graph/index.js.map +1 -0
  107. package/dist/graph/match.d.ts +12 -0
  108. package/dist/graph/match.d.ts.map +1 -0
  109. package/dist/graph/match.js +35 -0
  110. package/dist/graph/match.js.map +1 -0
  111. package/dist/graph/program.d.ts +12 -0
  112. package/dist/graph/program.d.ts.map +1 -0
  113. package/dist/graph/program.js +54 -0
  114. package/dist/graph/program.js.map +1 -0
  115. package/dist/graph/types.d.ts +55 -0
  116. package/dist/graph/types.d.ts.map +1 -0
  117. package/dist/graph/types.js +2 -0
  118. package/dist/graph/types.js.map +1 -0
  119. package/dist/index.d.ts +21 -0
  120. package/dist/index.d.ts.map +1 -0
  121. package/dist/index.js +20 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/init/index.d.ts +23 -0
  124. package/dist/init/index.d.ts.map +1 -0
  125. package/dist/init/index.js +218 -0
  126. package/dist/init/index.js.map +1 -0
  127. package/dist/normalize/identity.d.ts +4 -0
  128. package/dist/normalize/identity.d.ts.map +1 -0
  129. package/dist/normalize/identity.js +33 -0
  130. package/dist/normalize/identity.js.map +1 -0
  131. package/dist/normalize/index.d.ts +3 -0
  132. package/dist/normalize/index.d.ts.map +1 -0
  133. package/dist/normalize/index.js +3 -0
  134. package/dist/normalize/index.js.map +1 -0
  135. package/dist/normalize/normalize.d.ts +34 -0
  136. package/dist/normalize/normalize.d.ts.map +1 -0
  137. package/dist/normalize/normalize.js +91 -0
  138. package/dist/normalize/normalize.js.map +1 -0
  139. package/dist/probes/graph.d.ts +19 -0
  140. package/dist/probes/graph.d.ts.map +1 -0
  141. package/dist/probes/graph.js +181 -0
  142. package/dist/probes/graph.js.map +1 -0
  143. package/dist/probes/index.d.ts +5 -0
  144. package/dist/probes/index.d.ts.map +1 -0
  145. package/dist/probes/index.js +5 -0
  146. package/dist/probes/index.js.map +1 -0
  147. package/dist/probes/lint.d.ts +17 -0
  148. package/dist/probes/lint.d.ts.map +1 -0
  149. package/dist/probes/lint.js +121 -0
  150. package/dist/probes/lint.js.map +1 -0
  151. package/dist/probes/model/anthropic.d.ts +47 -0
  152. package/dist/probes/model/anthropic.d.ts.map +1 -0
  153. package/dist/probes/model/anthropic.js +100 -0
  154. package/dist/probes/model/anthropic.js.map +1 -0
  155. package/dist/probes/model/budget.d.ts +22 -0
  156. package/dist/probes/model/budget.d.ts.map +1 -0
  157. package/dist/probes/model/budget.js +27 -0
  158. package/dist/probes/model/budget.js.map +1 -0
  159. package/dist/probes/model/cache.d.ts +13 -0
  160. package/dist/probes/model/cache.d.ts.map +1 -0
  161. package/dist/probes/model/cache.js +74 -0
  162. package/dist/probes/model/cache.js.map +1 -0
  163. package/dist/probes/model/index.d.ts +20 -0
  164. package/dist/probes/model/index.d.ts.map +1 -0
  165. package/dist/probes/model/index.js +160 -0
  166. package/dist/probes/model/index.js.map +1 -0
  167. package/dist/probes/model/prompt.d.ts +16 -0
  168. package/dist/probes/model/prompt.d.ts.map +1 -0
  169. package/dist/probes/model/prompt.js +57 -0
  170. package/dist/probes/model/prompt.js.map +1 -0
  171. package/dist/probes/model/provider.d.ts +88 -0
  172. package/dist/probes/model/provider.d.ts.map +1 -0
  173. package/dist/probes/model/provider.js +48 -0
  174. package/dist/probes/model/provider.js.map +1 -0
  175. package/dist/probes/structure.d.ts +3 -0
  176. package/dist/probes/structure.d.ts.map +1 -0
  177. package/dist/probes/structure.js +95 -0
  178. package/dist/probes/structure.js.map +1 -0
  179. package/dist/probes/types.d.ts +46 -0
  180. package/dist/probes/types.d.ts.map +1 -0
  181. package/dist/probes/types.js +15 -0
  182. package/dist/probes/types.js.map +1 -0
  183. package/dist/registry/define.d.ts +40 -0
  184. package/dist/registry/define.d.ts.map +1 -0
  185. package/dist/registry/define.js +4 -0
  186. package/dist/registry/define.js.map +1 -0
  187. package/dist/registry/ids.d.ts +19 -0
  188. package/dist/registry/ids.d.ts.map +1 -0
  189. package/dist/registry/ids.js +86 -0
  190. package/dist/registry/ids.js.map +1 -0
  191. package/dist/registry/index.d.ts +45 -0
  192. package/dist/registry/index.d.ts.map +1 -0
  193. package/dist/registry/index.js +71 -0
  194. package/dist/registry/index.js.map +1 -0
  195. package/dist/registry/load.d.ts +14 -0
  196. package/dist/registry/load.d.ts.map +1 -0
  197. package/dist/registry/load.js +108 -0
  198. package/dist/registry/load.js.map +1 -0
  199. package/dist/registry/validate.d.ts +24 -0
  200. package/dist/registry/validate.d.ts.map +1 -0
  201. package/dist/registry/validate.js +160 -0
  202. package/dist/registry/validate.js.map +1 -0
  203. package/dist/report/index.d.ts +10 -0
  204. package/dist/report/index.d.ts.map +1 -0
  205. package/dist/report/index.js +30 -0
  206. package/dist/report/index.js.map +1 -0
  207. package/dist/report/json.d.ts +20 -0
  208. package/dist/report/json.d.ts.map +1 -0
  209. package/dist/report/json.js +34 -0
  210. package/dist/report/json.js.map +1 -0
  211. package/dist/report/sarif.d.ts +21 -0
  212. package/dist/report/sarif.d.ts.map +1 -0
  213. package/dist/report/sarif.js +138 -0
  214. package/dist/report/sarif.js.map +1 -0
  215. package/dist/report/terminal.d.ts +3 -0
  216. package/dist/report/terminal.d.ts.map +1 -0
  217. package/dist/report/terminal.js +117 -0
  218. package/dist/report/terminal.js.map +1 -0
  219. package/dist/report/types.d.ts +28 -0
  220. package/dist/report/types.d.ts.map +1 -0
  221. package/dist/report/types.js +11 -0
  222. package/dist/report/types.js.map +1 -0
  223. package/dist/report/verdict.d.ts +21 -0
  224. package/dist/report/verdict.d.ts.map +1 -0
  225. package/dist/report/verdict.js +31 -0
  226. package/dist/report/verdict.js.map +1 -0
  227. package/dist/result.d.ts +22 -0
  228. package/dist/result.d.ts.map +1 -0
  229. package/dist/result.js +19 -0
  230. package/dist/result.js.map +1 -0
  231. package/dist/types.d.ts +178 -0
  232. package/dist/types.d.ts.map +1 -0
  233. package/dist/types.js +11 -0
  234. package/dist/types.js.map +1 -0
  235. package/dist/util/compilerApi.d.ts +2 -0
  236. package/dist/util/compilerApi.d.ts.map +1 -0
  237. package/dist/util/compilerApi.js +28 -0
  238. package/dist/util/compilerApi.js.map +1 -0
  239. package/dist/util/glob.d.ts +43 -0
  240. package/dist/util/glob.d.ts.map +1 -0
  241. package/dist/util/glob.js +195 -0
  242. package/dist/util/glob.js.map +1 -0
  243. package/dist/util/paths.d.ts +6 -0
  244. package/dist/util/paths.d.ts.map +1 -0
  245. package/dist/util/paths.js +22 -0
  246. package/dist/util/paths.js.map +1 -0
  247. package/dist/version.d.ts +13 -0
  248. package/dist/version.d.ts.map +1 -0
  249. package/dist/version.js +12 -0
  250. package/dist/version.js.map +1 -0
  251. package/package.json +72 -0
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Argument parsing, and nothing else.
3
+ *
4
+ * What a caller must know: this returns a Result too. An unknown flag is a CONFIG-class mistake —
5
+ * exit 2, not 1 — because an agent that typed the wrong flag must not read "no violations" as
6
+ * success.
7
+ */
8
+ import { execFileSync } from 'node:child_process';
9
+ import { err, ok } from '../result.js';
10
+ const FORMATS = {
11
+ terminal: 'terminal',
12
+ json: 'json',
13
+ 'json-pretty': 'json-pretty',
14
+ sarif: 'sarif',
15
+ verdict: 'verdict',
16
+ };
17
+ const TIERS = {
18
+ deterministic: 'deterministic',
19
+ proxy: 'proxy',
20
+ model: 'model',
21
+ };
22
+ export const HELP = `archcheck — architecture conformance, declared once and checked everywhere
23
+
24
+ archcheck run every rule, terminal output
25
+ archcheck --changed diff-scoped · the pre-commit path
26
+ archcheck --format json the agent format
27
+ archcheck --format sarif SARIF 2.1.0, for CI code scanning and editors
28
+ archcheck --format verdict one blocking answer, for a hook
29
+ archcheck --only deterministic skip the proxy and model tiers
30
+ archcheck --show-baselined include findings the baseline records
31
+ archcheck --write-graph write .archcheck/graph.json for later gates to ingest
32
+ archcheck --ingest-graph read .archcheck/graph.json instead of re-reading the graph
33
+
34
+ archcheck emit regenerate the emitted configs
35
+ archcheck emit --check fail if the committed output is stale
36
+ archcheck explain <ruleId> statement, remedy and current violations
37
+ archcheck coverage the three counts, computed from the manifest
38
+ archcheck baseline --write record today's violations as pre-existing debt
39
+ archcheck baseline --prune drop entries that no longer reproduce
40
+ archcheck init write a starting architecture.config.ts from the folders
41
+ archcheck --version
42
+
43
+ exit codes
44
+ 0 clean, or only baselined and advisory findings
45
+ 1 new violations of error-severity rules → fix the code
46
+ 2 configuration invalid → fix the manifest, not the code
47
+ 3 emitted output is stale → run archcheck emit
48
+ 4 a baselined finding no longer reproduces → run archcheck baseline --prune
49
+ `;
50
+ /**
51
+ * Ask git for the changed set. Local only — archcheck makes no network call it was not told to.
52
+ *
53
+ * A git that cannot answer is a CONFIG failure (exit 2), never an empty changed set. git missing
54
+ * from PATH, an unborn or detached HEAD, or a directory outside any work tree used to be swallowed
55
+ * by a bare catch returning `[]`: every probe then filtered to nothing and the run reported clean,
56
+ * so a pre-commit hook passed every commit forever. Exit 2 because the manifest and the code are
57
+ * both fine — the environment is not, which is the same call `init` makes when it cannot read the
58
+ * module graph. `tests/cli.test.ts` → '--changed > git failing is a config error (2)' pins it.
59
+ */
60
+ export function gitChangedFiles(cwd) {
61
+ const files = new Set();
62
+ for (const args of [
63
+ ['diff', '--name-only', '--diff-filter=ACMR', 'HEAD'],
64
+ ['diff', '--name-only', '--diff-filter=ACMR', '--cached'],
65
+ ['ls-files', '--others', '--exclude-standard'],
66
+ ]) {
67
+ let output;
68
+ try {
69
+ output = execFileSync('git', args, {
70
+ cwd,
71
+ encoding: 'utf8',
72
+ stdio: ['ignore', 'pipe', 'pipe'],
73
+ });
74
+ }
75
+ catch (error) {
76
+ const said = error.stderr;
77
+ const detail = said === undefined || said.trim() === '' ? describeError(error) : said.trim();
78
+ return err([
79
+ `--changed asked git for the changed set, and \`git ${args.join(' ')}\` failed:`,
80
+ // git answers a misuse with its whole usage screen. The first two lines carry the reason;
81
+ // the rest would bury the two suggestions below.
82
+ ...detail
83
+ .split('\n')
84
+ .filter((line) => line.trim() !== '')
85
+ .slice(0, 2)
86
+ .map((line) => ` ${line.trim()}`),
87
+ ' → the environment is wrong, not the code: an empty changed set would check nothing',
88
+ ' → name the files yourself (--changed a.ts,b.ts), or drop --changed to check everything',
89
+ ]);
90
+ }
91
+ for (const line of output.split('\n')) {
92
+ const file = line.trim();
93
+ if (file.length > 0)
94
+ files.add(file);
95
+ }
96
+ }
97
+ return ok([...files].sort());
98
+ }
99
+ function describeError(error) {
100
+ return error instanceof Error ? error.message : String(error);
101
+ }
102
+ export function parseArgs(argv) {
103
+ const parsed = {
104
+ command: 'check',
105
+ format: 'terminal',
106
+ emitCheck: false,
107
+ force: false,
108
+ showBaselined: false,
109
+ ingestGraph: false,
110
+ writeGraph: false,
111
+ noColor: false,
112
+ };
113
+ const errors = [];
114
+ const rest = [...argv];
115
+ let sawCommand = false;
116
+ // The subcommand is recognised WHEREVER it appears, not only at argv[0]. `--cwd x baseline
117
+ // --write` is a perfectly natural thing to type, and a parser that silently rejected it read
118
+ // as "unexpected argument 'baseline'" — which names the wrong thing.
119
+ const COMMANDS = new Set(['check', 'emit', 'explain', 'coverage', 'baseline', 'init']);
120
+ while (rest.length > 0) {
121
+ const arg = rest.shift();
122
+ const [flag, inlineValue] = arg.startsWith('--') && arg.includes('=')
123
+ ? [arg.slice(0, arg.indexOf('=')), arg.slice(arg.indexOf('=') + 1)]
124
+ : [arg, undefined];
125
+ const takeValue = () => inlineValue ?? (rest[0]?.startsWith('-') === false ? rest.shift() : undefined);
126
+ switch (flag) {
127
+ case '--version':
128
+ case '-v':
129
+ parsed.command = 'version';
130
+ break;
131
+ case '--help':
132
+ case '-h':
133
+ parsed.command = 'help';
134
+ break;
135
+ case '--format': {
136
+ const value = takeValue();
137
+ const format = value === undefined ? undefined : FORMATS[value];
138
+ if (format === undefined) {
139
+ errors.push(`--format expects one of ${Object.keys(FORMATS).join(', ')} (got ${String(value)})`);
140
+ }
141
+ else {
142
+ parsed.format = format;
143
+ }
144
+ break;
145
+ }
146
+ case '--only': {
147
+ const value = takeValue();
148
+ const tier = value === undefined ? undefined : TIERS[value];
149
+ if (tier === undefined) {
150
+ errors.push(`--only expects one of ${Object.keys(TIERS).join(', ')} (got ${String(value)})`);
151
+ }
152
+ else {
153
+ parsed.only = tier;
154
+ }
155
+ break;
156
+ }
157
+ case '--changed': {
158
+ const value = takeValue();
159
+ parsed.changed =
160
+ value === undefined
161
+ ? []
162
+ : value
163
+ .split(',')
164
+ .map((f) => f.trim())
165
+ .filter(Boolean);
166
+ break;
167
+ }
168
+ case '--check':
169
+ parsed.emitCheck = true;
170
+ break;
171
+ case '--write':
172
+ parsed.baselineMode = 'write';
173
+ break;
174
+ case '--prune':
175
+ parsed.baselineMode = 'prune';
176
+ break;
177
+ case '--force':
178
+ parsed.force = true;
179
+ break;
180
+ case '--show-baselined':
181
+ parsed.showBaselined = true;
182
+ break;
183
+ case '--ingest-graph':
184
+ parsed.ingestGraph = true;
185
+ break;
186
+ case '--write-graph':
187
+ parsed.writeGraph = true;
188
+ break;
189
+ case '--no-color':
190
+ parsed.noColor = true;
191
+ break;
192
+ case '--cwd': {
193
+ const value = takeValue();
194
+ if (value === undefined)
195
+ errors.push('--cwd expects a directory');
196
+ else
197
+ parsed.cwd = value;
198
+ break;
199
+ }
200
+ default:
201
+ if (flag.startsWith('-'))
202
+ errors.push(`unknown flag '${flag}' — see archcheck --help`);
203
+ else if (COMMANDS.has(flag) && !sawCommand) {
204
+ parsed.command = flag;
205
+ sawCommand = true;
206
+ }
207
+ else if (parsed.command === 'explain' && parsed.ruleId === undefined)
208
+ parsed.ruleId = flag;
209
+ else
210
+ errors.push(`unexpected argument '${flag}'`);
211
+ }
212
+ }
213
+ if (parsed.command === 'explain' && parsed.ruleId === undefined) {
214
+ errors.push('explain needs a rule id: archcheck explain <ruleId>');
215
+ }
216
+ if (parsed.emitCheck && parsed.command !== 'emit') {
217
+ errors.push('--check applies to `archcheck emit` only');
218
+ }
219
+ if (parsed.baselineMode !== undefined && parsed.command !== 'baseline') {
220
+ errors.push('--write and --prune apply to `archcheck baseline` only');
221
+ }
222
+ if (parsed.force && parsed.command !== 'init') {
223
+ errors.push('--force applies to `archcheck init` only');
224
+ }
225
+ if (parsed.command === 'baseline' && parsed.baselineMode === undefined) {
226
+ errors.push("baseline needs a mode: --write to record today's violations, --prune to drop what no longer reproduces");
227
+ }
228
+ if (parsed.writeGraph && parsed.ingestGraph) {
229
+ errors.push('--write-graph and --ingest-graph are mutually exclusive: one produces the report the other consumes');
230
+ }
231
+ return errors.length > 0 ? err(errors) : ok(parsed);
232
+ }
233
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { type ExitCode } from '../archcheck.js';
3
+ export declare function main(argv: readonly string[]): Promise<ExitCode>;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAYA,OAAO,EAIL,KAAK,QAAQ,EAId,MAAM,iBAAiB,CAAC;AAgLzB,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CA0BrE"}
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * The command surface. Thin by construction: parse args → one ArchCheck method → a reporter.
4
+ *
5
+ * What rule this enforces: this file owns NO behaviour. Every capability is reachable through
6
+ * `ArchCheck`, because the agent hook does not shell out (plan 10). A feature that only works from
7
+ * here would be a feature an agent cannot use.
8
+ *
9
+ * This is an app entry point — the one place allowed to write to the console (PROD-1).
10
+ */
11
+ import { existsSync, writeFileSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+ import { buildInitManifest, CONFIG_FILENAME, EXIT, exitCodeFor, initSummary, load, } from '../archcheck.js';
14
+ import { automatablePercent, MARK } from '../coverage/index.js';
15
+ import { describeUnimplemented } from '../emit/index.js';
16
+ import { describeStale } from '../emit/write.js';
17
+ import { reporterFor } from '../report/index.js';
18
+ import { gitChangedFiles, HELP, parseArgs } from './args.js';
19
+ import { packageVersion } from './version.js';
20
+ function fail(lines, code) {
21
+ for (const line of lines)
22
+ console.error(line);
23
+ return code;
24
+ }
25
+ async function runCheck(args, cwd) {
26
+ const loaded = load({ cwd });
27
+ if (!loaded.ok)
28
+ return fail(loaded.error, EXIT.config);
29
+ // Load-time warnings first: a judgement rule promoted to `error` is legal, and it must not be
30
+ // possible to promote one quietly.
31
+ for (const warning of loaded.value.registry.warnings())
32
+ console.error(`warning: ${warning}`);
33
+ // `--changed` with no value means "ask git". A git that cannot answer is a failure, never an
34
+ // empty changed set: every probe would filter to nothing and the run would read as clean
35
+ // (gitChangedFiles, src/cli/args.ts).
36
+ let changed = args.changed;
37
+ if (args.changed?.length === 0) {
38
+ const asked = gitChangedFiles(cwd);
39
+ if (!asked.ok)
40
+ return fail(asked.error, EXIT.config);
41
+ changed = asked.value;
42
+ }
43
+ const result = await loaded.value.check({
44
+ ...(changed === undefined ? {} : { changed }),
45
+ ...(args.only === undefined ? {} : { only: args.only }),
46
+ ingestGraph: args.ingestGraph,
47
+ writeGraph: args.writeGraph,
48
+ });
49
+ if (!result.ok)
50
+ return fail(result.error, EXIT.config);
51
+ const text = await reporterFor(args.format).report(result.value, {
52
+ showBaselined: args.showBaselined,
53
+ noColor: args.noColor || process.env.NO_COLOR !== undefined || !process.stdout.isTTY,
54
+ root: cwd,
55
+ });
56
+ if (typeof text === 'string')
57
+ process.stdout.write(text);
58
+ return exitCodeFor(result.value);
59
+ }
60
+ async function runEmit(args, cwd) {
61
+ // `emit` is the command that WRITES the id ledger, so it must be able to run while the ledger
62
+ // and the manifest disagree — otherwise recording a new id would require the record to exist.
63
+ const loaded = load({ cwd, skipIdCheck: args.emitCheck === false });
64
+ if (!loaded.ok)
65
+ return fail(loaded.error, EXIT.config);
66
+ // Skipping the immutability check is not the same as accepting a ledger nobody could read:
67
+ // `emit` WRITES the ledger, so it would replace it with one rebuilt from today's manifest and
68
+ // every retired id would vanish. `readIdLedger` (src/registry/ids.ts) marks it.
69
+ const ledger = loaded.value.registry.ledger();
70
+ if (ledger.unreadable !== undefined)
71
+ return fail([ledger.unreadable], EXIT.config);
72
+ // A kind no contract type implements generates nothing. `emit` has no `skipped` channel, so
73
+ // this is the one place it is said — on both the write and the --check path.
74
+ for (const line of describeUnimplemented(loaded.value.registry.all()))
75
+ console.error(line);
76
+ if (args.emitCheck) {
77
+ const stale = loaded.value.emitCheck();
78
+ if (!stale.ok)
79
+ return fail(stale.error, EXIT.config);
80
+ if (stale.value.length === 0) {
81
+ console.log('emitted output is up to date');
82
+ return EXIT.clean;
83
+ }
84
+ return fail([
85
+ 'emitted output is stale:',
86
+ ...describeStale(stale.value).map((line) => ` ${line}`),
87
+ // `unreadable` is the one reason re-emitting cannot fix — the document `docs` names is not
88
+ // there — so an agent is not sent round a loop that changes nothing.
89
+ ...(stale.value.some((file) => file.reason !== 'unreadable')
90
+ ? [' → run: npx archcheck emit']
91
+ : []),
92
+ ], EXIT.stale);
93
+ }
94
+ const emitted = loaded.value.emit();
95
+ if (!emitted.ok)
96
+ return fail(emitted.error, EXIT.config);
97
+ const changed = emitted.value.written.filter((file) => file.changed);
98
+ if (changed.length === 0)
99
+ console.log('emitted output already matched the manifest');
100
+ for (const file of changed)
101
+ console.log(`wrote ${file.path}`);
102
+ console.log(`wrote ${emitted.value.ledgerPath}`);
103
+ return EXIT.clean;
104
+ }
105
+ function runInit(args, cwd) {
106
+ const configPath = join(cwd, CONFIG_FILENAME);
107
+ if (existsSync(configPath) && !args.force) {
108
+ return fail([
109
+ `${CONFIG_FILENAME} already exists — archcheck init will not overwrite your manifest`,
110
+ ' → pass --force if you really mean to replace it',
111
+ ], EXIT.config);
112
+ }
113
+ const built = buildInitManifest(cwd, join(cwd, 'tsconfig.json'));
114
+ if (!built.ok)
115
+ return fail(built.error, EXIT.config);
116
+ writeFileSync(configPath, built.value.manifest);
117
+ for (const line of initSummary(cwd, built.value.layers))
118
+ console.log(line);
119
+ console.log('');
120
+ if (!built.value.observed) {
121
+ // Never silent. Without the graph every allow-list is empty, so the manifest names the layers
122
+ // and describes nothing about how they depend on each other.
123
+ for (const line of built.value.notObservedBecause ?? [])
124
+ console.error(`warning: ${line}`);
125
+ console.error('');
126
+ console.error(`wrote ${CONFIG_FILENAME}, but archcheck could not read your module graph, so every ` +
127
+ 'mayImport list is EMPTY.');
128
+ console.error(' → fix the problem above, delete the file, and run `archcheck init --force`');
129
+ return EXIT.config;
130
+ }
131
+ console.log(`wrote ${CONFIG_FILENAME} — every rule is 'warn', so the first run is green`);
132
+ console.log(' next: npx archcheck see what it observes');
133
+ console.log(' npx archcheck emit write the generated configs');
134
+ return EXIT.clean;
135
+ }
136
+ async function runBaseline(args, cwd) {
137
+ const loaded = load({ cwd });
138
+ if (!loaded.ok)
139
+ return fail(loaded.error, EXIT.config);
140
+ const outcome = await loaded.value.baseline(args.baselineMode ?? 'write');
141
+ if (!outcome.ok)
142
+ return fail(outcome.error, EXIT.config);
143
+ const { path, entries, removed, reduced } = outcome.value;
144
+ // Both halves of the ratchet, on one line: a prune that drops nothing and only lowers a recorded
145
+ // count has still tightened it, and `removed` alone reported that as having done nothing
146
+ // (`BaselineOutcome.reduced`, src/archcheck.ts).
147
+ console.log(args.baselineMode === 'prune'
148
+ ? `pruned ${removed} entr${removed === 1 ? 'y' : 'ies'}, reduced ${reduced} ` +
149
+ `count${reduced === 1 ? '' : 's'} — ${entries} remaining in ${path}`
150
+ : `recorded ${entries} entr${entries === 1 ? 'y' : 'ies'} in ${path}`);
151
+ if (args.baselineMode === 'write' && entries > 0) {
152
+ console.log(' these are debt, not policy: no owner and no expiry, so they stay visible');
153
+ }
154
+ return EXIT.clean;
155
+ }
156
+ async function runExplain(args, cwd) {
157
+ const loaded = load({ cwd });
158
+ if (!loaded.ok)
159
+ return fail(loaded.error, EXIT.config);
160
+ const explained = await loaded.value.explain(args.ruleId ?? '');
161
+ if (!explained.ok)
162
+ return fail(explained.error, EXIT.config);
163
+ console.log(explained.value);
164
+ return EXIT.clean;
165
+ }
166
+ function runCoverage(cwd) {
167
+ const loaded = load({ cwd });
168
+ if (!loaded.ok)
169
+ return fail(loaded.error, EXIT.config);
170
+ const coverage = loaded.value.coverage();
171
+ const { total, deterministic, proxy, model, unchecked } = coverage;
172
+ console.log(`${MARK.deterministic} ${deterministic} deterministic`);
173
+ console.log(`${MARK.proxy} ${proxy} proxy`);
174
+ console.log(`${MARK.model} ${model} judgement`);
175
+ if (unchecked > 0) {
176
+ console.log(` ${unchecked} declared, but no version of archcheck checks their kind yet`);
177
+ }
178
+ console.log(` ${total} rules total · ${automatablePercent(coverage)}% automatable`);
179
+ return EXIT.clean;
180
+ }
181
+ export async function main(argv) {
182
+ const parsed = parseArgs(argv);
183
+ if (!parsed.ok)
184
+ return fail([...parsed.error, '', 'see archcheck --help'], EXIT.config);
185
+ const args = parsed.value;
186
+ const cwd = args.cwd ?? process.cwd();
187
+ switch (args.command) {
188
+ case 'version':
189
+ console.log(packageVersion());
190
+ return EXIT.clean;
191
+ case 'help':
192
+ console.log(HELP);
193
+ return EXIT.clean;
194
+ case 'emit':
195
+ return runEmit(args, cwd);
196
+ case 'explain':
197
+ return runExplain(args, cwd);
198
+ case 'coverage':
199
+ return runCoverage(cwd);
200
+ case 'baseline':
201
+ return runBaseline(args, cwd);
202
+ case 'init':
203
+ return runInit(args, cwd);
204
+ case 'check':
205
+ return runCheck(args, cwd);
206
+ }
207
+ }
208
+ // This module IS the bin, and nothing imports it, so it runs unconditionally. It previously
209
+ // guarded on `process.argv[1]` ending in `cli/index.js` — which is false when npm installs the
210
+ // package, because argv[1] is then the `node_modules/.bin/archcheck` symlink. The CLI silently
211
+ // did nothing and exited 0, so a consumer read "clean" from a check that never ran. A guard that
212
+ // can be wrong about whether to run at all has no place in an entry point.
213
+ main(process.argv.slice(2))
214
+ .then((code) => process.exit(code))
215
+ .catch((error) => {
216
+ console.error(error instanceof Error ? error.message : String(error));
217
+ process.exit(EXIT.config);
218
+ });
219
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function packageVersion(): string;
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/cli/version.ts"],"names":[],"mappings":"AAWA,wBAAgB,cAAc,IAAI,MAAM,CAkBvC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The package version, read from package.json at run time.
3
+ *
4
+ * Why read rather than inline: an inlined version drifts from the manifest the first time
5
+ * someone bumps one and not the other, and `archcheck --version` is the field a bug report
6
+ * quotes. `node:` builtins only — src/ stays Node-compatible.
7
+ */
8
+ import { readFileSync } from 'node:fs';
9
+ import { dirname, join } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+ export function packageVersion() {
12
+ const here = dirname(fileURLToPath(import.meta.url));
13
+ // src/cli/ in development, dist/cli/ once built — package.json is two levels up from both.
14
+ for (const candidate of [
15
+ join(here, '..', '..', 'package.json'),
16
+ join(here, '..', 'package.json'),
17
+ ]) {
18
+ try {
19
+ const raw = JSON.parse(readFileSync(candidate, 'utf8'));
20
+ if (raw.name === 'archcheck' && typeof raw.version === 'string')
21
+ return raw.version;
22
+ }
23
+ catch {
24
+ // try the next candidate — a missing package.json here is not an error yet
25
+ }
26
+ }
27
+ return '0.0.0-unknown';
28
+ }
29
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/cli/version.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,cAAc;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,2FAA2F;IAC3F,KAAK,MAAM,SAAS,IAAI;QACtB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;KACjC,EAAE,CAAC;QACF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAGrD,CAAC;YACF,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;gBAAE,OAAO,GAAG,CAAC,OAAO,CAAC;QACtF,CAAC;QAAC,MAAM,CAAC;YACP,2EAA2E;QAC7E,CAAC;IACH,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The `banned-syntax` kind. Constructs that are wrong wherever they appear in a given scope.
3
+ *
4
+ * What rule this enforces, and why the selector is a CLOSED SET rather than a selector language:
5
+ * the six rule families this kind exists for are
6
+ * no clock in a pure rule, no computed dynamic import, no console outside an entry point,
7
+ * no inline suppression comment, no branching on a literal name, no empty catch.
8
+ * Each is one named construct. A CSS-ish selector string would have to be parsed, would be
9
+ * half-implemented for years, and would let a manifest declare a selector that silently matches
10
+ * nothing — which looks exactly like compliance. A closed enum cannot do that: an unknown
11
+ * construct fails validation and exits 2.
12
+ *
13
+ * The inline-suppression ban is self-referential and deliberate. Exceptions live in the manifest
14
+ * with an owner and an expiry (plan 15); making the inline escape hatch itself a violation is what
15
+ * stops the manifest being bypassed.
16
+ *
17
+ * What a caller must know: these are evaluated over OUR OWN AST. We already hold the program from
18
+ * the graph reader, so a second parse would be waste. `remedy.autofix` stays false.
19
+ */
20
+ import ts from 'typescript';
21
+ import type { Edge } from '../graph/types.js';
22
+ import type { Rule } from '../types.js';
23
+ import type { ContractType } from './types.js';
24
+ /** The closed set. Adding one is a deliberate change with a fixture, not a config value. */
25
+ export declare const BANNED_CONSTRUCTS: readonly ["member-access", "new-expression", "computed-dynamic-import", "suppression-comment", "string-literal-comparison", "empty-catch"];
26
+ export type BannedConstruct = (typeof BANNED_CONSTRUCTS)[number];
27
+ export type BannedSyntaxParams = {
28
+ appliesTo: string | string[];
29
+ selector: BannedConstruct;
30
+ /** The dotted name to ban, e.g. `Date.now` or `console`. Required by some constructs. */
31
+ target?: string;
32
+ };
33
+ export declare function asBannedSyntaxParams(rule: Rule): BannedSyntaxParams;
34
+ export declare function bannedSyntaxApplies(params: BannedSyntaxParams, relativePath: string): boolean;
35
+ export type BannedOccurrence = {
36
+ line: number;
37
+ col: number;
38
+ snippet: string;
39
+ };
40
+ /**
41
+ * Occurrences of the banned construct in one file.
42
+ *
43
+ * `computedImports` comes from the graph reader, which already detects a computed dynamic import —
44
+ * re-detecting it here would be a second implementation of the one thing that is hard to get right.
45
+ */
46
+ export declare function findBannedOccurrences(params: BannedSyntaxParams, source: ts.SourceFile | undefined, computedImports: readonly Edge[]): BannedOccurrence[];
47
+ export declare const bannedSyntaxContract: ContractType;
48
+ //# sourceMappingURL=banned-syntax.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banned-syntax.d.ts","sourceRoot":"","sources":["../../src/contracts/banned-syntax.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,EAAwB,IAAI,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAgD,MAAM,YAAY,CAAC;AAE7F,4FAA4F;AAC5F,eAAO,MAAM,iBAAiB,4IAOpB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAKjE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,eAAe,CAAC;IAC1B,yFAAyF;IACzF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,kBAAkB,CAEnE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAG7F;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA0G9E;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,SAAS,EACjC,eAAe,EAAE,SAAS,IAAI,EAAE,GAC/B,gBAAgB,EAAE,CAepB;AA6DD,eAAO,MAAM,oBAAoB,EAAE,YAMlC,CAAC"}