archgate 0.1.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.md ADDED
@@ -0,0 +1,105 @@
1
+ # Functional Source License, Version 1.1, ALv2 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-ALv2
6
+
7
+ ## Notice
8
+
9
+ Copyright 2025 Archgate
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
package/README.md ADDED
@@ -0,0 +1,237 @@
1
+ # Archgate
2
+
3
+ <div align="center">
4
+
5
+ **Enforce Architecture Decision Records as executable rules — for both humans and AI agents.**
6
+
7
+ [![License: FSL-1.1-ALv2](https://img.shields.io/badge/License-FSL--1.1--ALv2-blue.svg)](LICENSE.md)
8
+ [![Release](https://github.com/archgate/cli/actions/workflows/release.yml/badge.svg)](https://github.com/archgate/cli/actions/workflows/release.yml)
9
+
10
+ </div>
11
+
12
+ ---
13
+
14
+ Archgate turns your Architecture Decision Records into a governance layer that runs in CI, enforces rules in pre-commit hooks, and feeds live context to AI coding agents — so architectural decisions don't stay in documents, they stay in the code.
15
+
16
+ **Write an ADR once. Enforce it everywhere.**
17
+
18
+ ## How it works
19
+
20
+ Archgate has two layers:
21
+
22
+ 1. **ADRs as documents** — markdown files with YAML frontmatter stored in `.archgate/adrs/`. Each ADR records a decision: what was decided, why, and what to do and not do.
23
+ 2. **ADRs as rules** — each ADR can have a companion `.rules.ts` file that exports automated checks. Archgate runs these checks against your codebase and reports violations.
24
+
25
+ ```
26
+ .archgate/
27
+ └── adrs/
28
+ ├── ARCH-001-command-structure.md # human-readable decision
29
+ ├── ARCH-001-command-structure.rules.ts # machine-executable checks
30
+ ├── ARCH-002-error-handling.md
31
+ └── ARCH-002-error-handling.rules.ts
32
+ ```
33
+
34
+ When a rule is violated, `archgate check` reports the file, line, and which ADR was broken. Exit code 1 means violations — wire it into CI and it blocks merges automatically.
35
+
36
+ **The AI integration layer** is a Claude Code plugin that gives AI agents live access to your ADRs through the MCP server (`archgate mcp`). Agents read the decisions before writing code, validate changes after, and capture new patterns into the governance base. Archgate ships as its own governance subject — its own development is governed by the ADRs in `.archgate/adrs/`.
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ curl -fsSL https://archgate.dev/install.sh | sh
42
+ ```
43
+
44
+ Installs the standalone binary to `~/.archgate/bin/` and adds it to your PATH.
45
+
46
+ **Requirements:** macOS (arm64) or Linux (x86_64).
47
+
48
+ ## Quick start
49
+
50
+ ```bash
51
+ # 1. Install
52
+ curl -fsSL https://archgate.dev/install.sh | sh
53
+
54
+ # 2. Initialize governance in your project
55
+ cd my-project
56
+ archgate init
57
+
58
+ # 3. Edit the generated ADR to document a real decision
59
+ # .archgate/adrs/ARCH-001-*.md
60
+
61
+ # 4. Add a companion .rules.ts to enforce it automatically
62
+ # .archgate/adrs/ARCH-001-*.rules.ts
63
+
64
+ # 5. Run checks
65
+ archgate check
66
+ ```
67
+
68
+ `archgate init` creates the `.archgate/adrs/` directory, an example ADR with a companion rules file to show the pattern, and configures the Claude Code plugin if you use it.
69
+
70
+ ## Writing rules
71
+
72
+ A companion `.rules.ts` file exports checks using `defineRules()` from the `archgate` package:
73
+
74
+ ```typescript
75
+ // .archgate/adrs/ARCH-002-error-handling.rules.ts
76
+ import { defineRules } from "archgate/rules";
77
+
78
+ export default defineRules([
79
+ {
80
+ id: "use-log-error",
81
+ description:
82
+ "Use logError() instead of console.error() for user-facing errors",
83
+ severity: "error",
84
+ async check({ files }) {
85
+ const violations = [];
86
+ for (const file of files) {
87
+ const content = await Bun.file(file).text();
88
+ const lines = content.split("\n");
89
+ lines.forEach((line, i) => {
90
+ if (line.includes("console.error(")) {
91
+ violations.push({
92
+ file,
93
+ line: i + 1,
94
+ message: "Use logError() instead",
95
+ });
96
+ }
97
+ });
98
+ }
99
+ return violations;
100
+ },
101
+ },
102
+ ]);
103
+ ```
104
+
105
+ Rules receive the list of files to check (filtered by the ADR's `files` glob if set), and return an array of violations with file paths and line numbers.
106
+
107
+ ## Commands
108
+
109
+ ### `archgate init`
110
+
111
+ Initialize governance in the current project.
112
+
113
+ ```bash
114
+ archgate init
115
+ ```
116
+
117
+ Creates `.archgate/adrs/` with an example ADR and rules file, and optionally wires up the Claude Code plugin.
118
+
119
+ ### `archgate check`
120
+
121
+ Run all automated ADR checks against your codebase.
122
+
123
+ ```bash
124
+ archgate check # check all files
125
+ archgate check --staged # check only git-staged files (for pre-commit hooks)
126
+ archgate check --json # machine-readable JSON output
127
+ ```
128
+
129
+ Exits with code 0 if all checks pass, 1 if any violations are found.
130
+
131
+ ### `archgate adr create`
132
+
133
+ Create a new ADR interactively.
134
+
135
+ ```bash
136
+ archgate adr create
137
+ ```
138
+
139
+ Prompts for a title, domain, and optional file glob. Generates a sequential ID (`ARCH-001`, `ARCH-002`, ...) and writes the markdown file.
140
+
141
+ ### `archgate adr list`
142
+
143
+ List all ADRs in the project.
144
+
145
+ ```bash
146
+ archgate adr list # table output
147
+ archgate adr list --json # JSON output
148
+ archgate adr list --domain backend # filter by domain
149
+ ```
150
+
151
+ ### `archgate adr show <id>`
152
+
153
+ Print a specific ADR.
154
+
155
+ ```bash
156
+ archgate adr show ARCH-001
157
+ ```
158
+
159
+ ### `archgate adr update`
160
+
161
+ Update an existing ADR's frontmatter.
162
+
163
+ ```bash
164
+ archgate adr update ARCH-001 --title "New Title" --domain backend
165
+ ```
166
+
167
+ ### `archgate mcp`
168
+
169
+ Start the MCP server for AI agent integration.
170
+
171
+ ```bash
172
+ archgate mcp
173
+ ```
174
+
175
+ Exposes four tools to MCP-compatible clients (Claude Code, Cursor, etc.):
176
+
177
+ | Tool | Description |
178
+ | ----------------- | ----------------------------------------------------------------- |
179
+ | `check` | Run ADR compliance checks, optionally on staged files only |
180
+ | `list_adrs` | List all ADRs with metadata |
181
+ | `review_context` | Get changed files grouped by domain with applicable ADR briefings |
182
+ | `session_context` | Read the current Claude Code session transcript |
183
+
184
+ Also exposes `adr://{id}` resources for reading individual ADRs by ID.
185
+
186
+ ### `archgate upgrade`
187
+
188
+ Upgrade to the latest release.
189
+
190
+ ```bash
191
+ archgate upgrade
192
+ ```
193
+
194
+ ### `archgate clean`
195
+
196
+ Remove the CLI cache directory (`~/.archgate/`).
197
+
198
+ ```bash
199
+ archgate clean
200
+ ```
201
+
202
+ ## CI integration
203
+
204
+ Add a check step to your pipeline:
205
+
206
+ ```yaml
207
+ # GitHub Actions example
208
+ - name: ADR compliance check
209
+ run: archgate check
210
+ ```
211
+
212
+ For pre-commit hooks (using [lefthook](https://github.com/evilmartians/lefthook) or similar):
213
+
214
+ ```yaml
215
+ pre-commit:
216
+ commands:
217
+ adr-check:
218
+ run: archgate check --staged
219
+ ```
220
+
221
+ ## Claude Code plugin
222
+
223
+ The Claude Code plugin (`archgate:developer`) gives AI agents a full governance workflow:
224
+
225
+ - Reads applicable ADRs before writing code
226
+ - Validates changes after implementation
227
+ - Captures new patterns back into ADRs
228
+
229
+ Install the plugin from [archgate/claude-code-plugin](https://github.com/archgate/claude-code-plugin), then run `archgate:onboard` once in your project to initialize governance.
230
+
231
+ ## Contributing
232
+
233
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and workflow.
234
+
235
+ ## License
236
+
237
+ [FSL-1.1-ALv2](LICENSE.md) — free to use, cannot be used to build a competing product.
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "archgate",
3
+ "version": "0.1.0",
4
+ "description": "AI governance for software development",
5
+ "readme": "README.md",
6
+ "license": "FSL-1.1-ALv2",
7
+ "homepage": "https://archgate.dev",
8
+ "exports": {
9
+ "./rules": "./src/formats/rules.ts"
10
+ },
11
+ "files": [
12
+ "src/formats/rules.ts"
13
+ ],
14
+ "author": {
15
+ "name": "Archgate",
16
+ "url": "https://archgate.dev"
17
+ },
18
+ "keywords": [
19
+ "archgate",
20
+ "cli",
21
+ "framework"
22
+ ],
23
+ "bugs": {
24
+ "url": "https://github.com/archgate/cli/issues"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/archgate/cli.git"
29
+ },
30
+ "os": [
31
+ "darwin",
32
+ "linux"
33
+ ],
34
+ "scripts": {
35
+ "cli": "bun run src/cli.ts",
36
+ "check": "bun run src/cli.ts check",
37
+ "lint": "oxlint .",
38
+ "typecheck": "tsc --build",
39
+ "format": "prettier --write .",
40
+ "format:check": "prettier --check .",
41
+ "test": "bun test --timeout 60000",
42
+ "test:watch": "bun test --watch --timeout 60000",
43
+ "validate": "bun run lint && bun run typecheck && bun run format:check && bun test && bun run check",
44
+ "commit": "cz",
45
+ "build": "bun run scripts/build.ts",
46
+ "build:darwin": "bun run scripts/build.ts --target darwin-arm64",
47
+ "build:linux": "bun run scripts/build.ts --target linux-x64",
48
+ "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
49
+ },
50
+ "type": "module",
51
+ "dependencies": {
52
+ "@commander-js/extra-typings": "14.0.0",
53
+ "@modelcontextprotocol/sdk": "1.26.0",
54
+ "inquirer": "12.9.4",
55
+ "zod": "4.3.6"
56
+ },
57
+ "devDependencies": {
58
+ "@commitlint/cli": "19.8.1",
59
+ "@commitlint/config-conventional": "19.8.1",
60
+ "@commitlint/cz-commitlint": "19.8.1",
61
+ "@simple-release/npm": "2.3.0",
62
+ "@types/bun": "1.3.9",
63
+ "commitizen": "4.3.1",
64
+ "conventional-changelog": "7.1.1",
65
+ "conventional-changelog-angular": "8.0.0",
66
+ "oxlint": "1.14.0",
67
+ "prettier": "3.6.2"
68
+ },
69
+ "peerDependencies": {
70
+ "typescript": "^5"
71
+ }
72
+ }
@@ -0,0 +1,86 @@
1
+ import { z } from "zod";
2
+
3
+ // --- Severity ---
4
+
5
+ export type Severity = "error" | "warning" | "info";
6
+
7
+ // --- Grep Match ---
8
+
9
+ export interface GrepMatch {
10
+ file: string;
11
+ line: number;
12
+ column: number;
13
+ content: string;
14
+ }
15
+
16
+ // --- Violation Detail ---
17
+
18
+ export interface ViolationDetail {
19
+ ruleId: string;
20
+ adrId: string;
21
+ message: string;
22
+ file?: string;
23
+ line?: number;
24
+ fix?: string;
25
+ severity: Severity;
26
+ }
27
+
28
+ // --- Report interface (side-effect based) ---
29
+
30
+ export interface RuleReport {
31
+ violation(
32
+ detail: Omit<ViolationDetail, "ruleId" | "adrId" | "severity">
33
+ ): void;
34
+ warning(detail: Omit<ViolationDetail, "ruleId" | "adrId" | "severity">): void;
35
+ info(detail: Omit<ViolationDetail, "ruleId" | "adrId" | "severity">): void;
36
+ }
37
+
38
+ // --- Rule Context ---
39
+
40
+ export interface RuleContext {
41
+ projectRoot: string;
42
+ scopedFiles: string[];
43
+ changedFiles: string[];
44
+ glob(pattern: string): Promise<string[]>;
45
+ grep(file: string, pattern: RegExp): Promise<GrepMatch[]>;
46
+ grepFiles(pattern: RegExp, fileGlob: string): Promise<GrepMatch[]>;
47
+ readFile(path: string): Promise<string>;
48
+ readJSON(path: string): Promise<unknown>;
49
+ report: RuleReport;
50
+ }
51
+
52
+ // --- Rule Config ---
53
+
54
+ export interface RuleConfig {
55
+ description: string;
56
+ severity?: Severity;
57
+ check: (ctx: RuleContext) => Promise<void>;
58
+ }
59
+
60
+ // --- Rule Set ---
61
+
62
+ export type RuleSet = {
63
+ rules: Record<string, RuleConfig>;
64
+ };
65
+
66
+ export const RuleSetSchema = z.object({
67
+ rules: z.record(
68
+ z.string(),
69
+ z.object({
70
+ description: z.string(),
71
+ severity: z.enum(["error", "warning", "info"]).optional(),
72
+ check: z.custom<(ctx: RuleContext) => Promise<void>>(
73
+ (val) => typeof val === "function",
74
+ "Expected a function"
75
+ ),
76
+ })
77
+ ),
78
+ });
79
+
80
+ /**
81
+ * Define rules in a .rules.ts companion file.
82
+ * Keys become rule IDs, preventing duplicates.
83
+ */
84
+ export function defineRules(rules: Record<string, RuleConfig>): RuleSet {
85
+ return { rules };
86
+ }