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.
- package/LICENSE +21 -0
- package/README.md +536 -0
- package/dist/archcheck.d.ts +99 -0
- package/dist/archcheck.d.ts.map +1 -0
- package/dist/archcheck.js +339 -0
- package/dist/archcheck.js.map +1 -0
- package/dist/baseline/index.d.ts +29 -0
- package/dist/baseline/index.d.ts.map +1 -0
- package/dist/baseline/index.js +116 -0
- package/dist/baseline/index.js.map +1 -0
- package/dist/cli/args.d.ts +36 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +233 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +219 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/version.d.ts +2 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +29 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/contracts/banned-syntax.d.ts +48 -0
- package/dist/contracts/banned-syntax.d.ts.map +1 -0
- package/dist/contracts/banned-syntax.js +201 -0
- package/dist/contracts/banned-syntax.js.map +1 -0
- package/dist/contracts/declared-field.d.ts +39 -0
- package/dist/contracts/declared-field.d.ts.map +1 -0
- package/dist/contracts/declared-field.js +142 -0
- package/dist/contracts/declared-field.js.map +1 -0
- package/dist/contracts/encapsulation.d.ts +28 -0
- package/dist/contracts/encapsulation.d.ts.map +1 -0
- package/dist/contracts/encapsulation.js +130 -0
- package/dist/contracts/encapsulation.js.map +1 -0
- package/dist/contracts/index.d.ts +10 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +9 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/judgement.d.ts +21 -0
- package/dist/contracts/judgement.d.ts.map +1 -0
- package/dist/contracts/judgement.js +109 -0
- package/dist/contracts/judgement.js.map +1 -0
- package/dist/contracts/layers.d.ts +75 -0
- package/dist/contracts/layers.d.ts.map +1 -0
- package/dist/contracts/layers.js +244 -0
- package/dist/contracts/layers.js.map +1 -0
- package/dist/contracts/naming.d.ts +21 -0
- package/dist/contracts/naming.d.ts.map +1 -0
- package/dist/contracts/naming.js +120 -0
- package/dist/contracts/naming.js.map +1 -0
- package/dist/contracts/registry.d.ts +23 -0
- package/dist/contracts/registry.d.ts.map +1 -0
- package/dist/contracts/registry.js +48 -0
- package/dist/contracts/registry.js.map +1 -0
- package/dist/contracts/required-file.d.ts +29 -0
- package/dist/contracts/required-file.d.ts.map +1 -0
- package/dist/contracts/required-file.js +131 -0
- package/dist/contracts/required-file.js.map +1 -0
- package/dist/contracts/types.d.ts +61 -0
- package/dist/contracts/types.d.ts.map +1 -0
- package/dist/contracts/types.js +2 -0
- package/dist/contracts/types.js.map +1 -0
- package/dist/coverage/index.d.ts +55 -0
- package/dist/coverage/index.d.ts.map +1 -0
- package/dist/coverage/index.js +68 -0
- package/dist/coverage/index.js.map +1 -0
- package/dist/emit/collect.d.ts +20 -0
- package/dist/emit/collect.d.ts.map +1 -0
- package/dist/emit/collect.js +17 -0
- package/dist/emit/collect.js.map +1 -0
- package/dist/emit/header.d.ts +21 -0
- package/dist/emit/header.d.ts.map +1 -0
- package/dist/emit/header.js +20 -0
- package/dist/emit/header.js.map +1 -0
- package/dist/emit/index.d.ts +57 -0
- package/dist/emit/index.d.ts.map +1 -0
- package/dist/emit/index.js +128 -0
- package/dist/emit/index.js.map +1 -0
- package/dist/emit/merge.d.ts +23 -0
- package/dist/emit/merge.d.ts.map +1 -0
- package/dist/emit/merge.js +71 -0
- package/dist/emit/merge.js.map +1 -0
- package/dist/emit/write.d.ts +20 -0
- package/dist/emit/write.d.ts.map +1 -0
- package/dist/emit/write.js +61 -0
- package/dist/emit/write.js.map +1 -0
- package/dist/exceptions/index.d.ts +46 -0
- package/dist/exceptions/index.d.ts.map +1 -0
- package/dist/exceptions/index.js +117 -0
- package/dist/exceptions/index.js.map +1 -0
- package/dist/fs/index.d.ts +12 -0
- package/dist/fs/index.d.ts.map +1 -0
- package/dist/fs/index.js +78 -0
- package/dist/fs/index.js.map +1 -0
- package/dist/graph/cache.d.ts +12 -0
- package/dist/graph/cache.d.ts.map +1 -0
- package/dist/graph/cache.js +76 -0
- package/dist/graph/cache.js.map +1 -0
- package/dist/graph/edges.d.ts +16 -0
- package/dist/graph/edges.d.ts.map +1 -0
- package/dist/graph/edges.js +161 -0
- package/dist/graph/edges.js.map +1 -0
- package/dist/graph/index.d.ts +15 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +90 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/match.d.ts +12 -0
- package/dist/graph/match.d.ts.map +1 -0
- package/dist/graph/match.js +35 -0
- package/dist/graph/match.js.map +1 -0
- package/dist/graph/program.d.ts +12 -0
- package/dist/graph/program.d.ts.map +1 -0
- package/dist/graph/program.js +54 -0
- package/dist/graph/program.js.map +1 -0
- package/dist/graph/types.d.ts +55 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +2 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/init/index.d.ts +23 -0
- package/dist/init/index.d.ts.map +1 -0
- package/dist/init/index.js +218 -0
- package/dist/init/index.js.map +1 -0
- package/dist/normalize/identity.d.ts +4 -0
- package/dist/normalize/identity.d.ts.map +1 -0
- package/dist/normalize/identity.js +33 -0
- package/dist/normalize/identity.js.map +1 -0
- package/dist/normalize/index.d.ts +3 -0
- package/dist/normalize/index.d.ts.map +1 -0
- package/dist/normalize/index.js +3 -0
- package/dist/normalize/index.js.map +1 -0
- package/dist/normalize/normalize.d.ts +34 -0
- package/dist/normalize/normalize.d.ts.map +1 -0
- package/dist/normalize/normalize.js +91 -0
- package/dist/normalize/normalize.js.map +1 -0
- package/dist/probes/graph.d.ts +19 -0
- package/dist/probes/graph.d.ts.map +1 -0
- package/dist/probes/graph.js +181 -0
- package/dist/probes/graph.js.map +1 -0
- package/dist/probes/index.d.ts +5 -0
- package/dist/probes/index.d.ts.map +1 -0
- package/dist/probes/index.js +5 -0
- package/dist/probes/index.js.map +1 -0
- package/dist/probes/lint.d.ts +17 -0
- package/dist/probes/lint.d.ts.map +1 -0
- package/dist/probes/lint.js +121 -0
- package/dist/probes/lint.js.map +1 -0
- package/dist/probes/model/anthropic.d.ts +47 -0
- package/dist/probes/model/anthropic.d.ts.map +1 -0
- package/dist/probes/model/anthropic.js +100 -0
- package/dist/probes/model/anthropic.js.map +1 -0
- package/dist/probes/model/budget.d.ts +22 -0
- package/dist/probes/model/budget.d.ts.map +1 -0
- package/dist/probes/model/budget.js +27 -0
- package/dist/probes/model/budget.js.map +1 -0
- package/dist/probes/model/cache.d.ts +13 -0
- package/dist/probes/model/cache.d.ts.map +1 -0
- package/dist/probes/model/cache.js +74 -0
- package/dist/probes/model/cache.js.map +1 -0
- package/dist/probes/model/index.d.ts +20 -0
- package/dist/probes/model/index.d.ts.map +1 -0
- package/dist/probes/model/index.js +160 -0
- package/dist/probes/model/index.js.map +1 -0
- package/dist/probes/model/prompt.d.ts +16 -0
- package/dist/probes/model/prompt.d.ts.map +1 -0
- package/dist/probes/model/prompt.js +57 -0
- package/dist/probes/model/prompt.js.map +1 -0
- package/dist/probes/model/provider.d.ts +88 -0
- package/dist/probes/model/provider.d.ts.map +1 -0
- package/dist/probes/model/provider.js +48 -0
- package/dist/probes/model/provider.js.map +1 -0
- package/dist/probes/structure.d.ts +3 -0
- package/dist/probes/structure.d.ts.map +1 -0
- package/dist/probes/structure.js +95 -0
- package/dist/probes/structure.js.map +1 -0
- package/dist/probes/types.d.ts +46 -0
- package/dist/probes/types.d.ts.map +1 -0
- package/dist/probes/types.js +15 -0
- package/dist/probes/types.js.map +1 -0
- package/dist/registry/define.d.ts +40 -0
- package/dist/registry/define.d.ts.map +1 -0
- package/dist/registry/define.js +4 -0
- package/dist/registry/define.js.map +1 -0
- package/dist/registry/ids.d.ts +19 -0
- package/dist/registry/ids.d.ts.map +1 -0
- package/dist/registry/ids.js +86 -0
- package/dist/registry/ids.js.map +1 -0
- package/dist/registry/index.d.ts +45 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +71 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/load.d.ts +14 -0
- package/dist/registry/load.d.ts.map +1 -0
- package/dist/registry/load.js +108 -0
- package/dist/registry/load.js.map +1 -0
- package/dist/registry/validate.d.ts +24 -0
- package/dist/registry/validate.d.ts.map +1 -0
- package/dist/registry/validate.js +160 -0
- package/dist/registry/validate.js.map +1 -0
- package/dist/report/index.d.ts +10 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +30 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/json.d.ts +20 -0
- package/dist/report/json.d.ts.map +1 -0
- package/dist/report/json.js +34 -0
- package/dist/report/json.js.map +1 -0
- package/dist/report/sarif.d.ts +21 -0
- package/dist/report/sarif.d.ts.map +1 -0
- package/dist/report/sarif.js +138 -0
- package/dist/report/sarif.js.map +1 -0
- package/dist/report/terminal.d.ts +3 -0
- package/dist/report/terminal.d.ts.map +1 -0
- package/dist/report/terminal.js +117 -0
- package/dist/report/terminal.js.map +1 -0
- package/dist/report/types.d.ts +28 -0
- package/dist/report/types.d.ts.map +1 -0
- package/dist/report/types.js +11 -0
- package/dist/report/types.js.map +1 -0
- package/dist/report/verdict.d.ts +21 -0
- package/dist/report/verdict.d.ts.map +1 -0
- package/dist/report/verdict.js +31 -0
- package/dist/report/verdict.js.map +1 -0
- package/dist/result.d.ts +22 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +19 -0
- package/dist/result.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/util/compilerApi.d.ts +2 -0
- package/dist/util/compilerApi.d.ts.map +1 -0
- package/dist/util/compilerApi.js +28 -0
- package/dist/util/compilerApi.js.map +1 -0
- package/dist/util/glob.d.ts +43 -0
- package/dist/util/glob.d.ts.map +1 -0
- package/dist/util/glob.js +195 -0
- package/dist/util/glob.js.map +1 -0
- package/dist/util/paths.d.ts +6 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +22 -0
- package/dist/util/paths.js.map +1 -0
- package/dist/version.d.ts +13 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +12 -0
- package/dist/version.js.map +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mitesh Sharma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
# archcheck
|
|
2
|
+
|
|
3
|
+
**Write your architecture rules once. archcheck checks them, and generates the configuration that
|
|
4
|
+
enforces them.**
|
|
5
|
+
|
|
6
|
+
Your architecture lives in many places. It lives in a linter config, in a module-graph config, in a
|
|
7
|
+
CI script, and in a document that somebody wrote a year ago. Nothing keeps these in agreement. A
|
|
8
|
+
rule that changes in one place stays wrong in the others. The copy that people read is often the
|
|
9
|
+
copy that is wrong.
|
|
10
|
+
|
|
11
|
+
archcheck gives you one file. You declare each rule once. archcheck then does two things with it.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
architecture.config.ts
|
|
15
|
+
one file · one rule, once
|
|
16
|
+
│
|
|
17
|
+
┌───────────────┴───────────────┐
|
|
18
|
+
│ │
|
|
19
|
+
GENERATE CHECK
|
|
20
|
+
│ │
|
|
21
|
+
generated/graph.config.cjs reads your code
|
|
22
|
+
generated/lint.overrides.json finds each violation
|
|
23
|
+
generated/required.json returns a typed finding
|
|
24
|
+
generated/rules.json │
|
|
25
|
+
the rule table in your docs ▼
|
|
26
|
+
│ ✗ domain may not import services
|
|
27
|
+
▼ modules/ledger/domain/supersede.ts:4
|
|
28
|
+
your editor shows the rule → invert the call: the service
|
|
29
|
+
before you run anything calls the domain
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Every rule has one home. The generated files carry a header that says they are generated. A gate
|
|
33
|
+
fails if somebody edits one by hand.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## What you get
|
|
38
|
+
|
|
39
|
+
| | |
|
|
40
|
+
|---|---|
|
|
41
|
+
| **One source of truth** | You declare a rule once. Every mechanism reads it. |
|
|
42
|
+
| **Honest coverage** | archcheck counts your rules by tier and computes the percentage. You cannot write a better number by hand. |
|
|
43
|
+
| **A remedy in every finding** | Each finding says what to do next, not only what failed. |
|
|
44
|
+
| **An adoption path** | A baseline records the violations you already have. Your build stays green. You then fix them one at a time. |
|
|
45
|
+
| **Typed output for an agent** | `--format json` gives a stable, versioned shape. Exit codes tell an agent which file to fix. |
|
|
46
|
+
| **SARIF for CI** | `--format sarif` gives code scanning and your editor a format they already read. |
|
|
47
|
+
| **Zero runtime dependencies** | archcheck needs TypeScript, which you already have. |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
You need **Node 20 or later**. You also need **TypeScript** in your project, in the range
|
|
54
|
+
`>=5.4 <7`. TypeScript 7 is the native port. It moved the compiler API that archcheck reads to
|
|
55
|
+
another subpath, so the range excludes it. archcheck names the installed version and the command to
|
|
56
|
+
fix it if it finds a TypeScript that does not expose that API.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install --save-dev archcheck
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
archcheck also runs with `bun`, `pnpm` and `yarn`.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Quick start
|
|
67
|
+
|
|
68
|
+
Five steps. Each step is one command.
|
|
69
|
+
|
|
70
|
+
### Step 1 — write a starting manifest
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx archcheck init
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`init` reads your folder structure. It writes `architecture.config.ts`. Each folder under `src/`
|
|
77
|
+
becomes a layer. Each layer lists what it imports today.
|
|
78
|
+
|
|
79
|
+
Every generated rule has `severity: 'warn'`. Your build stays green, and archcheck exits `0`. This
|
|
80
|
+
is deliberate: a tool that blocks 400 times on the first run gets removed the same day.
|
|
81
|
+
|
|
82
|
+
archcheck still **reports** what it sees, and it marks each finding `(warn)`. A group heading says
|
|
83
|
+
how many findings block. Read them, and fix them in your own order.
|
|
84
|
+
|
|
85
|
+
### Step 2 — look at what archcheck sees
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx archcheck
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
You get one group per tier, and the most important group comes first. Each finding says whether it
|
|
92
|
+
blocks.
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
✗ 2 deterministic (0 blocking)
|
|
96
|
+
|
|
97
|
+
services may not import repositories services-imports-only-what-it-declares (warn)
|
|
98
|
+
src/services/write.ts:3
|
|
99
|
+
allowed: contracts, domain
|
|
100
|
+
→ declare the dependency, or invert the call
|
|
101
|
+
|
|
102
|
+
logging goes through one seam, never straight to the console no-console-outside-an-entry-point (warn)
|
|
103
|
+
src/entry/main.ts:9
|
|
104
|
+
→ inject a logger, or list this path as an entry point in appliesTo
|
|
105
|
+
|
|
106
|
+
◑ 0 proxy · the check is narrower than the rule
|
|
107
|
+
○ 0 advisory
|
|
108
|
+
8 rules · 7 deterministic · 1 proxy · 0 advisory
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Nothing here blocks yet. When a run has nothing to report at all, archcheck says `nothing to fix`.
|
|
112
|
+
|
|
113
|
+
### Step 3 — tighten one rule
|
|
114
|
+
|
|
115
|
+
Open `architecture.config.ts`. Find a layer that imports something it must not. Remove that entry
|
|
116
|
+
from its `mayImport` list.
|
|
117
|
+
|
|
118
|
+
```diff
|
|
119
|
+
params: {
|
|
120
|
+
name: 'services',
|
|
121
|
+
match: 'src/services/**',
|
|
122
|
+
- mayImport: ['contracts', 'domain', 'repositories'],
|
|
123
|
+
+ mayImport: ['contracts', 'domain'],
|
|
124
|
+
},
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Run `npx archcheck` again. It now reports the imports that break the rule.
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
✗ 1 deterministic (0 blocking)
|
|
131
|
+
|
|
132
|
+
services may not import repositories services-imports-only-what-it-declares (warn)
|
|
133
|
+
src/services/write.ts:3
|
|
134
|
+
allowed: contracts, domain
|
|
135
|
+
→ declare the dependency, or invert the call
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Fix the code. Then change that one rule to `severity: 'error'`.
|
|
139
|
+
|
|
140
|
+
### Step 4 — generate the configuration
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
npx archcheck emit
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
archcheck writes the `generated/` folder. Commit it.
|
|
147
|
+
|
|
148
|
+
archcheck writes one file per **sink** your rules use, and `rules.json` always.
|
|
149
|
+
|
|
150
|
+
| File | The rules that write it |
|
|
151
|
+
|---|---|
|
|
152
|
+
| `generated/graph.config.cjs` | `layers`, `encapsulation` |
|
|
153
|
+
| `generated/lint.overrides.json` | `layers`, `naming`, `banned-syntax` |
|
|
154
|
+
| `generated/exports.json` | `encapsulation` |
|
|
155
|
+
| `generated/required.json` | `required-file`, `declared-field`, `judgement` |
|
|
156
|
+
| `generated/rules.json` | every rule — this is the data your documents read |
|
|
157
|
+
|
|
158
|
+
A sink with no rules writes no file. Your editor now shows each rule as you type, and it shows your
|
|
159
|
+
own sentence:
|
|
160
|
+
|
|
161
|
+
> `domain may not import services — invert the call: the service calls the domain`
|
|
162
|
+
|
|
163
|
+
### Step 5 — add two scripts and one CI step
|
|
164
|
+
|
|
165
|
+
Add these lines to `package.json`:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"scripts": {
|
|
170
|
+
"arch": "archcheck",
|
|
171
|
+
"arch:emit": "archcheck emit --check"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Add one step to your CI workflow:
|
|
177
|
+
|
|
178
|
+
```yaml
|
|
179
|
+
- run: npx archcheck --format sarif > archcheck.sarif
|
|
180
|
+
- run: npx archcheck emit --check
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
You are done. Repeat step 3 for each rule you want to enforce.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## A complete example
|
|
188
|
+
|
|
189
|
+
[`examples/minimal-service/`](examples/minimal-service/) is a small service with six layers. It has
|
|
190
|
+
a manifest, and it has one deliberate violation for each rule.
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
cd examples/minimal-service
|
|
194
|
+
npx archcheck # green
|
|
195
|
+
npx archcheck coverage # 8 rules · 100% automatable
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Read [its README](examples/minimal-service/README.md). It explains each file, and it shows you how
|
|
199
|
+
to make the rules fail on purpose.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## How the rules work
|
|
204
|
+
|
|
205
|
+
You write each rule as one entry in the manifest. A rule has a **kind**. The kind decides what the
|
|
206
|
+
rule can say.
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import { defineArchitecture } from 'archcheck';
|
|
210
|
+
|
|
211
|
+
export default defineArchitecture({
|
|
212
|
+
rules: [
|
|
213
|
+
{
|
|
214
|
+
id: 'domain-decides-alone',
|
|
215
|
+
kind: 'layers',
|
|
216
|
+
statement: 'the domain reads contracts and rules',
|
|
217
|
+
severity: 'error',
|
|
218
|
+
confidence: 'deterministic',
|
|
219
|
+
params: {
|
|
220
|
+
name: 'domain',
|
|
221
|
+
match: 'src/domain/**',
|
|
222
|
+
mayImport: ['contracts', 'rules'],
|
|
223
|
+
catchesUnlayered: true,
|
|
224
|
+
},
|
|
225
|
+
remedy: { summary: 'invert the call: the service calls the domain' },
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
There are eight kinds. The set is closed.
|
|
232
|
+
|
|
233
|
+
| Kind | It says | Example |
|
|
234
|
+
|---|---|---|
|
|
235
|
+
| `layers` | which layers a layer may import | the domain must not import a service |
|
|
236
|
+
| `encapsulation` | a module is reached through its barrel | import `modules/ledger`, never `modules/ledger/services/write` |
|
|
237
|
+
| `naming` | what a name must look like | every hook starts with `use` |
|
|
238
|
+
| `banned-syntax` | a construct is forbidden here | a pure rule reads no clock |
|
|
239
|
+
| `required-file` | a file must exist | every port has a memory twin |
|
|
240
|
+
| `declared-field` | a call must declare a field | every endpoint declares a permission |
|
|
241
|
+
| `judgement` | a rule in plain English, judged by a model | a controller decides nothing |
|
|
242
|
+
| `forbidden` | one specific edge is banned | reserved; `layers` covers this today |
|
|
243
|
+
|
|
244
|
+
### Default deny
|
|
245
|
+
|
|
246
|
+
A `layers` rule denies what it does not allow. A new folder that nobody declares fails on its first
|
|
247
|
+
commit. It is never silently legal.
|
|
248
|
+
|
|
249
|
+
One `layers` rule carries `catchesUnlayered: true`. That rule reports a file in no layer.
|
|
250
|
+
|
|
251
|
+
### Three tiers, so archcheck does not pretend
|
|
252
|
+
|
|
253
|
+
Each rule declares its `confidence`. The tier says how much to trust a pass.
|
|
254
|
+
|
|
255
|
+
| Mark | Tier | What it means |
|
|
256
|
+
|---|---|---|
|
|
257
|
+
| ✓ | `deterministic` | A script decides. No judgement, and no model. |
|
|
258
|
+
| ◑ | `proxy` | The check catches the practical violations. The rule as written is broader. Treat a pass as evidence, not proof. |
|
|
259
|
+
| ○ | `model` | A model reads the code. The verdict is advisory. |
|
|
260
|
+
|
|
261
|
+
`npx archcheck coverage` counts your rules by tier. archcheck computes the percentage from the
|
|
262
|
+
manifest. Add a rule with no real check, and the percentage falls.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Commands
|
|
267
|
+
|
|
268
|
+
```
|
|
269
|
+
archcheck check everything
|
|
270
|
+
archcheck --changed check only what git says changed
|
|
271
|
+
archcheck --format json the shape an agent reads
|
|
272
|
+
archcheck --format sarif SARIF 2.1.0, for CI and your editor
|
|
273
|
+
archcheck --format verdict one answer, for a blocking hook
|
|
274
|
+
archcheck --only deterministic skip the proxy and model tiers
|
|
275
|
+
|
|
276
|
+
archcheck emit write the generated configuration
|
|
277
|
+
archcheck emit --check fail if the committed output is stale
|
|
278
|
+
archcheck explain <ruleId> the rule, the remedy, and its current violations
|
|
279
|
+
archcheck coverage the three counts
|
|
280
|
+
archcheck init write a starting manifest
|
|
281
|
+
archcheck baseline --write record today's violations as debt
|
|
282
|
+
archcheck baseline --prune drop entries that no longer reproduce
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Exit codes
|
|
286
|
+
|
|
287
|
+
An agent reads these. They are frozen.
|
|
288
|
+
|
|
289
|
+
| Code | Meaning | What to do |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| `0` | Clean. Or only baselined and advisory findings. | Continue. |
|
|
292
|
+
| `1` | New violations of an `error` rule. | Fix the code. |
|
|
293
|
+
| `2` | The configuration or the environment is wrong. | Read the error. Do **not** touch the code. |
|
|
294
|
+
| `3` | The generated output is stale. | Run `archcheck emit`. Write the document yourself if `docs` names one archcheck cannot read. |
|
|
295
|
+
| `4` | A recorded violation no longer happens. | Run `archcheck baseline --prune`. |
|
|
296
|
+
|
|
297
|
+
Code `2` is separate from code `1` on purpose. Code `1` says the code is wrong. Code `2` says the
|
|
298
|
+
code is not the problem. The cause is the manifest, another committed archcheck file, or the
|
|
299
|
+
environment archcheck runs in. An unknown layer name in `mayImport` and an expired exception are
|
|
300
|
+
manifest problems. A corrupt `.archcheck/ids.json`, a `--changed` run that git cannot answer, a
|
|
301
|
+
`baseline --prune` on a degraded run, and an `init` that cannot read the module graph are not.
|
|
302
|
+
archcheck names the real fix in the error text. An agent that reads that text does not spend its
|
|
303
|
+
turn on the wrong file.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Adopt archcheck on a codebase that already breaks its rules
|
|
308
|
+
|
|
309
|
+
This is the normal case. You have two tools, and they do different jobs.
|
|
310
|
+
|
|
311
|
+
```
|
|
312
|
+
a violation you already have a violation you choose to allow
|
|
313
|
+
│ │
|
|
314
|
+
▼ ▼
|
|
315
|
+
archcheck baseline --write exceptions: [ … ] in the manifest
|
|
316
|
+
│ │
|
|
317
|
+
.archcheck/baseline.json owner + expiry + reason
|
|
318
|
+
│ │
|
|
319
|
+
DEBT POLICY
|
|
320
|
+
no owner · no expiry somebody signed for it
|
|
321
|
+
the file only shrinks it expires, and then it fails
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### The baseline records debt
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
npx archcheck baseline --write
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
archcheck records each current violation by a **stable hash of the evidence**. The hash holds no
|
|
331
|
+
line number. Move the code, and the entry still matches. Your build goes green.
|
|
332
|
+
|
|
333
|
+
A new violation of the same rule still fails. The ratchet turns one way.
|
|
334
|
+
|
|
335
|
+
When you fix a recorded violation, archcheck exits `4`. Run `npx archcheck baseline --prune`. The
|
|
336
|
+
file shrinks. It cannot silently hide more than it should.
|
|
337
|
+
|
|
338
|
+
### An exception records policy
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
exceptions: [
|
|
342
|
+
{
|
|
343
|
+
rule: 'no-deep-module-imports',
|
|
344
|
+
path: 'modules/legacy/**',
|
|
345
|
+
owner: 'mitesh',
|
|
346
|
+
expires: '2026-12-31',
|
|
347
|
+
reason: 'legacy module, scheduled for removal in Q4',
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
An exception needs an owner, a date and a reason. archcheck reports every exception on every run,
|
|
353
|
+
and it reports the ones that expire within 30 days.
|
|
354
|
+
|
|
355
|
+
After the date, the run fails and names the owner. An exception that nobody has to justify again is
|
|
356
|
+
a rule that somebody deleted quietly.
|
|
357
|
+
|
|
358
|
+
Inline suppression comments stay a violation. That is what makes the manifest the only way past a
|
|
359
|
+
rule.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Prove that a rule catches something
|
|
364
|
+
|
|
365
|
+
A rule whose pattern matches nothing passes every build. It looks exactly like compliance.
|
|
366
|
+
|
|
367
|
+
archcheck makes this a gate. Add one rule to your manifest:
|
|
368
|
+
|
|
369
|
+
```ts
|
|
370
|
+
{
|
|
371
|
+
id: 'every-error-rule-has-a-fixture',
|
|
372
|
+
kind: 'required-file',
|
|
373
|
+
statement: 'every error-severity rule has a fixture it catches',
|
|
374
|
+
severity: 'error',
|
|
375
|
+
confidence: 'deterministic',
|
|
376
|
+
params: { forEach: 'rule[severity=error]', expect: 'fixtures/rules/{id}.violation.ts' },
|
|
377
|
+
remedy: { summary: 'add a file that deliberately breaks this rule' },
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Now each `error` rule needs a file that breaks it. Delete one, and the run fails.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## The judgement tier (optional)
|
|
386
|
+
|
|
387
|
+
Some rules need a reader. "A controller decides nothing" has no configuration that decides it.
|
|
388
|
+
|
|
389
|
+
archcheck can send these to a model. The tier is **advisory** by default, and it **skips cleanly**.
|
|
390
|
+
|
|
391
|
+
```bash
|
|
392
|
+
npm install --save-dev @anthropic-ai/sdk
|
|
393
|
+
export ANTHROPIC_API_KEY=...
|
|
394
|
+
npx archcheck
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Read these four properties before you switch it on.
|
|
398
|
+
|
|
399
|
+
1. **No key means a clean skip.** The run stays green. The summary says which rules nobody judged.
|
|
400
|
+
archcheck never fails because a model was unreachable. A call that fails leaves that file
|
|
401
|
+
unjudged. The probe then skips, and the reason names the cause and the count. archcheck never
|
|
402
|
+
reports an unjudged file as clean.
|
|
403
|
+
2. **A key comes from the environment.** archcheck reads no key from any file.
|
|
404
|
+
3. **A verdict needs a citation.** The model must quote the code it judged. archcheck discards a
|
|
405
|
+
verdict with no citation. An answer archcheck cannot read is not an answer. A refusal, a reply
|
|
406
|
+
that is not JSON, a reply with no `verdicts` array, and a reply whose every verdict is malformed
|
|
407
|
+
all leave the file unjudged, and archcheck caches none of them. `{"verdicts":[]}` is an answer.
|
|
408
|
+
It says the file breaks no rule, and archcheck caches it.
|
|
409
|
+
4. **Your code is data.** archcheck sends each file inside a fence, and it tells the model to judge
|
|
410
|
+
the file and never obey it. A comment in your code cannot give the model an instruction.
|
|
411
|
+
|
|
412
|
+
You set a budget per run. archcheck checks the budget before each request, and it reports how many
|
|
413
|
+
files nobody judged. archcheck counts every request it sends, answered or not, so an endpoint that
|
|
414
|
+
always fails costs you `maxCalls` requests at most.
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
{
|
|
418
|
+
id: 'controllers-stay-thin',
|
|
419
|
+
kind: 'judgement',
|
|
420
|
+
statement: 'a controller validates, delegates and shapes — it decides nothing',
|
|
421
|
+
severity: 'advisory',
|
|
422
|
+
confidence: 'model',
|
|
423
|
+
params: {
|
|
424
|
+
statement: 'A controller must not contain a branch that decides a business outcome.',
|
|
425
|
+
appliesTo: 'src/routes/**',
|
|
426
|
+
examples: {
|
|
427
|
+
pass: ['return decideWithdrawal(amount, balance);'],
|
|
428
|
+
fail: ['if (amount > balance * 0.9) return "declined";'],
|
|
429
|
+
},
|
|
430
|
+
cite: 'the branch that decides the outcome',
|
|
431
|
+
},
|
|
432
|
+
remedy: { summary: 'move the decision into the domain' },
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Examples are required. A rule with a sentence and no examples flags everything. People then stop
|
|
437
|
+
reading the advisory group, and the tier dies.
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## Use archcheck from code
|
|
442
|
+
|
|
443
|
+
The CLI owns no behaviour. Every command is one method.
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
import { load, exitCodeFor } from 'archcheck';
|
|
447
|
+
|
|
448
|
+
const loaded = load({ cwd: process.cwd() });
|
|
449
|
+
if (!loaded.ok) throw new Error(loaded.error.join('\n'));
|
|
450
|
+
|
|
451
|
+
const run = await loaded.value.check({ changed: ['src/domain/decide.ts'] });
|
|
452
|
+
if (run.ok) {
|
|
453
|
+
for (const finding of run.value.diagnostics) {
|
|
454
|
+
console.log(finding.statement, finding.file, finding.remedy.summary);
|
|
455
|
+
}
|
|
456
|
+
process.exit(exitCodeFor(run.value));
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
An agent hook does not shell out. Every result is typed, and no call throws.
|
|
461
|
+
|
|
462
|
+
Several violations of one rule in one file collapse into one finding. The `occurrences` field says
|
|
463
|
+
how many violations collapsed into it. The `occurrenceLines` field says which lines they are on. The
|
|
464
|
+
baseline records the count, so a new occurrence in a file the baseline already covers still fails.
|
|
465
|
+
The hash does not change: the evidence holds no line number, and the count stays out of the
|
|
466
|
+
evidence. No baseline file you already have becomes invalid.
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## How archcheck reads your code
|
|
471
|
+
|
|
472
|
+
archcheck owns its module graph. It builds one program with the TypeScript compiler, and every
|
|
473
|
+
check reads it.
|
|
474
|
+
|
|
475
|
+
```
|
|
476
|
+
your tsconfig.json
|
|
477
|
+
│
|
|
478
|
+
▼
|
|
479
|
+
┌───────────────┐ one program, one parse, shared by every check
|
|
480
|
+
│ module graph │ every import edge · type-only · dynamic · computed
|
|
481
|
+
└───────┬───────┘
|
|
482
|
+
│
|
|
483
|
+
┌──────┼──────────┬───────────────┐
|
|
484
|
+
▼ ▼ ▼ ▼
|
|
485
|
+
graph lint structure judgement
|
|
486
|
+
layers naming required-file plain English
|
|
487
|
+
barrels bans declared-field (advisory)
|
|
488
|
+
│ │ │ │
|
|
489
|
+
└──────┴────┬─────┴───────────────┘
|
|
490
|
+
▼
|
|
491
|
+
one finding per violation
|
|
492
|
+
+ a stable hash of the evidence
|
|
493
|
+
▼
|
|
494
|
+
terminal · json · sarif · verdict
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
archcheck owns the graph for three reasons.
|
|
498
|
+
|
|
499
|
+
1. **A stable hash.** The hash comes from the evidence, and never from a line number. Move a
|
|
500
|
+
function, and the baseline still matches.
|
|
501
|
+
2. **A computed import stays visible.** `import(\`./${name}.js\`)` resolves to nothing. A graph tool
|
|
502
|
+
cannot see it, and a layer violation hides there. archcheck reports it.
|
|
503
|
+
3. **One parse.** Every check reads the same program. archcheck does not run your linter again.
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## Contributing
|
|
508
|
+
|
|
509
|
+
archcheck checks itself. Its own manifest is [`architecture.config.ts`](architecture.config.ts), and
|
|
510
|
+
its own rule table is [`RULES.md`](RULES.md).
|
|
511
|
+
|
|
512
|
+
```bash
|
|
513
|
+
bun install
|
|
514
|
+
bun run check
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
`bun run check` runs every gate. The pre-push hook and CI run the same scripts.
|
|
518
|
+
|
|
519
|
+
| Gate | It enforces |
|
|
520
|
+
|---|---|
|
|
521
|
+
| `typecheck` | no type errors, strict |
|
|
522
|
+
| `lint` | format, style, and no Bun-only API in `src/` |
|
|
523
|
+
| `tests` | every test, co-located beside its subject |
|
|
524
|
+
| `emit` | the committed generated output is not stale |
|
|
525
|
+
| `selfhost` | archcheck passes its own rules |
|
|
526
|
+
|
|
527
|
+
Two standing rules for a change:
|
|
528
|
+
|
|
529
|
+
1. A bug fix lands its reproducing test first.
|
|
530
|
+
2. Every `error` rule has a fixture that it catches.
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## License
|
|
535
|
+
|
|
536
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { StaleFile } from './emit/write.js';
|
|
2
|
+
import { type Registry } from './registry/index.js';
|
|
3
|
+
import { type Result } from './result.js';
|
|
4
|
+
import type { Confidence, ContractKind, Coverage, Diagnostic, RunResult } from './types.js';
|
|
5
|
+
/** Exit codes are an API. An agent branches on them, so they are frozen from v0.1 (LLD §6). */
|
|
6
|
+
export declare const EXIT: {
|
|
7
|
+
/** Clean, or only baselined and advisory findings. */
|
|
8
|
+
readonly clean: 0;
|
|
9
|
+
/** New violations of error-severity rules. Fix the code. */
|
|
10
|
+
readonly violations: 1;
|
|
11
|
+
/** Configuration invalid. Fix the manifest, NOT the code. */
|
|
12
|
+
readonly config: 2;
|
|
13
|
+
/** Emitted output is stale. Run `archcheck emit`. */
|
|
14
|
+
readonly stale: 3;
|
|
15
|
+
/** A baselined finding no longer reproduces. Run `archcheck baseline --prune` (plan 14). */
|
|
16
|
+
readonly baselineStale: 4;
|
|
17
|
+
};
|
|
18
|
+
export type ExitCode = (typeof EXIT)[keyof typeof EXIT];
|
|
19
|
+
export type CheckOptions = {
|
|
20
|
+
/** Repo-relative POSIX paths. Undefined means the whole repository. */
|
|
21
|
+
changed?: readonly string[];
|
|
22
|
+
/** Run only rules at or above this confidence tier. `deterministic` skips the model tier. */
|
|
23
|
+
only?: Confidence;
|
|
24
|
+
/**
|
|
25
|
+
* Identities the baseline records. Omitted means "read `.archcheck/baseline.json`", which is
|
|
26
|
+
* what every real caller wants; pass an explicit set only to test without a file.
|
|
27
|
+
*/
|
|
28
|
+
baselined?: ReadonlySet<string>;
|
|
29
|
+
/** Override today's date. Only the expiry-boundary tests have a reason to. */
|
|
30
|
+
today?: string;
|
|
31
|
+
/** Ingest `.archcheck/graph.json` instead of reading the graph ourselves. */
|
|
32
|
+
ingestGraph?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Write `.archcheck/graph.json` as a side effect of this run. The other half of `ingestGraph`:
|
|
35
|
+
* CI builds the graph once, writes it here, and every later gate ingests it rather than paying
|
|
36
|
+
* for a second parse (LLD §1.3).
|
|
37
|
+
*/
|
|
38
|
+
writeGraph?: boolean;
|
|
39
|
+
cache?: boolean;
|
|
40
|
+
};
|
|
41
|
+
export type EmitResult = {
|
|
42
|
+
written: {
|
|
43
|
+
path: string;
|
|
44
|
+
changed: boolean;
|
|
45
|
+
}[];
|
|
46
|
+
ledgerPath: string;
|
|
47
|
+
/**
|
|
48
|
+
* Rule kinds this version generated no configuration for. Carried here because `emit` has no
|
|
49
|
+
* `skipped` channel, so a programmatic caller has nowhere else to learn it — the CLI says the
|
|
50
|
+
* same thing through `describeUnimplemented` (src/emit/index.ts), which also has to serve the
|
|
51
|
+
* `--check` path, where there is no `EmitResult`.
|
|
52
|
+
*/
|
|
53
|
+
unimplemented: ContractKind[];
|
|
54
|
+
};
|
|
55
|
+
export type BaselineOutcome = {
|
|
56
|
+
path: string;
|
|
57
|
+
entries: number;
|
|
58
|
+
removed: number;
|
|
59
|
+
/**
|
|
60
|
+
* Entries that survived with a LOWER recorded count than before. `--prune` tightens the ratchet
|
|
61
|
+
* two ways, and only `removed` was visible: a prune that fixed one of two occurrences reported
|
|
62
|
+
* "pruned 0 entries" and read as having done nothing. Pinned by 'a prune that only reduced a
|
|
63
|
+
* count says so, rather than reporting nothing' in tests/adoption.test.ts.
|
|
64
|
+
*/
|
|
65
|
+
reduced: number;
|
|
66
|
+
};
|
|
67
|
+
export type ArchCheck = {
|
|
68
|
+
readonly registry: Registry;
|
|
69
|
+
check(options?: CheckOptions): Promise<Result<RunResult>>;
|
|
70
|
+
/** `baseline --write` / `baseline --prune`. Both go through a real run first. */
|
|
71
|
+
baseline(mode: 'write' | 'prune'): Promise<Result<BaselineOutcome>>;
|
|
72
|
+
emit(): Result<EmitResult>;
|
|
73
|
+
emitCheck(): Result<StaleFile[]>;
|
|
74
|
+
/** Statement, rationale, allowed alternatives and CURRENT violations. */
|
|
75
|
+
explain(ruleId: string): Promise<Result<string>>;
|
|
76
|
+
coverage(): Coverage;
|
|
77
|
+
};
|
|
78
|
+
export type LoadOptions = {
|
|
79
|
+
cwd?: string;
|
|
80
|
+
configPath?: string;
|
|
81
|
+
skipIdCheck?: boolean;
|
|
82
|
+
};
|
|
83
|
+
export declare function load(options?: LoadOptions): Result<ArchCheck>;
|
|
84
|
+
/**
|
|
85
|
+
* What `explain` appends once the run has happened — the live violation count. It counts
|
|
86
|
+
* OCCURRENCES, not diagnostics: an agent asking "how many" means how many places to fix, and one
|
|
87
|
+
* diagnostic can stand for several (see `Diagnostic.occurrences`).
|
|
88
|
+
*/
|
|
89
|
+
export declare function describeViolations(ruleId: string, diagnostics: readonly Diagnostic[]): string;
|
|
90
|
+
/**
|
|
91
|
+
* The order matters. An expired exception is a MANIFEST problem (exit 2) and is checked first,
|
|
92
|
+
* because the violations it stopped covering are a consequence of it rather than news of their own.
|
|
93
|
+
* A stale baseline (exit 4) outranks live violations for the same reason: the fix is
|
|
94
|
+
* `baseline --prune`, and reporting exit 1 would send an agent to edit code that is already right.
|
|
95
|
+
*/
|
|
96
|
+
export { buildInitManifest, inferLayers, initSummary, renderManifest, } from './init/index.js';
|
|
97
|
+
export { CONFIG_FILENAME } from './registry/index.js';
|
|
98
|
+
export declare function exitCodeFor(result: RunResult): ExitCode;
|
|
99
|
+
//# sourceMappingURL=archcheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archcheck.d.ts","sourceRoot":"","sources":["../src/archcheck.ts"],"names":[],"mappings":"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"}
|