archondev 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/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # ArchonDev
2
+
3
+ **Local-first AI-powered development governance**
4
+
5
+ ArchonDev brings architectural governance to AI-assisted development. It ensures your AI coding assistants (Cursor, Copilot, Claude, etc.) respect codebase boundaries, follow coding standards, and never violate critical invariants.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g archondev
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # Initialize ArchonDev in your project
17
+ archon init
18
+
19
+ # Create a work item (atom) with AI-powered planning
20
+ archon plan "Add user authentication with JWT"
21
+
22
+ # Execute the plan with quality gates
23
+ archon execute ATOM-001
24
+ ```
25
+
26
+ ## How It Works
27
+
28
+ 1. **Architecture as Input** - Define your system boundaries, invariants, and protected paths in `ARCHITECTURE.md`
29
+ 2. **Adversarial Planning** - An Architect agent creates plans, a Sentinel agent critiques them
30
+ 3. **Governed Execution** - Changes are validated against your architecture before being applied
31
+ 4. **Learning Persistence** - Insights are captured in `progress.txt` for future sessions
32
+
33
+ ## Commands
34
+
35
+ | Command | Description |
36
+ |---------|-------------|
37
+ | `archon init` | Initialize ArchonDev in your project |
38
+ | `archon plan <description>` | Create a new atom with AI planning |
39
+ | `archon execute <atom-id>` | Execute a planned atom |
40
+ | `archon list` | List all atoms |
41
+ | `archon show <atom-id>` | Show atom details |
42
+ | `archon status` | Show current user and project status |
43
+ | `archon login` | Authenticate with ArchonDev |
44
+ | `archon keys add <provider>` | Add API key for BYOK tier |
45
+ | `archon bug report <title>` | Report a bug with RCA |
46
+ | `archon promote <atom-id>` | Promote atom to higher environment |
47
+
48
+ ## Tiers
49
+
50
+ | Tier | Price | Features |
51
+ |------|-------|----------|
52
+ | **Free** | $0 | 100 atoms/month, basic models (Haiku, Flash, GPT-4 Mini) |
53
+ | **BYOK** | $0 | Unlimited atoms, use your own API keys |
54
+ | **Pro** | $29/mo | Premium models (Opus, Sonnet), $50 credits included |
55
+
56
+ ## Light Packages
57
+
58
+ Don't need the full CLI? Download governance templates for your IDE:
59
+
60
+ - [Cursor Package](https://archondev.io/downloads/cursor-package.zip)
61
+ - [Windsurf Package](https://archondev.io/downloads/windsurf-package.zip)
62
+ - [VS Code + Copilot Package](https://archondev.io/downloads/vscode-copilot-package.zip)
63
+ - [Claude Code / Amp Package](https://archondev.io/downloads/claude-amp-package.zip)
64
+
65
+ ## Documentation
66
+
67
+ Full documentation at [https://archondev.io](https://archondev.io)
68
+
69
+ ## License
70
+
71
+ MIT
72
+
73
+ ---
74
+
75
+ *Powered by ArchonDev - AI Development Governance by Jumping Ahead Corp.*
@@ -0,0 +1,389 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ // src/core/parser/parser.ts
34
+ import { readFile } from "fs/promises";
35
+ import { existsSync } from "fs";
36
+ import matter from "gray-matter";
37
+ var ArchitectureParser = class {
38
+ filePath;
39
+ constructor(filePath = "ARCHITECTURE.md") {
40
+ this.filePath = filePath;
41
+ }
42
+ /**
43
+ * Parse the ARCHITECTURE.md file
44
+ */
45
+ async parse() {
46
+ const errors = [];
47
+ const warnings = [];
48
+ if (!existsSync(this.filePath)) {
49
+ return {
50
+ success: false,
51
+ errors: [
52
+ {
53
+ type: "FILE_NOT_FOUND",
54
+ message: `ARCHITECTURE.md not found at ${this.filePath}`
55
+ }
56
+ ],
57
+ warnings: []
58
+ };
59
+ }
60
+ let content;
61
+ try {
62
+ content = await readFile(this.filePath, "utf-8");
63
+ } catch (error) {
64
+ return {
65
+ success: false,
66
+ errors: [
67
+ {
68
+ type: "FILE_NOT_FOUND",
69
+ message: `Failed to read ${this.filePath}: ${error instanceof Error ? error.message : "Unknown error"}`
70
+ }
71
+ ],
72
+ warnings: []
73
+ };
74
+ }
75
+ let parsed;
76
+ try {
77
+ parsed = matter(content);
78
+ } catch (error) {
79
+ return {
80
+ success: false,
81
+ errors: [
82
+ {
83
+ type: "INVALID_YAML",
84
+ message: `Invalid YAML frontmatter: ${error instanceof Error ? error.message : "Unknown error"}`
85
+ }
86
+ ],
87
+ warnings: []
88
+ };
89
+ }
90
+ const data = parsed.data;
91
+ if (!data["version"]) {
92
+ warnings.push('Missing version field, defaulting to "1.0"');
93
+ }
94
+ const schema = {
95
+ version: this.getString(data, "version", "1.0"),
96
+ updatedAt: this.getString(data, "updatedAt", (/* @__PURE__ */ new Date()).toISOString()),
97
+ profile: this.getProfile(data),
98
+ strictMode: this.getBoolean(data, "strictMode", true),
99
+ systemGoals: this.parseSystemGoals(data, warnings),
100
+ components: this.parseComponents(data, errors, warnings),
101
+ invariants: this.parseInvariants(data, errors, warnings),
102
+ protectedPaths: this.parseProtectedPaths(data, warnings),
103
+ cautiousPaths: this.parseCautiousPaths(data, warnings),
104
+ temporaryOverrides: this.parseTemporaryOverrides(data, warnings),
105
+ environments: this.parseEnvironments(data, warnings),
106
+ rawYaml: data,
107
+ markdownBody: parsed.content
108
+ };
109
+ if (errors.length > 0) {
110
+ return {
111
+ success: false,
112
+ errors,
113
+ warnings
114
+ };
115
+ }
116
+ return {
117
+ success: true,
118
+ schema,
119
+ errors: [],
120
+ warnings
121
+ };
122
+ }
123
+ // ============================================================================
124
+ // HELPER METHODS
125
+ // ============================================================================
126
+ getString(data, key, defaultValue) {
127
+ const value = data[key];
128
+ return typeof value === "string" ? value : defaultValue;
129
+ }
130
+ getBoolean(data, key, defaultValue) {
131
+ const value = data[key];
132
+ return typeof value === "boolean" ? value : defaultValue;
133
+ }
134
+ getProfile(data) {
135
+ const value = data["profile"];
136
+ if (value === "strict" || value === "balanced" || value === "exploratory") {
137
+ return value;
138
+ }
139
+ return "strict";
140
+ }
141
+ parseSystemGoals(data, warnings) {
142
+ const goals = data["systemGoals"];
143
+ if (!Array.isArray(goals)) {
144
+ if (goals !== void 0) {
145
+ warnings.push("systemGoals should be an array");
146
+ }
147
+ return [];
148
+ }
149
+ return goals.filter((g) => typeof g === "object" && g !== null).map((g) => ({
150
+ id: this.getString(g, "id", ""),
151
+ title: this.getString(g, "title", ""),
152
+ description: this.getString(g, "description", ""),
153
+ priority: this.getPriority(g)
154
+ })).filter((g) => g.id && g.title);
155
+ }
156
+ getPriority(data) {
157
+ const value = data["priority"];
158
+ if (value === "CRITICAL" || value === "HIGH" || value === "MEDIUM" || value === "LOW") {
159
+ return value;
160
+ }
161
+ return "MEDIUM";
162
+ }
163
+ parseComponents(data, errors, warnings) {
164
+ const components = data["components"];
165
+ if (!Array.isArray(components)) {
166
+ if (components !== void 0) {
167
+ warnings.push("components should be an array");
168
+ }
169
+ return [];
170
+ }
171
+ return components.filter((c) => typeof c === "object" && c !== null).map((c) => {
172
+ const id = this.getString(c, "id", "");
173
+ const name = this.getString(c, "name", "");
174
+ const paths = this.getStringArray(c, "paths");
175
+ if (!id) {
176
+ errors.push({
177
+ type: "MISSING_REQUIRED_FIELD",
178
+ message: "Component missing required field: id",
179
+ field: "components[].id"
180
+ });
181
+ }
182
+ if (paths.length === 0) {
183
+ warnings.push(`Component ${id} has no paths defined`);
184
+ }
185
+ return {
186
+ id,
187
+ name,
188
+ description: this.getOptionalString(c, "description"),
189
+ paths,
190
+ boundary: this.getBoundary(c),
191
+ stability: this.getStability(c),
192
+ owner: this.getOptionalString(c, "owner"),
193
+ tags: this.getStringArray(c, "tags"),
194
+ dependsOn: this.parseDependencies(c),
195
+ exports: this.parseExports(c),
196
+ forbiddenImports: this.parseForbiddenImports(c)
197
+ };
198
+ }).filter((c) => c.id);
199
+ }
200
+ getStringArray(data, key) {
201
+ const value = data[key];
202
+ if (!Array.isArray(value)) return [];
203
+ return value.filter((v) => typeof v === "string");
204
+ }
205
+ getOptionalString(data, key) {
206
+ const value = data[key];
207
+ return typeof value === "string" ? value : void 0;
208
+ }
209
+ getBoundary(data) {
210
+ const value = data["boundary"];
211
+ if (value === "PUBLIC_API" || value === "INTERNAL" || value === "INFRASTRUCTURE" || value === "EXTERNAL") {
212
+ return value;
213
+ }
214
+ return "INTERNAL";
215
+ }
216
+ getStability(data) {
217
+ const value = data["stability"];
218
+ if (value === "STABLE" || value === "EVOLVING" || value === "EXPERIMENTAL" || value === "DEPRECATED") {
219
+ return value;
220
+ }
221
+ return "EVOLVING";
222
+ }
223
+ parseDependencies(data) {
224
+ const deps = data["dependsOn"];
225
+ if (!Array.isArray(deps)) return void 0;
226
+ return deps.filter((d) => typeof d === "object" && d !== null).map((d) => ({
227
+ component: this.getString(d, "component", ""),
228
+ coupling: this.getCoupling(d),
229
+ reason: this.getOptionalString(d, "reason")
230
+ })).filter((d) => d.component);
231
+ }
232
+ getCoupling(data) {
233
+ const value = data["coupling"];
234
+ if (value === "TIGHT" || value === "LOOSE" || value === "NONE") {
235
+ return value;
236
+ }
237
+ return "LOOSE";
238
+ }
239
+ parseExports(data) {
240
+ const exports = data["exports"];
241
+ if (!Array.isArray(exports)) return void 0;
242
+ return exports.filter((e) => typeof e === "object" && e !== null).map((e) => ({
243
+ symbol: this.getString(e, "symbol", ""),
244
+ type: this.getExportType(e),
245
+ path: this.getString(e, "path", "")
246
+ })).filter((e) => e.symbol && e.path);
247
+ }
248
+ getExportType(data) {
249
+ const value = data["type"];
250
+ if (value === "function" || value === "class" || value === "interface" || value === "type" || value === "const") {
251
+ return value;
252
+ }
253
+ return "function";
254
+ }
255
+ parseForbiddenImports(data) {
256
+ const imports = data["forbiddenImports"];
257
+ if (!Array.isArray(imports)) return void 0;
258
+ return imports.filter((i) => typeof i === "object" && i !== null).map((i) => ({
259
+ pattern: this.getString(i, "pattern", ""),
260
+ reason: this.getString(i, "reason", "")
261
+ })).filter((i) => i.pattern);
262
+ }
263
+ parseInvariants(data, errors, warnings) {
264
+ const invariants = data["invariants"];
265
+ if (!Array.isArray(invariants)) {
266
+ if (invariants !== void 0) {
267
+ warnings.push("invariants should be an array");
268
+ }
269
+ return [];
270
+ }
271
+ return invariants.filter((i) => typeof i === "object" && i !== null).map((i) => {
272
+ const id = this.getString(i, "id", "");
273
+ const rule = this.getString(i, "rule", "");
274
+ if (!id) {
275
+ errors.push({
276
+ type: "MISSING_REQUIRED_FIELD",
277
+ message: "Invariant missing required field: id",
278
+ field: "invariants[].id"
279
+ });
280
+ }
281
+ if (!rule) {
282
+ errors.push({
283
+ type: "MISSING_REQUIRED_FIELD",
284
+ message: `Invariant ${id} missing required field: rule`,
285
+ field: "invariants[].rule"
286
+ });
287
+ }
288
+ return {
289
+ id,
290
+ severity: this.getSeverity(i),
291
+ rule,
292
+ match: this.getOptionalString(i, "match"),
293
+ scope: this.getOptionalString(i, "scope"),
294
+ pathPattern: this.getOptionalString(i, "pathPattern"),
295
+ reason: this.getOptionalString(i, "reason"),
296
+ exception: this.getOptionalString(i, "exception")
297
+ };
298
+ }).filter((i) => i.id && i.rule);
299
+ }
300
+ getSeverity(data) {
301
+ const value = data["severity"];
302
+ if (value === "BLOCKING" || value === "REQUIRES_OVERRIDE" || value === "WARN" || value === "ADVISORY") {
303
+ return value;
304
+ }
305
+ return "WARN";
306
+ }
307
+ parseProtectedPaths(data, warnings) {
308
+ const paths = data["protectedPaths"];
309
+ if (!Array.isArray(paths)) {
310
+ if (paths !== void 0) {
311
+ warnings.push("protectedPaths should be an array");
312
+ }
313
+ return [];
314
+ }
315
+ return paths.filter((p) => typeof p === "object" && p !== null).map((p) => ({
316
+ pattern: this.getString(p, "pattern", ""),
317
+ level: this.getProtectionLevel(p),
318
+ reason: this.getString(p, "reason", ""),
319
+ approvalRequired: this.getOptionalString(p, "approvalRequired")
320
+ })).filter((p) => p.pattern);
321
+ }
322
+ getProtectionLevel(data) {
323
+ const value = data["level"];
324
+ if (value === "HARD" || value === "SOFT" || value === "ADVISORY") {
325
+ return value;
326
+ }
327
+ return "SOFT";
328
+ }
329
+ parseCautiousPaths(data, warnings) {
330
+ const paths = data["cautiousPaths"];
331
+ if (!Array.isArray(paths)) {
332
+ if (paths !== void 0) {
333
+ warnings.push("cautiousPaths should be an array");
334
+ }
335
+ return [];
336
+ }
337
+ return paths.filter((p) => typeof p === "object" && p !== null).map((p) => ({
338
+ pattern: this.getString(p, "pattern", ""),
339
+ level: "SOFT",
340
+ reason: this.getString(p, "reason", ""),
341
+ warning: this.getOptionalString(p, "warning")
342
+ })).filter((p) => p.pattern);
343
+ }
344
+ parseTemporaryOverrides(data, warnings) {
345
+ const overrides = data["temporaryOverrides"];
346
+ if (!Array.isArray(overrides)) {
347
+ if (overrides !== void 0) {
348
+ warnings.push("temporaryOverrides should be an array");
349
+ }
350
+ return [];
351
+ }
352
+ return overrides.filter((o) => typeof o === "object" && o !== null).map((o) => ({
353
+ path: this.getString(o, "path", ""),
354
+ grantedTo: this.getString(o, "grantedTo", ""),
355
+ reason: this.getString(o, "reason", ""),
356
+ expiresAt: this.getString(o, "expiresAt", "")
357
+ })).filter((o) => o.path && o.grantedTo);
358
+ }
359
+ parseEnvironments(data, warnings) {
360
+ const envs = data["environments"];
361
+ if (typeof envs !== "object" || envs === null) {
362
+ if (envs !== void 0) {
363
+ warnings.push("environments should be an object");
364
+ }
365
+ return {};
366
+ }
367
+ const envsObj = envs;
368
+ const result = {};
369
+ for (const key of ["development", "staging", "production"]) {
370
+ const env = envsObj[key];
371
+ if (typeof env === "object" && env !== null) {
372
+ const envData = env;
373
+ result[key] = {
374
+ autoApprove: this.getBoolean(envData, "autoApprove", key === "development"),
375
+ qualityGates: this.getStringArray(envData, "qualityGates"),
376
+ requiresManualPromotion: this.getBoolean(envData, "requiresManualPromotion", false)
377
+ };
378
+ }
379
+ }
380
+ return result;
381
+ }
382
+ };
383
+
384
+ export {
385
+ __require,
386
+ __commonJS,
387
+ __toESM,
388
+ ArchitectureParser
389
+ };
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node