@a-company/paradigm 3.9.0 → 3.11.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.
Files changed (39) hide show
  1. package/dist/{accept-orchestration-DIGPJVUR.js → accept-orchestration-Z35I5AYN.js} +5 -5
  2. package/dist/{assessment-loader-T4GPBHLB.js → assessment-loader-C5EOUM47.js} +0 -1
  3. package/dist/{chunk-Y4XZWCHK.js → chunk-24AAVLME.js} +8 -8
  4. package/dist/{chunk-4N6AYEEA.js → chunk-3TWXFFZ3.js} +1 -1
  5. package/dist/{chunk-5S5CF3ER.js → chunk-4ZO3ZOPM.js} +19 -2141
  6. package/dist/{chunk-6RNYVBSG.js → chunk-CP6IZGUN.js} +4 -4
  7. package/dist/{chunk-M2XMTJHQ.js → chunk-DS5QY37M.js} +201 -287
  8. package/dist/chunk-F6EJKLF4.js +4971 -0
  9. package/dist/chunk-MW5DMGBB.js +255 -0
  10. package/dist/{chunk-KFHK6EBI.js → chunk-OSYMVGWX.js} +59 -3
  11. package/dist/{chunk-GY5KO3YZ.js → chunk-RDPXBMHK.js} +1 -1
  12. package/dist/{chunk-ADOBV4PH.js → chunk-UVI3OH3G.js} +6 -2127
  13. package/dist/{diff-J6C5IHPV.js → diff-PZAYCIAE.js} +5 -5
  14. package/dist/{dist-OLFOTUHS.js → dist-6SX5ZKKF.js} +2 -2
  15. package/dist/{dist-OMY7U6NR.js → dist-YB7T54QE.js} +1 -2
  16. package/dist/{doctor-TQYRF7KK.js → doctor-3YQ55536.js} +1 -1
  17. package/dist/drift-FH2UY64B.js +251 -0
  18. package/dist/{flow-7JUH6D4H.js → flow-MCKPJGRJ.js} +1 -1
  19. package/dist/{habits-ZJBAL4HD.js → habits-NC2TRMRV.js} +2 -2
  20. package/dist/{hooks-DLZEYHI3.js → hooks-JXYHVGIN.js} +1 -1
  21. package/dist/index.js +77 -51
  22. package/dist/mcp.js +5502 -9984
  23. package/dist/{orchestrate-FAV64G2R.js → orchestrate-BGRFBGBH.js} +5 -5
  24. package/dist/{plugin-update-checker-TWBWUSAG.js → plugin-update-checker-S3W4BUJO.js} +0 -1
  25. package/dist/portal-check-2HI4FFD6.js +42 -0
  26. package/dist/portal-compliance-KQCTAQTJ.js +18 -0
  27. package/dist/{providers-NQ67LO2Z.js → providers-IONB4YRJ.js} +1 -1
  28. package/dist/reindex-ZM6J53UP.js +11 -0
  29. package/dist/{sentinel-KDIGZWKT.js → sentinel-BGCISNIK.js} +1 -1
  30. package/dist/{server-NN7WDAZJ.js → server-3K3TTJH3.js} +1 -1
  31. package/dist/{shift-KJWSJLWN.js → shift-6I6N6RNK.js} +36 -8
  32. package/dist/{spawn-EO7B2UM3.js → spawn-WGFJ5RQZ.js} +5 -5
  33. package/dist/{task-loader-GUX4KS6N.js → task-loader-7M2FCBX6.js} +0 -1
  34. package/dist/{team-6CCNANKE.js → team-AFOKQ7YQ.js} +6 -6
  35. package/dist/{triage-B5W6GZLT.js → triage-MKKIWBSW.js} +2 -2
  36. package/dist/workspace-VBTW7OYL.js +271 -0
  37. package/package.json +2 -1
  38. package/dist/chunk-HPC3JAUP.js +0 -42
  39. /package/dist/{chunk-CCG6KYBT.js → chunk-5N5LR2KS.js} +0 -0
@@ -0,0 +1,255 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/portal-compliance.ts
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ import * as yaml from "js-yaml";
7
+ import { execSync } from "child_process";
8
+ var SKIP_DIRECTORIES = [
9
+ "node_modules",
10
+ ".git",
11
+ "dist",
12
+ "build",
13
+ "coverage",
14
+ ".paradigm",
15
+ "vendor",
16
+ "__pycache__"
17
+ ];
18
+ function loadPortalConfig(rootDir) {
19
+ const portalPath = path.join(rootDir, "portal.yaml");
20
+ if (!fs.existsSync(portalPath)) {
21
+ return null;
22
+ }
23
+ try {
24
+ const content = fs.readFileSync(portalPath, "utf-8");
25
+ return yaml.load(content);
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+ function extractDeclaredGates(config) {
31
+ const gates = /* @__PURE__ */ new Set();
32
+ if (config.gates) {
33
+ for (const key of Object.keys(config.gates)) {
34
+ const gateName = key.startsWith("^") ? key.slice(1) : key;
35
+ gates.add(gateName);
36
+ }
37
+ }
38
+ if (config.routes) {
39
+ for (const routeConfig of Object.values(config.routes)) {
40
+ const gateList = Array.isArray(routeConfig) ? routeConfig : routeConfig.gates || [];
41
+ for (const gate of gateList) {
42
+ const gateName = gate.startsWith("^") ? gate.slice(1) : gate;
43
+ gates.add(gateName);
44
+ }
45
+ }
46
+ }
47
+ return Array.from(gates);
48
+ }
49
+ function findGateReferences(rootDir) {
50
+ const references = [];
51
+ const skipDirsArg = SKIP_DIRECTORIES.map((d) => `--exclude-dir=${d}`).join(" ");
52
+ try {
53
+ const symbolPattern = "\\^[a-zA-Z][a-zA-Z0-9_-]+";
54
+ const symbolResult = execSync(
55
+ `grep -rn ${skipDirsArg} -E "${symbolPattern}" "${rootDir}" 2>/dev/null || true`,
56
+ { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 }
57
+ );
58
+ for (const line of symbolResult.split("\n").filter(Boolean)) {
59
+ const match = line.match(/^(.+?):(\d+):(.*)$/);
60
+ if (match) {
61
+ const [, file, lineNum, context] = match;
62
+ const gateMatch = context.match(/\^([a-zA-Z][a-zA-Z0-9_-]+)/);
63
+ if (gateMatch) {
64
+ references.push({
65
+ gate: gateMatch[1],
66
+ file: path.relative(rootDir, file),
67
+ line: parseInt(lineNum, 10),
68
+ context: context.trim().slice(0, 100),
69
+ matchType: "symbol"
70
+ });
71
+ }
72
+ }
73
+ }
74
+ } catch {
75
+ }
76
+ const functionPatterns = [
77
+ { pattern: `checkGate\\s*\\(['"]([^'"]+)['"]`, type: "function" },
78
+ { pattern: `requireGate\\s*\\(['"]([^'"]+)['"]`, type: "function" },
79
+ { pattern: `gate:\\s*['"]([^'"]+)['"]`, type: "config" },
80
+ { pattern: `@Gate\\s*\\(['"]?([^'"\\)]+)['"]?\\)`, type: "function" }
81
+ ];
82
+ for (const { pattern, type } of functionPatterns) {
83
+ try {
84
+ const result = execSync(
85
+ `grep -rn ${skipDirsArg} -E "${pattern}" "${rootDir}" 2>/dev/null || true`,
86
+ { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 }
87
+ );
88
+ for (const line of result.split("\n").filter(Boolean)) {
89
+ const match = line.match(/^(.+?):(\d+):(.*)$/);
90
+ if (match) {
91
+ const [, file, lineNum, context] = match;
92
+ const gateMatch = context.match(new RegExp(pattern));
93
+ if (gateMatch && gateMatch[1]) {
94
+ const gateName = gateMatch[1].startsWith("^") ? gateMatch[1].slice(1) : gateMatch[1];
95
+ references.push({
96
+ gate: gateName,
97
+ file: path.relative(rootDir, file),
98
+ line: parseInt(lineNum, 10),
99
+ context: context.trim().slice(0, 100),
100
+ matchType: type
101
+ });
102
+ }
103
+ }
104
+ }
105
+ } catch {
106
+ }
107
+ }
108
+ return references;
109
+ }
110
+ function extractUniqueGates(references) {
111
+ return [...new Set(references.map((r) => r.gate))];
112
+ }
113
+ async function checkPortalCompliance(rootDir) {
114
+ const config = loadPortalConfig(rootDir);
115
+ if (!config) {
116
+ const references2 = findGateReferences(rootDir);
117
+ const usedGates2 = extractUniqueGates(references2);
118
+ if (usedGates2.length === 0) {
119
+ return {
120
+ status: "compliant",
121
+ declaredButUnused: [],
122
+ usedButUndeclared: [],
123
+ properlyDeclared: [],
124
+ suggestions: ["No portal.yaml found, and no gate references detected in code."],
125
+ references: []
126
+ };
127
+ }
128
+ return {
129
+ status: "violations",
130
+ declaredButUnused: [],
131
+ usedButUndeclared: usedGates2,
132
+ properlyDeclared: [],
133
+ suggestions: [
134
+ "Gate references found in code but no portal.yaml exists.",
135
+ "Create a portal.yaml file to declare these gates:",
136
+ ...usedGates2.map((g) => ` - ^${g}`),
137
+ "",
138
+ "Run: paradigm portal init"
139
+ ],
140
+ references: references2
141
+ };
142
+ }
143
+ const declaredGates = extractDeclaredGates(config);
144
+ const references = findGateReferences(rootDir);
145
+ const usedGates = extractUniqueGates(references);
146
+ const declaredSet = new Set(declaredGates);
147
+ const usedSet = new Set(usedGates);
148
+ const declaredButUnused = declaredGates.filter((g) => !usedSet.has(g));
149
+ const usedButUndeclared = usedGates.filter((g) => !declaredSet.has(g));
150
+ const properlyDeclared = declaredGates.filter((g) => usedSet.has(g));
151
+ const suggestions = [];
152
+ if (declaredButUnused.length > 0) {
153
+ suggestions.push("Gates declared but never referenced:");
154
+ for (const gate of declaredButUnused) {
155
+ suggestions.push(` - ^${gate} (consider removing from portal.yaml or implementing)`);
156
+ }
157
+ suggestions.push("");
158
+ }
159
+ if (usedButUndeclared.length > 0) {
160
+ suggestions.push("Gates used in code but not declared in portal.yaml:");
161
+ for (const gate of usedButUndeclared) {
162
+ suggestions.push(` - ^${gate} (add to portal.yaml with proper definition)`);
163
+ }
164
+ suggestions.push("");
165
+ }
166
+ let status = "compliant";
167
+ if (usedButUndeclared.length > 0) {
168
+ status = "violations";
169
+ } else if (declaredButUnused.length > 0) {
170
+ status = "warnings";
171
+ }
172
+ return {
173
+ status,
174
+ declaredButUnused,
175
+ usedButUndeclared,
176
+ properlyDeclared,
177
+ suggestions,
178
+ references
179
+ };
180
+ }
181
+ function formatComplianceReport(report) {
182
+ const lines = [];
183
+ const statusIcon = report.status === "compliant" ? "\u2713" : report.status === "warnings" ? "\u26A0" : "\u2717";
184
+ lines.push(`Portal Compliance: ${statusIcon} ${report.status.toUpperCase()}`);
185
+ lines.push("");
186
+ lines.push(`Properly Declared: ${report.properlyDeclared.length}`);
187
+ if (report.declaredButUnused.length > 0) {
188
+ lines.push(`Declared but Unused: ${report.declaredButUnused.length}`);
189
+ }
190
+ if (report.usedButUndeclared.length > 0) {
191
+ lines.push(`Used but Undeclared: ${report.usedButUndeclared.length}`);
192
+ }
193
+ lines.push("");
194
+ if (report.properlyDeclared.length > 0) {
195
+ lines.push("Gates in Use:");
196
+ for (const gate of report.properlyDeclared) {
197
+ lines.push(` \u2713 ^${gate}`);
198
+ }
199
+ lines.push("");
200
+ }
201
+ if (report.declaredButUnused.length > 0) {
202
+ lines.push("Unused Gates (declared but never referenced):");
203
+ for (const gate of report.declaredButUnused) {
204
+ lines.push(` \u26A0 ^${gate}`);
205
+ }
206
+ lines.push("");
207
+ }
208
+ if (report.usedButUndeclared.length > 0) {
209
+ lines.push("Undeclared Gates (used but not in portal.yaml):");
210
+ for (const gate of report.usedButUndeclared) {
211
+ lines.push(` \u2717 ^${gate}`);
212
+ const refs = report.references.filter((r) => r.gate === gate).slice(0, 3);
213
+ for (const ref of refs) {
214
+ lines.push(` at ${ref.file}:${ref.line}`);
215
+ }
216
+ }
217
+ lines.push("");
218
+ }
219
+ if (report.suggestions.length > 0 && report.status !== "compliant") {
220
+ lines.push("Suggestions:");
221
+ for (const suggestion of report.suggestions) {
222
+ if (suggestion) {
223
+ lines.push(` ${suggestion}`);
224
+ }
225
+ }
226
+ }
227
+ return lines.join("\n");
228
+ }
229
+ function getComplianceSummary(report) {
230
+ if (report.status === "compliant") {
231
+ return {
232
+ status: "ok",
233
+ message: `${report.properlyDeclared.length} gates properly declared`
234
+ };
235
+ }
236
+ if (report.status === "warnings") {
237
+ return {
238
+ status: "warn",
239
+ message: `${report.declaredButUnused.length} unused gates`
240
+ };
241
+ }
242
+ return {
243
+ status: "error",
244
+ message: `${report.usedButUndeclared.length} gates used but not declared`
245
+ };
246
+ }
247
+
248
+ export {
249
+ loadPortalConfig,
250
+ extractDeclaredGates,
251
+ findGateReferences,
252
+ checkPortalCompliance,
253
+ formatComplianceReport,
254
+ getComplianceSummary
255
+ };
@@ -39,10 +39,10 @@ async function doctorCommand(options = {}) {
39
39
  status: "ok",
40
40
  message: "Directory exists"
41
41
  });
42
- const configPath = path.join(paradigmDir, "config.yaml");
43
- if (fs.existsSync(configPath)) {
42
+ const configPath2 = path.join(paradigmDir, "config.yaml");
43
+ if (fs.existsSync(configPath2)) {
44
44
  try {
45
- const content = fs.readFileSync(configPath, "utf8");
45
+ const content = fs.readFileSync(configPath2, "utf8");
46
46
  parseParadigmConfig(content);
47
47
  results.push({
48
48
  name: ".paradigm/config.yaml",
@@ -217,6 +217,48 @@ async function doctorCommand(options = {}) {
217
217
  fix: "paradigm init"
218
218
  });
219
219
  }
220
+ const configPath = path.join(paradigmDir, "config.yaml");
221
+ if (fs.existsSync(configPath)) {
222
+ try {
223
+ const configContent = fs.readFileSync(configPath, "utf8");
224
+ const { parse } = await import("./dist-JOHRYQUA.js");
225
+ const config = parse(configContent);
226
+ const purposeRequired = config?.["purpose-required"];
227
+ if (purposeRequired && Array.isArray(purposeRequired)) {
228
+ const missingDirs = [];
229
+ for (const entry of purposeRequired) {
230
+ if (!entry.pattern) continue;
231
+ const { glob } = await import("glob");
232
+ const matches = await glob(entry.pattern, { cwd, nodir: false });
233
+ for (const match of matches) {
234
+ const fullPath = path.join(cwd, match);
235
+ try {
236
+ const stat = fs.statSync(fullPath);
237
+ if (stat.isDirectory() && !fs.existsSync(path.join(fullPath, ".purpose"))) {
238
+ missingDirs.push(match);
239
+ }
240
+ } catch {
241
+ }
242
+ }
243
+ }
244
+ if (missingDirs.length > 0) {
245
+ results.push({
246
+ name: "Purpose-required",
247
+ status: "warn",
248
+ message: `${missingDirs.length} director${missingDirs.length === 1 ? "y" : "ies"} missing .purpose: ${missingDirs.join(", ")}`,
249
+ fix: "Create .purpose files with paradigm_purpose_init + paradigm_purpose_add_component"
250
+ });
251
+ } else {
252
+ results.push({
253
+ name: "Purpose-required",
254
+ status: "ok",
255
+ message: "All required directories have .purpose files"
256
+ });
257
+ }
258
+ }
259
+ } catch {
260
+ }
261
+ }
220
262
  const clarificationMarkerRegex = /\[NEEDS CLARIFICATION:\s*[^\]]+\]/gi;
221
263
  let clarificationCount = 0;
222
264
  function findPurposeFilesRecursive(dir) {
@@ -292,6 +334,20 @@ async function doctorCommand(options = {}) {
292
334
  });
293
335
  }
294
336
  }
337
+ if (fs.existsSync(portalPath)) {
338
+ try {
339
+ const { checkPortalCompliance, getComplianceSummary } = await import("./portal-compliance-KQCTAQTJ.js");
340
+ const complianceReport = await checkPortalCompliance(cwd);
341
+ const summary = getComplianceSummary(complianceReport);
342
+ results.push({
343
+ name: "Portal compliance",
344
+ status: summary.status,
345
+ message: summary.message,
346
+ fix: summary.status !== "ok" ? "paradigm portal check" : void 0
347
+ });
348
+ } catch {
349
+ }
350
+ }
295
351
  const flowsPath = path.join(paradigmDir, "flows.yaml");
296
352
  if (fs.existsSync(flowsPath)) {
297
353
  try {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  SentinelStorage,
4
4
  v4_default
5
- } from "./chunk-ADOBV4PH.js";
5
+ } from "./chunk-UVI3OH3G.js";
6
6
 
7
7
  // ../sentinel/dist/chunk-VQ3SIN7S.js
8
8
  var DEFAULTS = {