@archrad/deterministic 0.1.4 → 0.1.6
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/CHANGELOG.md +39 -4
- package/README.md +81 -48
- package/biome.json +32 -25
- package/dist/cli.js +1 -1
- package/dist/mcp-server-tools-patch.d.ts +29 -0
- package/dist/mcp-server-tools-patch.d.ts.map +1 -0
- package/dist/mcp-server-tools-patch.js +71 -0
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +256 -0
- package/dist/nodeExpress.d.ts.map +1 -1
- package/dist/nodeExpress.js +5 -1
- package/dist/openapi-to-ir.d.ts.map +1 -1
- package/dist/openapi-to-ir.js +6 -4
- package/dist/pythonFastAPI.d.ts.map +1 -1
- package/dist/pythonFastAPI.js +3 -1
- package/dist/static-rule-guidance.d.ts +19 -0
- package/dist/static-rule-guidance.d.ts.map +1 -0
- package/dist/static-rule-guidance.js +165 -0
- package/dist/stringEdgeStrip.d.ts +8 -0
- package/dist/stringEdgeStrip.d.ts.map +1 -0
- package/dist/stringEdgeStrip.js +25 -0
- package/docs/CI.md +122 -0
- package/docs/DRIFT.md +52 -0
- package/docs/MCP.md +153 -0
- package/docs/RULE_CODES.md +208 -0
- package/package.json +17 -10
- package/scripts/generate-corpus.mjs +667 -0
- package/scripts/npm-postinstall.mjs +22 -0
- package/scripts/smoke-mcp.mjs +44 -0
package/docs/CI.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# CI integration — `archrad validate`
|
|
2
|
+
|
|
3
|
+
`archrad validate` is the usual gate for **architecture-as-code** in pipelines. It reads an IR JSON file and runs structural validation (IR-STRUCT-*) plus architecture lint (IR-LINT-*).
|
|
4
|
+
|
|
5
|
+
## Exit codes
|
|
6
|
+
|
|
7
|
+
| Situation | Default exit code |
|
|
8
|
+
|-----------|-------------------|
|
|
9
|
+
| No findings | **0** |
|
|
10
|
+
| Any finding with severity **`error`** (structural / blocking) | **1** |
|
|
11
|
+
| **Warnings only** (e.g. many IR-LINT-* rules) | **0** |
|
|
12
|
+
|
|
13
|
+
Optional stricter gates:
|
|
14
|
+
|
|
15
|
+
- **`--fail-on-warning`** — exit **1** if any warning exists.
|
|
16
|
+
- **`--max-warnings <n>`** — exit **1** if the warning count is **greater than** `n` (e.g. **`--max-warnings 0`** allows no warnings).
|
|
17
|
+
|
|
18
|
+
JSON output: add **`--json`** (findings array on stdout).
|
|
19
|
+
|
|
20
|
+
Policy packs: **`--policies <dir>`** (directory of PolicyPack YAML/JSON), merged after built-in IR-LINT-* (omit **`--skip-lint`** if you want lint + policies).
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx archrad validate --ir ./graph.json
|
|
26
|
+
npx archrad validate --ir ./graph.json --fail-on-warning
|
|
27
|
+
npx archrad validate --ir ./graph.json --max-warnings 0 --json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Install **`@archrad/deterministic`** as a dev dependency so `npx archrad` resolves locally, or invoke **`node node_modules/@archrad/deterministic/dist/cli.js`** explicitly.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## GitHub Actions
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
jobs:
|
|
38
|
+
archrad:
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
- uses: actions/setup-node@v4
|
|
43
|
+
with:
|
|
44
|
+
node-version: '20'
|
|
45
|
+
cache: 'npm'
|
|
46
|
+
- run: npm ci
|
|
47
|
+
- run: npx archrad validate --ir ./path/to/graph.json
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
With warnings as failures:
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
- run: npx archrad validate --ir ./path/to/graph.json --fail-on-warning
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## GitLab CI
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
archrad-validate:
|
|
62
|
+
image: node:20-bookworm
|
|
63
|
+
script:
|
|
64
|
+
- npm ci
|
|
65
|
+
- npx archrad validate --ir ./path/to/graph.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Bitbucket Pipelines
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
pipelines:
|
|
74
|
+
default:
|
|
75
|
+
- step:
|
|
76
|
+
name: ArchRad validate
|
|
77
|
+
image: node:20
|
|
78
|
+
script:
|
|
79
|
+
- npm ci
|
|
80
|
+
- npx archrad validate --ir ./path/to/graph.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Jenkins (Declarative)
|
|
86
|
+
|
|
87
|
+
```groovy
|
|
88
|
+
pipeline {
|
|
89
|
+
agent any
|
|
90
|
+
stages {
|
|
91
|
+
stage('ArchRad') {
|
|
92
|
+
steps {
|
|
93
|
+
sh 'npm ci'
|
|
94
|
+
sh 'npx archrad validate --ir ./path/to/graph.json'
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Azure DevOps
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
steps:
|
|
107
|
+
- task: NodeTool@0
|
|
108
|
+
inputs:
|
|
109
|
+
versionSpec: '20.x'
|
|
110
|
+
- script: npm ci
|
|
111
|
+
displayName: npm ci
|
|
112
|
+
- script: npx archrad validate --ir ./path/to/graph.json
|
|
113
|
+
displayName: archrad validate
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Notes
|
|
119
|
+
|
|
120
|
+
- Replace **`./path/to/graph.json`** with your IR path (repo-relative in CI).
|
|
121
|
+
- Ensure the job installs the same **`@archrad/deterministic`** version you use locally (`package.json` / lockfile).
|
|
122
|
+
- Drift checks use **`archrad validate-drift`** (separate command); see **`docs/DRIFT.md`**.
|
package/docs/DRIFT.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Deterministic drift (`validate-drift`)
|
|
2
|
+
|
|
3
|
+
**Canonical OSS description** — versioned with **`@archrad/deterministic`**.
|
|
4
|
+
**Not** semantic “does this code match business intent?” — that class of analysis is out of scope for this layer (see **`STRUCTURAL_VS_SEMANTIC_VALIDATION.md`**).
|
|
5
|
+
|
|
6
|
+
## What it is
|
|
7
|
+
|
|
8
|
+
**Drift** here means: you already have an **on-disk tree** (usually from `archrad export`), and you want to know whether it still matches what the **deterministic exporter would produce today** from the **same IR**.
|
|
9
|
+
|
|
10
|
+
The engine:
|
|
11
|
+
|
|
12
|
+
1. Runs a **fresh export** from your IR in memory (same pipeline as `archrad export`).
|
|
13
|
+
2. Compares the **expected file set + contents** to what is on disk (paths normalized, line endings normalized to `\n`).
|
|
14
|
+
3. Emits **DRIFT-*** findings when something is missing, changed, or (optionally) extra.
|
|
15
|
+
|
|
16
|
+
So: **regen vs reality** — a thin gate for CI and pre-merge checks.
|
|
17
|
+
|
|
18
|
+
## What it is not
|
|
19
|
+
|
|
20
|
+
- **Not** diffing IR to arbitrary hand-written code semantics.
|
|
21
|
+
- **Not** proving runtime behavior or security — use tests, review, and (where applicable) **ArchRad Cloud** governance.
|
|
22
|
+
|
|
23
|
+
## CLI
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
archrad validate-drift -i ./graph.json -t python -o ./out
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use **`--json`** in CI. **`--strict-extra`** treats unexpected files in the output directory as findings. **`--skip-ir-lint`** / **`--policies`** follow the same semantics as **`export`** (see **`README.md`**).
|
|
30
|
+
|
|
31
|
+
## Library
|
|
32
|
+
|
|
33
|
+
**`runValidateDrift`**, **`diffExpectedExportAgainstFiles`**, **`readDirectoryAsExportMap`** — see **`src/validate-drift.ts`**.
|
|
34
|
+
|
|
35
|
+
## MCP
|
|
36
|
+
|
|
37
|
+
**`archrad_validate_drift`** — same semantics: IR (inline or **`irPath`**) + **`target`** + **`exportDir`**. See **`MCP.md`**.
|
|
38
|
+
|
|
39
|
+
## DRIFT-* codes
|
|
40
|
+
|
|
41
|
+
| Code | Meaning |
|
|
42
|
+
|------|--------|
|
|
43
|
+
| **DRIFT-MISSING** | A file the exporter would emit is missing on disk. |
|
|
44
|
+
| **DRIFT-MODIFIED** | File exists but content differs from the deterministic export. |
|
|
45
|
+
| **DRIFT-EXTRA** | File exists on disk but is not in the reference export (with **`--strict-extra`**). |
|
|
46
|
+
| **DRIFT-NO-EXPORT** | Exporter produced no file map (often blocked by structural/lint errors or empty target output). |
|
|
47
|
+
|
|
48
|
+
Remediation text for each code (aligned with MCP **`archrad_suggest_fix`**) lives in **`RULE_CODES.md`** and **`src/static-rule-guidance.ts`**.
|
|
49
|
+
|
|
50
|
+
## Product site
|
|
51
|
+
|
|
52
|
+
**archrad.com** may host narrative pages (e.g. `/docs/drift`) for onboarding; **definitions and CLI/MCP behavior** are maintained **here** in the OSS repo so they ship with the engine.
|
package/docs/MCP.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# ArchRad MCP server — specification
|
|
2
|
+
|
|
3
|
+
**Status:** **0.1.x** — `archrad-mcp` ships in **`@archrad/deterministic`** (stdio MCP, same engine as CLI).
|
|
4
|
+
**Audience:** Engineering + launch narrative (Show HN / registry listing).
|
|
5
|
+
|
|
6
|
+
## 1. Problem statement
|
|
7
|
+
|
|
8
|
+
| Mode | Behavior |
|
|
9
|
+
|------|------------|
|
|
10
|
+
| **Reactive** | CI runs `archrad` after code exists → catches drift late. |
|
|
11
|
+
| **Proactive** | An MCP server answers **before** edits land: “Is this edge allowed?”, “What does IR-LINT say about this sketch?” |
|
|
12
|
+
|
|
13
|
+
Agents optimize for *working code*; ArchRad supplies **deterministic constraints** so the loop can ask the engine *before* violating architecture.
|
|
14
|
+
|
|
15
|
+
## 2. OSS vs product boundary
|
|
16
|
+
|
|
17
|
+
Aligned with **`STRUCTURAL_VS_SEMANTIC_VALIDATION.md`** (this folder) and your org’s OSS/product split docs.
|
|
18
|
+
|
|
19
|
+
| Surface | Ships in **OSS** (`@archrad/deterministic`, binary **`archrad-mcp`**) | Stays in **product / Cloud** |
|
|
20
|
+
|---------|------------------------------------------------------------------------|------------------------------|
|
|
21
|
+
| IR structural validation (`IR-STRUCT-*`) | Yes | — |
|
|
22
|
+
| Architecture lint (`IR-LINT-*`) + PolicyPack YAML from **local dir** | Yes | — |
|
|
23
|
+
| `validate_drift` vs on-disk export (local paths) | Yes | — |
|
|
24
|
+
| Static remediation text per **built-in** code (`archrad_suggest_fix`) | Yes | — |
|
|
25
|
+
| Org **`settings.archPolicyPacks`**, Firestore, membership | — | Yes |
|
|
26
|
+
| Semantic “is this business-correct?” reasoning | — | Yes (future assisted tools) |
|
|
27
|
+
|
|
28
|
+
**Rule of thumb:** If the tool only needs **IR JSON + local files**, it can live in the public MCP server. If it needs **tenant identity, billing, or org policy from Cloud**, expose a **separate** “ArchRad Cloud” MCP connector (private or authenticated) — do not move Cloud policy enforcement into OSS without an explicit product decision.
|
|
29
|
+
|
|
30
|
+
## 3. Transport and packaging
|
|
31
|
+
|
|
32
|
+
- **Protocol:** [Model Context Protocol](https://modelcontextprotocol.io/) over **stdio** (default for Cursor, Claude Desktop, Copilot agent adapters).
|
|
33
|
+
- **Package:** **`@archrad/deterministic`** publishes two binaries: **`archrad`** (CLI) and **`archrad-mcp`** (MCP). One implementation backs CLI + MCP.
|
|
34
|
+
- **Registry:** Optional `server.json` / manifest for MCP Registry; document install for Cursor “Add MCP server”.
|
|
35
|
+
|
|
36
|
+
## 4. IR payload size and `ir` vs `irPath`
|
|
37
|
+
|
|
38
|
+
| Concern | Guidance |
|
|
39
|
+
|---------|----------|
|
|
40
|
+
| **Inline `ir`** | Fine for small/medium graphs. Large JSON in a single tool call still stresses **host message limits** and **model context** — prefer **`irPath`** when the IR is big. |
|
|
41
|
+
| **`irPath`** | Absolute or relative path to a **single JSON file** (same shape as CLI `--ir`). Enforced **max file size 25 MiB** in the server (hard cap); if you exceed it, split validation or trim fixtures. |
|
|
42
|
+
| **Soft ceiling** | Below ~**5k–10k nodes**, inline JSON is usually workable if the host allows; above that, **`irPath` is recommended**. This is not a graph semantics limit — only practical transport/memory. |
|
|
43
|
+
| **Exactly one** | Provide **`ir`** **or** **`irPath`**, not both, not neither (for tools that need IR). |
|
|
44
|
+
|
|
45
|
+
**Privacy:** The OSS server does **not** add analytics or tracking parameters to tool responses. Optional product docs URLs use a stable path only (see **`archrad_suggest_fix`**).
|
|
46
|
+
|
|
47
|
+
## 5. Local testing
|
|
48
|
+
|
|
49
|
+
### 5.1 Smoke script (npm)
|
|
50
|
+
|
|
51
|
+
From the **`@archrad/deterministic`** package root (where **`package.json`** lives):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm run build
|
|
55
|
+
npm run smoke:mcp
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Exit code **0** means the MCP server spawned **`dist/mcp-server.js`**, listed tools, and successfully called **`archrad_suggest_fix`**.
|
|
59
|
+
|
|
60
|
+
### 5.2 MCP Inspector (browser UI)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx @modelcontextprotocol/inspector node dist/mcp-server.js
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Open the URL Inspector prints (often **http://localhost:6274**). Under **Tools**, run **`archrad_list_rule_codes`** (no args), then **`archrad_validate_ir`** with **`irPath`** set to **`fixtures/minimal-graph.json`** (relative paths work if the process was started with **cwd** set to the package root).
|
|
67
|
+
|
|
68
|
+
### 5.3 Cursor (MCP config + chat)
|
|
69
|
+
|
|
70
|
+
1. **Build** so **`dist/mcp-server.js`** exists (`npm run build`).
|
|
71
|
+
2. In Cursor **Settings → MCP**, add a server (exact JSON shape depends on Cursor version):
|
|
72
|
+
- **Command:** `node` (or full path to `node.exe` on Windows).
|
|
73
|
+
- **Args:** full path to **`dist/mcp-server.js`**.
|
|
74
|
+
- **Cwd (recommended):** the deterministic package root (directory containing **`package.json`**). Relative **`irPath`** values like **`fixtures/minimal-graph.json`** resolve from this directory.
|
|
75
|
+
3. **Chat:** Cursor does not always show a “run tool” button for every server. Use **Agent** mode (or another mode that supports **tool use**) and ask explicitly, for example:
|
|
76
|
+
|
|
77
|
+
**List codes:**
|
|
78
|
+
|
|
79
|
+
> Use the MCP tool **`archrad_list_rule_codes`** (no arguments) and show me the raw JSON result.
|
|
80
|
+
|
|
81
|
+
**Validate via file:**
|
|
82
|
+
|
|
83
|
+
> Use the MCP tool **`archrad_validate_ir`** with **`irPath`** set to **`fixtures/minimal-graph.json`** (relative to the deterministic package). Show the full tool result.
|
|
84
|
+
|
|
85
|
+
If the model says it cannot find the tool, the MCP server failed to start or the configured server name does not match — check Cursor’s MCP panel for errors.
|
|
86
|
+
|
|
87
|
+
4. **If `irPath` fails** with “file not found”, use the **absolute path** to **`fixtures/minimal-graph.json`**.
|
|
88
|
+
|
|
89
|
+
### 5.4 Success criteria
|
|
90
|
+
|
|
91
|
+
- **`archrad_list_rule_codes`:** JSON with a **`codes`** array.
|
|
92
|
+
- **`archrad_validate_ir`:** JSON with **`irStructuralFindings`**, **`irLintFindings`**, **`combined`**, **`ok`** — not a connection or file error.
|
|
93
|
+
|
|
94
|
+
## 6. Tools (0.1.6)
|
|
95
|
+
|
|
96
|
+
Tools are **idempotent** and **deterministic** where stated.
|
|
97
|
+
|
|
98
|
+
### 6.1 Core
|
|
99
|
+
|
|
100
|
+
| Tool | Input | Output | Notes |
|
|
101
|
+
|------|--------|--------|-------|
|
|
102
|
+
| **`archrad_validate_ir`** | `ir` **or** `irPath`; optional `policiesDirectory` | `{ ok, irStructuralFindings, irLintFindings, combined }` | Same as CLI validate. |
|
|
103
|
+
| **`archrad_lint_summary`** | `ir` **or** `irPath`; optional `policiesDirectory` | Short summary + counts | Agent-friendly. |
|
|
104
|
+
| **`archrad_validate_drift`** | `ir` **or** `irPath`; `target`; `exportDir`; optional policies, `skipIrLint` | Drift + export findings | Same engine as CLI `validate-drift`. **MCP `target` values:** `python` or `nodejs` only (not `node`). The CLI `validate-drift` / `export` may still accept `node` as an alias for Node exports. |
|
|
105
|
+
| **`archrad_policy_packs_load`** | `directory` or `files[]` | `{ ok, ruleCount }` or errors | Compiles packs; does not return visitor functions over MCP. |
|
|
106
|
+
|
|
107
|
+
### 6.2 Static guidance (no generated architecture)
|
|
108
|
+
|
|
109
|
+
| Tool | Input | Output | Notes |
|
|
110
|
+
|------|--------|--------|-------|
|
|
111
|
+
| **`archrad_suggest_fix`** | `findingCode` (e.g. `IR-LINT-MISSING-AUTH-010`) | `{ ok, findingCode, title, remediation, docsUrl }` or `{ ok: false, error }` | **Curated text only** — not JSON Patch, not IR edits, not LLM output. **`docsUrl`** points to the **[`RULE_CODES.md`](https://github.com/archradhq/arch-deterministic/blob/main/docs/RULE_CODES.md)** section for that code on **GitHub** (canonical OSS; no query strings). Unknown built-in codes and **PolicyPack/org** ids return `ok: false` with a short explanation. |
|
|
112
|
+
| **`archrad_list_rule_codes`** | _(none)_ | `{ codes: string[] }` | Sorted list of built-in codes with static guidance. |
|
|
113
|
+
|
|
114
|
+
**Explicit non-goal:** **`archrad_suggest_fix` must not** return machine-generated graph edits or “patches” that invent services — that would be **generative** and would break the deterministic OSS contract.
|
|
115
|
+
|
|
116
|
+
### 6.3 Explicit non-goals (MVP)
|
|
117
|
+
|
|
118
|
+
- No automatic **code** generation inside MCP (keep **`export`** as CLI/CI).
|
|
119
|
+
- No remote calls to ArchRad Cloud unless a **separate authenticated** server is defined.
|
|
120
|
+
- No **tracking** query parameters in MCP tool payloads.
|
|
121
|
+
|
|
122
|
+
## 7. Resources (optional)
|
|
123
|
+
|
|
124
|
+
| Resource URI | Content |
|
|
125
|
+
|--------------|---------|
|
|
126
|
+
| `archrad://docs/ir-contract` | Pointer to bundled `IR_CONTRACT.md` snippet or link. |
|
|
127
|
+
| `archrad://schemas/ir-graph-v1` | JSON Schema for IR graph validation. |
|
|
128
|
+
|
|
129
|
+
## 8. Security
|
|
130
|
+
|
|
131
|
+
- **Local-only by default:** IR and paths stay on the user machine; **no telemetry** in the OSS server unless explicitly documented elsewhere.
|
|
132
|
+
- **Path sandbox:** Validate `exportDir` / `irPath` against workspace roots if the host passes a `workspaceRoot` (host-dependent).
|
|
133
|
+
- **Cloud MCP (future):** OAuth or API keys; never embed product secrets in OSS.
|
|
134
|
+
|
|
135
|
+
## 9. Launch narrative (copy bank)
|
|
136
|
+
|
|
137
|
+
- **One-liner:** *AI agents write code fast but drift from your architecture; ArchRad MCP gives them the same deterministic IR checks as CI, inside the agent loop.*
|
|
138
|
+
- **Show HN angle:** *Architectural conscience for Copilot / Cursor — IR-LINT before you merge.*
|
|
139
|
+
|
|
140
|
+
## 10. Related repo tasks
|
|
141
|
+
|
|
142
|
+
- **Quality:** Keep graph/lint work responsive so MCP tools stay usable on mid-size IRs.
|
|
143
|
+
|
|
144
|
+
## 11. Implementation checklist
|
|
145
|
+
|
|
146
|
+
1. ~~Node MCP server (`@modelcontextprotocol/sdk`), stdio transport.~~
|
|
147
|
+
2. ~~`archrad_validate_ir` + `archrad_validate_drift` + policy load + static `archrad_suggest_fix`.~~
|
|
148
|
+
3. README + **`docs/MCP.md`**: Cursor config, `ir` / `irPath`, local testing (smoke, Inspector, chat prompts).
|
|
149
|
+
4. Publish **`@archrad/deterministic`** to npm; subtree to public repo per release process.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
*This document aligns OSS MCP scope with product strategy; update when adding Cloud-only tools.*
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Built-in finding codes (IR-STRUCT, IR-LINT, DRIFT)
|
|
2
|
+
|
|
3
|
+
**Canonical OSS reference** — ships in **`@archrad/deterministic`**.
|
|
4
|
+
**MCP** **`archrad_suggest_fix`** returns **`title`**, **`remediation`**, and a **`docsUrl`** pointing at the matching section below. **PolicyPack / org** rules use custom ids (e.g. `ORG-*`) — not listed here.
|
|
5
|
+
|
|
6
|
+
**Product / marketing** copy may live on **archrad.com**; **deterministic semantics** are defined in this repo.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## DRIFT-EXTRA
|
|
11
|
+
|
|
12
|
+
Extra file not in deterministic export. **Remediation:** Remove stray files from the export directory or add them to the model if they should be generated. Use **`--strict-extra`** semantics as documented for your CI gate.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## DRIFT-MISSING
|
|
17
|
+
|
|
18
|
+
Exported file missing on disk. **Remediation:** Regenerate the export (**`archrad export`**) or restore the missing file so the tree matches the deterministic output for this IR.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## DRIFT-MODIFIED
|
|
23
|
+
|
|
24
|
+
File differs from deterministic export. **Remediation:** Revert manual edits to generated files or update the IR and re-export so the on-disk tree matches the compiler output.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## DRIFT-NO-EXPORT
|
|
29
|
+
|
|
30
|
+
No export produced for drift comparison. **Remediation:** Fix IR structural/lint errors blocking export, or verify **`--target`** and IR content so the exporter emits files.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## IR-LINT-DATASTORE-NO-INCOMING-008
|
|
35
|
+
|
|
36
|
+
Datastore has no incoming edges. **Remediation:** Connect a service or data path to this datastore, or remove it if unused.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## IR-LINT-DEAD-NODE-011
|
|
41
|
+
|
|
42
|
+
Non-sink node with incoming edges but no outgoing edges. **Remediation:** Add an outgoing edge to a downstream consumer, or remove the node if it is obsolete.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## IR-LINT-DIRECT-DB-ACCESS-002
|
|
47
|
+
|
|
48
|
+
HTTP-like node connects directly to a datastore. **Remediation:** Introduce a service or domain layer between HTTP handlers and persistence.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## IR-LINT-DUPLICATE-EDGE-006
|
|
53
|
+
|
|
54
|
+
Duplicate from→to edge. **Remediation:** Collapse duplicate edges or distinguish them with metadata if your model allows.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## IR-LINT-HIGH-FANOUT-004
|
|
59
|
+
|
|
60
|
+
High outgoing dependency count. **Remediation:** Reduce fan-out: split responsibilities, add a facade, batch calls, or use async handoff.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## IR-LINT-HTTP-MISSING-NAME-007
|
|
65
|
+
|
|
66
|
+
HTTP-like node missing display name. **Remediation:** Set a short human-readable **`name`** on the node.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## IR-LINT-ISOLATED-NODE-005
|
|
71
|
+
|
|
72
|
+
Node has no incident edges. **Remediation:** Remove the orphan or connect it with edges.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## IR-LINT-MISSING-AUTH-010
|
|
77
|
+
|
|
78
|
+
HTTP entry missing auth coverage. **Remediation:** Add an auth boundary (auth/middleware/oauth/jwt node or **`config.authRequired: false`** for public endpoints).
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## IR-LINT-MULTIPLE-HTTP-ENTRIES-009
|
|
83
|
+
|
|
84
|
+
Multiple HTTP entry nodes without incoming edges. **Remediation:** Prefer a single API gateway or BFF unless multiple public surfaces are intentional.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## IR-LINT-NO-HEALTHCHECK-003
|
|
89
|
+
|
|
90
|
+
No typical health/readiness route on HTTP nodes. **Remediation:** Add a GET route such as **`/health`** or **`/ready`**.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## IR-LINT-SYNC-CHAIN-001
|
|
95
|
+
|
|
96
|
+
Long synchronous chain from HTTP entry. **Remediation:** Shorten the graph or mark non-blocking hops as async in edge metadata.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## IR-STRUCT-CYCLE
|
|
101
|
+
|
|
102
|
+
Directed cycle in the graph. **Remediation:** Remove or break cyclic edges unless your tooling explicitly allows execution loops.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## IR-STRUCT-DUP_NODE_ID
|
|
107
|
+
|
|
108
|
+
Duplicate node id. **Remediation:** Ensure node ids are unique.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## IR-STRUCT-EDGE_AMBIGUOUS_FROM
|
|
113
|
+
|
|
114
|
+
Edge references duplicate source id. **Remediation:** Resolve duplicate node ids first.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## IR-STRUCT-EDGE_AMBIGUOUS_TO
|
|
119
|
+
|
|
120
|
+
Edge references duplicate target id. **Remediation:** Resolve duplicate node ids first.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## IR-STRUCT-EDGE_INVALID
|
|
125
|
+
|
|
126
|
+
Edge is not an object. **Remediation:** Each edge must be an object with **`from`**/**`to`** (or **`source`**/**`target`**).
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## IR-STRUCT-EDGE_NO_ENDPOINTS
|
|
131
|
+
|
|
132
|
+
Edge missing endpoints. **Remediation:** Set **`from`** and **`to`** to existing node ids.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## IR-STRUCT-EDGE_UNKNOWN_FROM
|
|
137
|
+
|
|
138
|
+
Edge references unknown source node. **Remediation:** Add a node with the referenced id or correct **`from`**.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## IR-STRUCT-EDGE_UNKNOWN_TO
|
|
143
|
+
|
|
144
|
+
Edge references unknown target node. **Remediation:** Add a node with the referenced id or correct **`to`**.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## IR-STRUCT-EDGES_NOT_ARRAY
|
|
149
|
+
|
|
150
|
+
**`edges`** is present but not an array. **Remediation:** Set **`edges`** to an array of edge objects (or omit **`edges`**).
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## IR-STRUCT-EMPTY_GRAPH
|
|
155
|
+
|
|
156
|
+
Graph has no nodes. **Remediation:** Add at least one node before validation or export.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## IR-STRUCT-HTTP_METHOD
|
|
161
|
+
|
|
162
|
+
HTTP method not supported. **Remediation:** Use GET, POST, PUT, PATCH, DELETE, HEAD, or OPTIONS.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## IR-STRUCT-HTTP_PATH
|
|
167
|
+
|
|
168
|
+
HTTP endpoint path invalid. **Remediation:** Set **`config.url`** or **`config.route`** to a path starting with **`/`**.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## IR-STRUCT-INVALID_ROOT
|
|
173
|
+
|
|
174
|
+
IR root is not a JSON object. **Remediation:** Pass a single JSON object with **`graph`** or top-level **`nodes`**.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## IR-STRUCT-NO_GRAPH
|
|
179
|
+
|
|
180
|
+
Missing graph shape. **Remediation:** Include **`.graph`** with **`nodes`** or a top-level **`nodes`** array.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## IR-STRUCT-NODE_INVALID
|
|
185
|
+
|
|
186
|
+
Node entry is not an object. **Remediation:** Each **`nodes`** entry must be a JSON object with **`id`** and type information.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## IR-STRUCT-NODE_INVALID_CONFIG
|
|
191
|
+
|
|
192
|
+
Node **`config`** is not a plain object. **Remediation:** Use a plain object for **`config`**.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## IR-STRUCT-NODE_NO_ID
|
|
197
|
+
|
|
198
|
+
Node missing non-empty id. **Remediation:** Assign a stable string **`id`** to every node.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## IR-STRUCT-NODES_NOT_ARRAY
|
|
203
|
+
|
|
204
|
+
**`nodes`** is not an array. **Remediation:** Set **`nodes`** to an array of node objects.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
*Full strings in MCP/CLI mirror **`src/static-rule-guidance.ts`** (single implementation).*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archrad/deterministic",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A deterministic compiler and linter for system architecture. Validate your architecture before you write code. OSS: structural validation + basic architecture lint (rule-based); FastAPI/Express export; OpenAPI document-shape; golden Docker/Makefile — no LLM.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"archrad",
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"deterministic",
|
|
15
15
|
"codegen",
|
|
16
16
|
"docker",
|
|
17
|
-
"cli"
|
|
17
|
+
"cli",
|
|
18
|
+
"mcp",
|
|
19
|
+
"model-context-protocol"
|
|
18
20
|
],
|
|
19
21
|
"homepage": "https://github.com/archradhq/arch-deterministic#readme",
|
|
20
22
|
"bugs": {
|
|
@@ -39,7 +41,8 @@
|
|
|
39
41
|
}
|
|
40
42
|
},
|
|
41
43
|
"bin": {
|
|
42
|
-
"archrad": "./dist/cli.js"
|
|
44
|
+
"archrad": "./dist/cli.js",
|
|
45
|
+
"archrad-mcp": "./dist/mcp-server.js"
|
|
43
46
|
},
|
|
44
47
|
"files": [
|
|
45
48
|
"dist",
|
|
@@ -61,22 +64,26 @@
|
|
|
61
64
|
"scripts": {
|
|
62
65
|
"build": "tsc -p tsconfig.build.json",
|
|
63
66
|
"prepublishOnly": "npm run build",
|
|
64
|
-
"test": "tsc -p tsconfig.build.json --noEmit && vitest run",
|
|
67
|
+
"test": "tsc -p tsconfig.build.json --noEmit && npm run build && vitest run",
|
|
65
68
|
"lint": "biome check ./src",
|
|
66
69
|
"typecheck": "tsc -p tsconfig.build.json --noEmit",
|
|
70
|
+
"generate-corpus": "node scripts/generate-corpus.mjs",
|
|
71
|
+
"smoke:mcp": "node scripts/smoke-mcp.mjs",
|
|
67
72
|
"record:demo:payment-retry": "vhs scripts/record-demo-payment-retry.tape",
|
|
68
73
|
"record:demo:drift": "vhs scripts/record-demo-drift.tape"
|
|
69
74
|
},
|
|
70
75
|
"dependencies": {
|
|
71
|
-
"
|
|
72
|
-
"
|
|
76
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
77
|
+
"commander": "^14.0.3",
|
|
78
|
+
"js-yaml": "^4.1.0",
|
|
79
|
+
"zod": "^4.3.6"
|
|
73
80
|
},
|
|
74
81
|
"devDependencies": {
|
|
75
|
-
"@biomejs/biome": "^
|
|
82
|
+
"@biomejs/biome": "^2.4.9",
|
|
76
83
|
"@types/js-yaml": "^4.0.9",
|
|
77
|
-
"@types/node": "^
|
|
78
|
-
"typescript": "^
|
|
79
|
-
"vitest": "^4.
|
|
84
|
+
"@types/node": "^25.5.0",
|
|
85
|
+
"typescript": "^6.0.2",
|
|
86
|
+
"vitest": "^4.1.2"
|
|
80
87
|
},
|
|
81
88
|
"engines": {
|
|
82
89
|
"node": ">=20"
|