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 +75 -0
- package/dist/chunk-R6IMTNKV.js +389 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7490 -0
- package/dist/parser-D6PBQUJH.js +6 -0
- package/package.json +68 -0
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
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|