@a-company/paradigm 1.5.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 +142 -0
- package/dist/accept-orchestration-CWZNCGZX.js +188 -0
- package/dist/agents-suggest-35LIQKDH.js +83 -0
- package/dist/aggregate-W7Q6VIM2.js +88 -0
- package/dist/auto-IU7VN55K.js +470 -0
- package/dist/beacon-B47XSTL7.js +251 -0
- package/dist/chunk-2M6OSOIG.js +1302 -0
- package/dist/chunk-4NCFWYGG.js +110 -0
- package/dist/chunk-5C4SGQKH.js +705 -0
- package/dist/chunk-5GOA7WYD.js +1095 -0
- package/dist/chunk-5JGJACDU.js +37 -0
- package/dist/chunk-6QC3YGB6.js +114 -0
- package/dist/chunk-753RICFF.js +325 -0
- package/dist/chunk-AD2LSCHB.js +1595 -0
- package/dist/chunk-CHSHON3O.js +669 -0
- package/dist/chunk-ELLR7WP6.js +3175 -0
- package/dist/chunk-ILOWBJRC.js +12 -0
- package/dist/chunk-IRKUEJVW.js +405 -0
- package/dist/chunk-MC7XC7XQ.js +533 -0
- package/dist/chunk-MO4EEYFW.js +38 -0
- package/dist/chunk-MQWH7PFI.js +13366 -0
- package/dist/chunk-N6PJAPDE.js +364 -0
- package/dist/chunk-PBHIFAL4.js +259 -0
- package/dist/chunk-PMXRGPRQ.js +305 -0
- package/dist/chunk-PW2EXJQT.js +689 -0
- package/dist/chunk-TAP5N3HH.js +245 -0
- package/dist/chunk-THFVK5AE.js +148 -0
- package/dist/chunk-UM54F7G5.js +1533 -0
- package/dist/chunk-UUZ2DMG5.js +185 -0
- package/dist/chunk-WS5KM7OL.js +780 -0
- package/dist/chunk-YDNKXH4Z.js +2316 -0
- package/dist/chunk-YO6DVTL7.js +99 -0
- package/dist/claude-SUYNN72C.js +362 -0
- package/dist/claude-cli-OF43XAO3.js +276 -0
- package/dist/claude-code-PW6SKD2M.js +126 -0
- package/dist/claude-code-teams-JLZ5IXB6.js +199 -0
- package/dist/constellation-K3CIQCHI.js +225 -0
- package/dist/cost-AEK6R7HK.js +174 -0
- package/dist/cost-KYXIQ62X.js +93 -0
- package/dist/cursor-cli-IHJMPRCW.js +269 -0
- package/dist/cursorrules-KI5QWHIX.js +84 -0
- package/dist/diff-AJJ5H6HV.js +125 -0
- package/dist/dist-7MPIRMTZ-IOQOREMZ.js +10866 -0
- package/dist/dist-NHJQVVUW.js +68 -0
- package/dist/dist-ZEMSQV74.js +20 -0
- package/dist/doctor-6Y6L6HEB.js +11 -0
- package/dist/echo-VYZW3OTT.js +248 -0
- package/dist/export-R4FJ5NOH.js +38 -0
- package/dist/history-EVO3L6SC.js +277 -0
- package/dist/hooks-MBWE4ILT.js +12 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +568 -0
- package/dist/lint-HXKTWRNO.js +316 -0
- package/dist/manual-Y3QOXWYA.js +204 -0
- package/dist/mcp.js +14745 -0
- package/dist/orchestrate-4ZH5GUQH.js +323 -0
- package/dist/probe-OYCP4JYG.js +151 -0
- package/dist/promote-Z52ZJTJU.js +181 -0
- package/dist/providers-4PGPZEWP.js +104 -0
- package/dist/remember-6VZ74B7E.js +77 -0
- package/dist/ripple-SBQOSTZD.js +215 -0
- package/dist/sentinel-LCFD56OJ.js +43 -0
- package/dist/server-F5ITNK6T.js +9846 -0
- package/dist/server-T6WIFYRQ.js +16076 -0
- package/dist/setup-DF4F3ICN.js +25 -0
- package/dist/setup-JHBPZAG7.js +296 -0
- package/dist/shift-HKIAP4ZN.js +226 -0
- package/dist/snapshot-GTVPRYZG.js +62 -0
- package/dist/spawn-BJRQA2NR.js +196 -0
- package/dist/summary-H6J6N6PJ.js +140 -0
- package/dist/switch-6EANJ7O6.js +232 -0
- package/dist/sync-BEOCW7TZ.js +11 -0
- package/dist/team-NWP2KJAB.js +32 -0
- package/dist/test-MA5TWJQV.js +934 -0
- package/dist/thread-JCJVRUQR.js +258 -0
- package/dist/triage-ETVXXFMV.js +1880 -0
- package/dist/tutorial-L5Q3ZDHK.js +666 -0
- package/dist/university-R2WDQLSI.js +40 -0
- package/dist/upgrade-5B3YGGC6.js +550 -0
- package/dist/validate-F3YHBCRZ.js +39 -0
- package/dist/validate-QEEY6KFS.js +64 -0
- package/dist/watch-4LT4O6K7.js +123 -0
- package/dist/watch-6IIWPWDN.js +111 -0
- package/dist/wisdom-LRM4FFCH.js +319 -0
- package/package.json +68 -0
- package/templates/paradigm/config.yaml +175 -0
- package/templates/paradigm/docs/commands.md +727 -0
- package/templates/paradigm/docs/decisions/000-template.md +47 -0
- package/templates/paradigm/docs/decisions/README.md +26 -0
- package/templates/paradigm/docs/error-patterns.md +215 -0
- package/templates/paradigm/docs/patterns.md +358 -0
- package/templates/paradigm/docs/queries.md +200 -0
- package/templates/paradigm/docs/troubleshooting.md +477 -0
- package/templates/paradigm/echoes.yaml +25 -0
- package/templates/paradigm/prompts/add-feature.md +152 -0
- package/templates/paradigm/prompts/add-gate.md +117 -0
- package/templates/paradigm/prompts/debug-auth.md +174 -0
- package/templates/paradigm/prompts/implement-ftux.md +722 -0
- package/templates/paradigm/prompts/implement-sandbox.md +651 -0
- package/templates/paradigm/prompts/read-docs.md +84 -0
- package/templates/paradigm/prompts/refactor.md +106 -0
- package/templates/paradigm/prompts/run-e2e-tests.md +340 -0
- package/templates/paradigm/prompts/trace-flow.md +202 -0
- package/templates/paradigm/prompts/validate-portals.md +279 -0
- package/templates/paradigm/specs/context-tracking.md +200 -0
- package/templates/paradigm/specs/context.md +461 -0
- package/templates/paradigm/specs/disciplines.md +413 -0
- package/templates/paradigm/specs/history.md +339 -0
- package/templates/paradigm/specs/logger.md +303 -0
- package/templates/paradigm/specs/navigator.md +236 -0
- package/templates/paradigm/specs/purpose.md +265 -0
- package/templates/paradigm/specs/scan.md +177 -0
- package/templates/paradigm/specs/symbols.md +451 -0
- package/templates/paradigm/specs/wisdom.md +294 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ../sentinel/dist/chunk-MLKGABMK.js
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
__export
|
|
12
|
+
};
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ../portal/core/dist/index.js
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import * as yaml from "js-yaml";
|
|
7
|
+
import { glob } from "glob";
|
|
8
|
+
var DEFAULT_DEV_SETTINGS = {
|
|
9
|
+
visualizerPort: 42195,
|
|
10
|
+
// Marathon: 42.195km
|
|
11
|
+
watcherPort: 42196,
|
|
12
|
+
// Marathon + 1
|
|
13
|
+
autoConnect: true
|
|
14
|
+
};
|
|
15
|
+
async function parseGateConfig(configPath) {
|
|
16
|
+
const absolutePath = path.resolve(configPath);
|
|
17
|
+
const rootDir = path.dirname(absolutePath);
|
|
18
|
+
if (!fs.existsSync(absolutePath)) {
|
|
19
|
+
throw new Error(`Gate config not found: ${absolutePath}`);
|
|
20
|
+
}
|
|
21
|
+
const content = fs.readFileSync(absolutePath, "utf8");
|
|
22
|
+
const config = yaml.load(content);
|
|
23
|
+
if (!config.version) {
|
|
24
|
+
throw new Error('Gate config missing required "version" field');
|
|
25
|
+
}
|
|
26
|
+
const gates = [];
|
|
27
|
+
const configAny = config;
|
|
28
|
+
const gatesSource = config.gates || configAny.portals;
|
|
29
|
+
if (gatesSource) {
|
|
30
|
+
for (const [id, gateDef] of Object.entries(gatesSource)) {
|
|
31
|
+
gates.push(normalizeGate(id, gateDef));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (config.include) {
|
|
35
|
+
for (const pattern of config.include) {
|
|
36
|
+
const fullPattern = path.join(rootDir, pattern);
|
|
37
|
+
const files = await glob(fullPattern.replace(/\\/g, "/"));
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
const additionalGates = await parseGateFile(file);
|
|
40
|
+
gates.push(...additionalGates);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const flows = [];
|
|
45
|
+
if (config.flows) {
|
|
46
|
+
for (const [id, flowDef] of Object.entries(config.flows)) {
|
|
47
|
+
flows.push(normalizeFlow(id, flowDef));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
version: config.version,
|
|
52
|
+
gates,
|
|
53
|
+
flows,
|
|
54
|
+
settings: {
|
|
55
|
+
dev: {
|
|
56
|
+
...DEFAULT_DEV_SETTINGS,
|
|
57
|
+
...config.settings?.dev
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function parseGateFile(filePath) {
|
|
63
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
64
|
+
const data = yaml.load(content);
|
|
65
|
+
if (data.id) {
|
|
66
|
+
return [normalizeGate(data.id, data)];
|
|
67
|
+
}
|
|
68
|
+
if (data.gates) {
|
|
69
|
+
const gates = [];
|
|
70
|
+
for (const [id, gateDef] of Object.entries(data.gates)) {
|
|
71
|
+
gates.push(normalizeGate(id, gateDef));
|
|
72
|
+
}
|
|
73
|
+
return gates;
|
|
74
|
+
}
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
function normalizeGate(id, def) {
|
|
78
|
+
const locks = [];
|
|
79
|
+
if (def.locks) {
|
|
80
|
+
for (const lockDef of def.locks) {
|
|
81
|
+
locks.push(normalizeLock(lockDef));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const prizes = [];
|
|
85
|
+
if (def.prizes) {
|
|
86
|
+
for (const prizeDef of def.prizes) {
|
|
87
|
+
prizes.push(normalizePrize(prizeDef));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
id,
|
|
92
|
+
description: def.description,
|
|
93
|
+
locks,
|
|
94
|
+
prizes,
|
|
95
|
+
position: def.position
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function normalizeLock(def) {
|
|
99
|
+
const lockDef = def;
|
|
100
|
+
const keys = [];
|
|
101
|
+
if (lockDef.keys) {
|
|
102
|
+
for (const keyDef of lockDef.keys) {
|
|
103
|
+
if (typeof keyDef === "string") {
|
|
104
|
+
keys.push({ expression: keyDef });
|
|
105
|
+
} else if (keyDef.expression) {
|
|
106
|
+
const k = keyDef;
|
|
107
|
+
keys.push({
|
|
108
|
+
expression: k.expression,
|
|
109
|
+
description: k.description
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
id: lockDef.id,
|
|
116
|
+
description: lockDef.description,
|
|
117
|
+
keys,
|
|
118
|
+
mode: lockDef.mode || "all"
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function normalizePrize(def) {
|
|
122
|
+
const prizeDef = def;
|
|
123
|
+
return {
|
|
124
|
+
id: prizeDef.id,
|
|
125
|
+
oneTime: prizeDef.oneTime ?? false,
|
|
126
|
+
metadata: prizeDef.metadata
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function normalizeFlow(id, def) {
|
|
130
|
+
return {
|
|
131
|
+
id,
|
|
132
|
+
description: def.description,
|
|
133
|
+
gates: def.gates || [],
|
|
134
|
+
forkable: def.forkable
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function serializeGateConfig(config) {
|
|
138
|
+
const output = {
|
|
139
|
+
version: config.version,
|
|
140
|
+
gates: {},
|
|
141
|
+
flows: {},
|
|
142
|
+
settings: {
|
|
143
|
+
dev: config.settings.dev
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
for (const gate of config.gates) {
|
|
147
|
+
const { id, ...rest } = gate;
|
|
148
|
+
output.gates[id] = rest;
|
|
149
|
+
}
|
|
150
|
+
for (const flow of config.flows) {
|
|
151
|
+
const { id, ...rest } = flow;
|
|
152
|
+
output.flows[id] = rest;
|
|
153
|
+
}
|
|
154
|
+
return yaml.dump(output, {
|
|
155
|
+
indent: 2,
|
|
156
|
+
lineWidth: -1,
|
|
157
|
+
noRefs: true,
|
|
158
|
+
sortKeys: false
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function getDefaultGateConfig() {
|
|
162
|
+
const config = {
|
|
163
|
+
version: "1.0.0",
|
|
164
|
+
gates: {
|
|
165
|
+
"example-gate": {
|
|
166
|
+
description: "An example gate to get you started",
|
|
167
|
+
locks: [
|
|
168
|
+
{
|
|
169
|
+
id: "example-lock",
|
|
170
|
+
description: "Requires user to be authenticated",
|
|
171
|
+
keys: [{ expression: "user.isAuthenticated === true" }]
|
|
172
|
+
}
|
|
173
|
+
],
|
|
174
|
+
prizes: [
|
|
175
|
+
{
|
|
176
|
+
id: "example-prize",
|
|
177
|
+
oneTime: true,
|
|
178
|
+
metadata: { event: "first_access" }
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
flows: {
|
|
184
|
+
"example-flow": {
|
|
185
|
+
description: "An example user journey",
|
|
186
|
+
gates: ["example-gate"]
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
settings: {
|
|
190
|
+
dev: {
|
|
191
|
+
visualizerPort: 42195,
|
|
192
|
+
// Marathon: 42.195km
|
|
193
|
+
watcherPort: 42196,
|
|
194
|
+
// Marathon + 1
|
|
195
|
+
autoConnect: true
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
return yaml.dump(config, {
|
|
200
|
+
indent: 2,
|
|
201
|
+
lineWidth: -1,
|
|
202
|
+
noRefs: true,
|
|
203
|
+
sortKeys: false
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
async function findGateFiles(rootDir) {
|
|
207
|
+
const absoluteRoot = path.resolve(rootDir);
|
|
208
|
+
const files = await glob("**/portal.yaml", {
|
|
209
|
+
cwd: absoluteRoot,
|
|
210
|
+
absolute: true,
|
|
211
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
212
|
+
});
|
|
213
|
+
return files;
|
|
214
|
+
}
|
|
215
|
+
function validateGateConfig(config) {
|
|
216
|
+
const issues = [];
|
|
217
|
+
if (!config.version) {
|
|
218
|
+
issues.push({
|
|
219
|
+
type: "error",
|
|
220
|
+
message: 'Missing required "version" field',
|
|
221
|
+
path: "version"
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
const gateIds = /* @__PURE__ */ new Set();
|
|
225
|
+
for (const gate of config.gates) {
|
|
226
|
+
validateGate(gate, gateIds, issues);
|
|
227
|
+
gateIds.add(gate.id);
|
|
228
|
+
}
|
|
229
|
+
for (const flow of config.flows) {
|
|
230
|
+
validateFlow(flow, gateIds, issues);
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
valid: issues.filter((i) => i.type === "error").length === 0,
|
|
234
|
+
issues
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function validateGate(gate, existingIds, issues) {
|
|
238
|
+
const path2 = `gates.${gate.id}`;
|
|
239
|
+
if (existingIds.has(gate.id)) {
|
|
240
|
+
issues.push({
|
|
241
|
+
type: "error",
|
|
242
|
+
message: `Duplicate gate ID: "${gate.id}"`,
|
|
243
|
+
path: path2
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
if (!/^[a-z][a-z0-9-]*$/.test(gate.id)) {
|
|
247
|
+
issues.push({
|
|
248
|
+
type: "warning",
|
|
249
|
+
message: `Gate ID "${gate.id}" should use kebab-case (e.g., "my-gate")`,
|
|
250
|
+
path: path2
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const lockIds = /* @__PURE__ */ new Set();
|
|
254
|
+
for (const lock of gate.locks) {
|
|
255
|
+
validateLock(lock, lockIds, `${path2}.locks`, issues);
|
|
256
|
+
lockIds.add(lock.id);
|
|
257
|
+
}
|
|
258
|
+
const prizeIds = /* @__PURE__ */ new Set();
|
|
259
|
+
for (const prize of gate.prizes) {
|
|
260
|
+
if (prizeIds.has(prize.id)) {
|
|
261
|
+
issues.push({
|
|
262
|
+
type: "error",
|
|
263
|
+
message: `Duplicate prize ID "${prize.id}" in gate "${gate.id}"`,
|
|
264
|
+
path: `${path2}.prizes`
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
prizeIds.add(prize.id);
|
|
268
|
+
if (!/^[a-z][a-z0-9-]*$/.test(prize.id)) {
|
|
269
|
+
issues.push({
|
|
270
|
+
type: "warning",
|
|
271
|
+
message: `Prize ID "${prize.id}" should use kebab-case`,
|
|
272
|
+
path: `${path2}.prizes`
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (gate.locks.length === 0) {
|
|
277
|
+
issues.push({
|
|
278
|
+
type: "warning",
|
|
279
|
+
message: `Gate "${gate.id}" has no locks - any entity can pass through`,
|
|
280
|
+
path: path2
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function validateLock(lock, existingIds, basePath, issues) {
|
|
285
|
+
const path2 = `${basePath}.${lock.id}`;
|
|
286
|
+
if (existingIds.has(lock.id)) {
|
|
287
|
+
issues.push({
|
|
288
|
+
type: "error",
|
|
289
|
+
message: `Duplicate lock ID: "${lock.id}"`,
|
|
290
|
+
path: path2
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
if (!/^[a-z][a-z0-9-]*$/.test(lock.id)) {
|
|
294
|
+
issues.push({
|
|
295
|
+
type: "warning",
|
|
296
|
+
message: `Lock ID "${lock.id}" should use kebab-case`,
|
|
297
|
+
path: path2
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
if (lock.keys.length === 0) {
|
|
301
|
+
issues.push({
|
|
302
|
+
type: "error",
|
|
303
|
+
message: `Lock "${lock.id}" has no keys - it can never be opened`,
|
|
304
|
+
path: path2
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
for (const key of lock.keys) {
|
|
308
|
+
if (!key.expression || key.expression.trim() === "") {
|
|
309
|
+
issues.push({
|
|
310
|
+
type: "error",
|
|
311
|
+
message: `Key in lock "${lock.id}" has empty expression`,
|
|
312
|
+
path: `${path2}.keys`
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
if (key.expression.includes("==") && !key.expression.includes("===")) {
|
|
316
|
+
issues.push({
|
|
317
|
+
type: "warning",
|
|
318
|
+
message: `Key expression uses "==" instead of "===" - consider using strict equality`,
|
|
319
|
+
path: `${path2}.keys`
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (lock.mode && !["all", "any"].includes(lock.mode)) {
|
|
324
|
+
issues.push({
|
|
325
|
+
type: "error",
|
|
326
|
+
message: `Invalid lock mode "${lock.mode}" - must be "all" or "any"`,
|
|
327
|
+
path: path2
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function validateFlow(flow, gateIds, issues) {
|
|
332
|
+
const path2 = `flows.${flow.id}`;
|
|
333
|
+
if (!/^[a-z][a-z0-9-]*$/.test(flow.id)) {
|
|
334
|
+
issues.push({
|
|
335
|
+
type: "warning",
|
|
336
|
+
message: `Flow ID "${flow.id}" should use kebab-case`,
|
|
337
|
+
path: path2
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
for (const gateId of flow.gates) {
|
|
341
|
+
if (!gateIds.has(gateId)) {
|
|
342
|
+
issues.push({
|
|
343
|
+
type: "error",
|
|
344
|
+
message: `Flow "${flow.id}" references unknown gate "${gateId}"`,
|
|
345
|
+
path: `${path2}.gates`
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (flow.gates.length === 0) {
|
|
350
|
+
issues.push({
|
|
351
|
+
type: "warning",
|
|
352
|
+
message: `Flow "${flow.id}" has no gates`,
|
|
353
|
+
path: path2
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
const seen = /* @__PURE__ */ new Set();
|
|
357
|
+
for (const gateId of flow.gates) {
|
|
358
|
+
if (seen.has(gateId)) {
|
|
359
|
+
issues.push({
|
|
360
|
+
type: "warning",
|
|
361
|
+
message: `Flow "${flow.id}" contains duplicate gate "${gateId}"`,
|
|
362
|
+
path: `${path2}.gates`
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
seen.add(gateId);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
function formatValidationResult(result) {
|
|
369
|
+
if (result.valid && result.issues.length === 0) {
|
|
370
|
+
return "\u2705 Configuration is valid";
|
|
371
|
+
}
|
|
372
|
+
const lines = [];
|
|
373
|
+
const errors = result.issues.filter((i) => i.type === "error");
|
|
374
|
+
const warnings = result.issues.filter((i) => i.type === "warning");
|
|
375
|
+
if (errors.length > 0) {
|
|
376
|
+
lines.push(`
|
|
377
|
+
\u274C ${errors.length} error(s):`);
|
|
378
|
+
for (const issue of errors) {
|
|
379
|
+
lines.push(` \u2022 ${issue.message}${issue.path ? ` (${issue.path})` : ""}`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (warnings.length > 0) {
|
|
383
|
+
lines.push(`
|
|
384
|
+
\u26A0\uFE0F ${warnings.length} warning(s):`);
|
|
385
|
+
for (const issue of warnings) {
|
|
386
|
+
lines.push(` \u2022 ${issue.message}${issue.path ? ` (${issue.path})` : ""}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (result.valid) {
|
|
390
|
+
lines.push("\n\u2705 Configuration is valid (with warnings)");
|
|
391
|
+
} else {
|
|
392
|
+
lines.push("\n\u274C Configuration is invalid");
|
|
393
|
+
}
|
|
394
|
+
return lines.join("\n");
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export {
|
|
398
|
+
parseGateConfig,
|
|
399
|
+
parseGateFile,
|
|
400
|
+
serializeGateConfig,
|
|
401
|
+
getDefaultGateConfig,
|
|
402
|
+
findGateFiles,
|
|
403
|
+
validateGateConfig,
|
|
404
|
+
formatValidationResult
|
|
405
|
+
};
|