@a-company/paradigm 3.34.0 → 3.44.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 (122) hide show
  1. package/dist/{accept-orchestration-XXANWJVZ.js → accept-orchestration-ZUWQUHSK.js} +6 -6
  2. package/dist/add-VSPZ6FM4.js +81 -0
  3. package/dist/{aggregate-XHQ6GI3Z.js → aggregate-SV3VGEIL.js} +2 -2
  4. package/dist/assess-UHBDYIK7.js +68 -0
  5. package/dist/{beacon-BTLQMYQL.js → beacon-3SJV4DAP.js} +2 -2
  6. package/dist/calibration-WWHK73WU.js +135 -0
  7. package/dist/{chunk-C5ZE6WEX.js → chunk-2SKXFXIT.js} +91 -1
  8. package/dist/{chunk-S5TDFT5Q.js → chunk-7COU5S2Z.js} +2 -2
  9. package/dist/{chunk-H4TVBJD4.js → chunk-AKIMFN6I.js} +3 -3
  10. package/dist/{chunk-3DYYXGDC.js → chunk-CDMAMDSG.js} +33 -0
  11. package/dist/chunk-F3BCHPYT.js +143 -0
  12. package/dist/{chunk-R2SGQ22F.js → chunk-FKJUBQU3.js} +461 -2
  13. package/dist/chunk-GT5QGC2H.js +253 -0
  14. package/dist/{chunk-UQNTJ5VB.js → chunk-HIKKOCXY.js} +1 -1
  15. package/dist/{chunk-J26YQVAK.js → chunk-J4E6K5MG.js} +1 -1
  16. package/dist/chunk-L27I3CPZ.js +357 -0
  17. package/dist/{chunk-WOONGZ3C.js → chunk-P7XSBJE3.js} +1 -1
  18. package/dist/{chunk-Z7W7HNRG.js → chunk-QDXI2DHR.js} +1 -1
  19. package/dist/{chunk-BRILIG7Z.js → chunk-QIOCFXDQ.js} +42 -0
  20. package/dist/{chunk-3BGSDKWD.js → chunk-QWA26UNO.js} +7 -7
  21. package/dist/{lore-server-ILPHKWLK.js → chunk-RAB5IKPR.js} +77 -112
  22. package/dist/chunk-SOBTKFSP.js +616 -0
  23. package/dist/{chunk-BKMNLROM.js → chunk-ZDHLG5VP.js} +461 -147
  24. package/dist/{chunk-CTF6RHKG.js → chunk-ZGUAAVMA.js} +17 -2
  25. package/dist/{chunk-PFLWLC6J.js → chunk-ZMQA6SCO.js} +855 -34
  26. package/dist/{chunk-3BAMPB6I.js → chunk-ZSYVKSY6.js} +2 -147
  27. package/dist/{commands-KPT2T2OZ.js → commands-5N4ILTPH.js} +465 -1
  28. package/dist/config-schema-3YNIFJCJ.js +152 -0
  29. package/dist/{constellation-LZ6XIKDT.js → constellation-FAGT45TU.js} +2 -2
  30. package/dist/{context-audit-RI4R2WRH.js → context-audit-557EO6PK.js} +138 -8
  31. package/dist/{cost-4SZM7OUS.js → cost-UD3WPEKZ.js} +1 -1
  32. package/dist/{delete-YTASL4SM.js → delete-RRK4RL6Y.js} +1 -1
  33. package/dist/{diff-T6YJSAAC.js → diff-IP5CIARP.js} +6 -6
  34. package/dist/{dist-AG5JNIZU-HW2FWNTZ.js → dist-5QE2BB2B-X6DYVSUL.js} +59 -5
  35. package/dist/{dist-IKBGY7FQ.js → dist-CM3MVWWW.js} +3 -1
  36. package/dist/{dist-OH4DBV2O.js → dist-OGTSAZ55.js} +16 -1
  37. package/dist/{dist-RMAIFRTW.js → dist-POMVY6WP.js} +5 -3
  38. package/dist/{dist-QSBAGCZT.js → dist-UXWV4OKX.js} +2 -2
  39. package/dist/{doctor-INBOLZC7.js → doctor-GKZJU7QG.js} +1 -1
  40. package/dist/{edit-S7NZD7H7.js → edit-4CLNN5JG.js} +1 -1
  41. package/dist/{graph-ERNQQQ7C.js → graph-YYUXI3F7.js} +1 -1
  42. package/dist/graph-server-ZPXRSGCW.js +116 -0
  43. package/dist/{habits-7BORPC2F.js → habits-RG5SVKXP.js} +2 -2
  44. package/dist/index.js +200 -86
  45. package/dist/integrity-MK2OP5TA.js +194 -0
  46. package/dist/integrity-checker-J7YXRTBT.js +11 -0
  47. package/dist/{lint-MTRZB5EC.js → lint-HYWGS3JJ.js} +1 -1
  48. package/dist/{list-QTFWN35D.js → list-BTLFHSRC.js} +1 -1
  49. package/dist/list-IUCYPGMK.js +57 -0
  50. package/dist/{lore-loader-S5BXMH27.js → lore-loader-VTEEZDX3.js} +3 -1
  51. package/dist/lore-server-NOOAHKJX.js +118 -0
  52. package/dist/mcp.js +2591 -112
  53. package/dist/{migrate-HRN5TUBQ.js → migrate-FQVGQNXZ.js} +21 -3
  54. package/dist/{migrate-assessments-FPR6C35Z.js → migrate-assessments-JP6Q5KME.js} +1 -1
  55. package/dist/{orchestrate-3SI6ON33.js → orchestrate-A226N6FC.js} +6 -6
  56. package/dist/platform-server-KHL6ZPPN.js +900 -0
  57. package/dist/{probe-ABMGCXQG.js → probe-7JK7IDNI.js} +4 -4
  58. package/dist/{providers-YW3FG6DA.js → providers-YNFSL6HK.js} +1 -1
  59. package/dist/quiz-I75NU2QQ.js +99 -0
  60. package/dist/{record-UGN75GTB.js → record-46CLR4OG.js} +11 -2
  61. package/dist/{reindex-YC7LD4MN.js → reindex-WIJMCJ4A.js} +3 -2
  62. package/dist/{remember-WR6ZVXLT.js → remember-4EUZKIIB.js} +1 -1
  63. package/dist/{retag-URLJLMSK.js → retag-KC4JVRLE.js} +1 -1
  64. package/dist/{review-725ZKA7U.js → review-Q7M4CRB5.js} +1 -1
  65. package/dist/{ripple-QTXKJCEI.js → ripple-RI3LOT6R.js} +2 -2
  66. package/dist/{sentinel-FUR3QKCJ.js → sentinel-UOIGJWHH.js} +1 -1
  67. package/dist/sentinel-bridge-APDXYAZS.js +109 -0
  68. package/dist/sentinel-mcp.js +13 -0
  69. package/dist/sentinel-ui/assets/{index-Zh1YM0C9.css → index-CJ1Wx083.css} +1 -1
  70. package/dist/sentinel-ui/assets/index-S1VJ67dT.js +62 -0
  71. package/dist/sentinel-ui/assets/index-S1VJ67dT.js.map +1 -0
  72. package/dist/sentinel-ui/index.html +2 -2
  73. package/dist/sentinel.js +6 -6
  74. package/dist/{serve-DIALBCTU.js → serve-22A4XOIG.js} +1 -1
  75. package/dist/{university-A66BMZ4Z.js → serve-2YJ6D2Y6.js} +9 -8
  76. package/dist/serve-JVXSRSUB.js +33 -0
  77. package/dist/{server-2VICPDUR.js → server-JV6UFGWZ.js} +25 -2
  78. package/dist/{server-OWBK2WFS.js → server-RDLQ3DK7.js} +49 -4
  79. package/dist/{setup-ASR6OMKV.js → setup-M2ZKLKNN.js} +2 -2
  80. package/dist/{shift-7XLSBLDW.js → shift-LNMKFYLR.js} +63 -14
  81. package/dist/{show-GEVVQWWG.js → show-P7GYO43X.js} +1 -1
  82. package/dist/show-PKZMYKRN.js +82 -0
  83. package/dist/{snapshot-QZFD7YBI.js → snapshot-Y3COXK4T.js} +2 -2
  84. package/dist/{spawn-DIY7T4QW.js → spawn-SSXZX45U.js} +2 -2
  85. package/dist/status-KLHALGW4.js +71 -0
  86. package/dist/{summary-R4CSYNNP.js → summary-5NQNOD3F.js} +2 -2
  87. package/dist/{sweep-5POCF2E4.js → sweep-EZU3GU6S.js} +1 -1
  88. package/dist/symphony-EYRGGVNE.js +470 -0
  89. package/dist/symphony-QWOEKZMC.js +308 -0
  90. package/dist/{team-VH3HYABB.js → team-HGLJXWQG.js} +7 -7
  91. package/dist/{timeline-RKXNRMKF.js → timeline-ANC7LVDL.js} +1 -1
  92. package/dist/{triage-GJ6GK647.js → triage-IZ4MDYNB.js} +2 -2
  93. package/dist/university-content/courses/.purpose +7 -1
  94. package/dist/university-content/courses/para-501.json +166 -0
  95. package/dist/university-content/plsat/.purpose +6 -0
  96. package/dist/university-content/plsat/v3.0.json +323 -1
  97. package/dist/university-content/reference.json +48 -0
  98. package/dist/university-ui/assets/{index-TcsCEBMo.js → index-tfi5xN4Q.js} +2 -2
  99. package/dist/university-ui/assets/{index-TcsCEBMo.js.map → index-tfi5xN4Q.js.map} +1 -1
  100. package/dist/university-ui/index.html +1 -1
  101. package/dist/validate-GD5XWILV.js +134 -0
  102. package/dist/{validate-OUHUBZPO.js → validate-ZVPNN4FL.js} +1 -1
  103. package/dist/{workspace-5RBSALXC.js → workspace-UIUTHZTD.js} +5 -5
  104. package/package.json +4 -2
  105. package/platform-ui/dist/assets/GitSection-BD3Ze06e.js +4 -0
  106. package/platform-ui/dist/assets/GitSection-C-GQWHcu.css +1 -0
  107. package/platform-ui/dist/assets/GraphSection-BlgXTl53.css +1 -0
  108. package/platform-ui/dist/assets/GraphSection-SglITfSs.js +8 -0
  109. package/platform-ui/dist/assets/LoreSection-C3EixkjW.css +1 -0
  110. package/platform-ui/dist/assets/LoreSection-bR5Km4Fd.js +1 -0
  111. package/platform-ui/dist/assets/SentinelSection-BI-aIYKL.css +1 -0
  112. package/platform-ui/dist/assets/SentinelSection-QSpAZArG.js +1 -0
  113. package/platform-ui/dist/assets/SymphonySection-CobYJgvg.js +1 -0
  114. package/platform-ui/dist/assets/SymphonySection-zY0C5tFl.css +1 -0
  115. package/platform-ui/dist/assets/index-CfpZFjea.css +1 -0
  116. package/platform-ui/dist/assets/index-DbxeSMkV.js +57 -0
  117. package/platform-ui/dist/index.html +14 -0
  118. package/dist/graph-server-BZ73HTAT.js +0 -251
  119. package/dist/sentinel-ui/assets/index-C_Wstm64.js +0 -62
  120. package/dist/sentinel-ui/assets/index-C_Wstm64.js.map +0 -1
  121. /package/dist/{chunk-VUSCJJ4A.js → chunk-EDOAWN7J.js} +0 -0
  122. /package/dist/{chunk-5SXMV4SP.js → chunk-FS3WTUHY.js} +0 -0
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/university/storage.ts
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ import * as yaml from "js-yaml";
7
+ var UNIVERSITY_DIR = ".paradigm/university";
8
+ var CONTENT_DIR = "content";
9
+ function parseFrontmatter(content) {
10
+ const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
11
+ if (!match) return null;
12
+ try {
13
+ const frontmatter = yaml.load(match[1]);
14
+ return { frontmatter, body: match[2].trim() };
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+ function serializeFrontmatter(frontmatter, body) {
20
+ const fm = yaml.dump(frontmatter, { lineWidth: -1, noRefs: true, sortKeys: false });
21
+ return `---
22
+ ${fm}---
23
+
24
+ ${body}
25
+ `;
26
+ }
27
+ function loadUniversityIndex(rootDir) {
28
+ const indexPath = path.join(rootDir, UNIVERSITY_DIR, "index.yaml");
29
+ if (!fs.existsSync(indexPath)) return null;
30
+ try {
31
+ return yaml.load(fs.readFileSync(indexPath, "utf8"));
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+ function resolveFile(rootDir, id, ext) {
37
+ const base = path.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR);
38
+ for (const subdir of ["notes", "policies", "quizzes", "paths"]) {
39
+ const fp = path.join(base, subdir, `${id}${ext}`);
40
+ if (fs.existsSync(fp)) return fp;
41
+ }
42
+ return null;
43
+ }
44
+ function loadNote(rootDir, id) {
45
+ const fp = resolveFile(rootDir, id, ".md");
46
+ if (!fp) return null;
47
+ try {
48
+ const parsed = parseFrontmatter(fs.readFileSync(fp, "utf8"));
49
+ if (!parsed) return null;
50
+ const fm = parsed.frontmatter;
51
+ return {
52
+ frontmatter: {
53
+ ...fm,
54
+ tags: fm.tags || [],
55
+ symbols: fm.symbols || [],
56
+ prerequisites: fm.prerequisites || []
57
+ },
58
+ body: parsed.body
59
+ };
60
+ } catch {
61
+ return null;
62
+ }
63
+ }
64
+ function loadQuiz(rootDir, id) {
65
+ const fp = resolveFile(rootDir, id, ".yaml");
66
+ if (!fp) return null;
67
+ try {
68
+ const data = yaml.load(fs.readFileSync(fp, "utf8"));
69
+ if (!data?.id) return null;
70
+ return { ...data, tags: data.tags || [], symbols: data.symbols || [], questions: data.questions || [] };
71
+ } catch {
72
+ return null;
73
+ }
74
+ }
75
+ function loadPath(rootDir, id) {
76
+ const fp = resolveFile(rootDir, id, ".yaml");
77
+ if (!fp) return null;
78
+ try {
79
+ const data = yaml.load(fs.readFileSync(fp, "utf8"));
80
+ if (!data?.id) return null;
81
+ return data;
82
+ } catch {
83
+ return null;
84
+ }
85
+ }
86
+ function loadDiplomas(rootDir, filter) {
87
+ const dir = path.join(rootDir, UNIVERSITY_DIR, "diplomas");
88
+ if (!fs.existsSync(dir)) return [];
89
+ const results = [];
90
+ try {
91
+ for (const file of fs.readdirSync(dir).filter((f) => f.endsWith(".yaml"))) {
92
+ try {
93
+ const d = yaml.load(fs.readFileSync(path.join(dir, file), "utf8"));
94
+ if (!d?.id) continue;
95
+ if (filter?.student && d.student !== filter.student) continue;
96
+ if (filter?.type && d.type !== filter.type) continue;
97
+ results.push(d);
98
+ } catch {
99
+ }
100
+ }
101
+ } catch {
102
+ }
103
+ return results.sort((a, b) => b.earnedAt.localeCompare(a.earnedAt));
104
+ }
105
+ function saveNote(rootDir, frontmatter, body) {
106
+ const subdir = frontmatter.type === "policy" ? "policies" : "notes";
107
+ const dir = path.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR, subdir);
108
+ fs.mkdirSync(dir, { recursive: true });
109
+ const fp = path.join(dir, `${frontmatter.id}.md`);
110
+ fs.writeFileSync(fp, serializeFrontmatter(frontmatter, body), "utf8");
111
+ return fp;
112
+ }
113
+ function saveQuiz(rootDir, quiz) {
114
+ const dir = path.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR, "quizzes");
115
+ fs.mkdirSync(dir, { recursive: true });
116
+ const fp = path.join(dir, `${quiz.id}.yaml`);
117
+ fs.writeFileSync(fp, yaml.dump(quiz, { lineWidth: -1, noRefs: true }), "utf8");
118
+ return fp;
119
+ }
120
+ function saveDiploma(rootDir, diploma) {
121
+ const dir = path.join(rootDir, UNIVERSITY_DIR, "diplomas");
122
+ fs.mkdirSync(dir, { recursive: true });
123
+ const fp = path.join(dir, `${diploma.id}.yaml`);
124
+ fs.writeFileSync(fp, yaml.dump(diploma, { lineWidth: -1, noRefs: true }), "utf8");
125
+ return fp;
126
+ }
127
+ function rebuildUniversityIndex(rootDir) {
128
+ const uniDir = path.join(rootDir, UNIVERSITY_DIR);
129
+ const contentBase = path.join(uniDir, CONTENT_DIR);
130
+ const entries = [];
131
+ for (const subdir of ["notes", "policies"]) {
132
+ const dir = path.join(contentBase, subdir);
133
+ if (!fs.existsSync(dir)) continue;
134
+ try {
135
+ for (const file of fs.readdirSync(dir).filter((f) => f.endsWith(".md"))) {
136
+ try {
137
+ const raw = fs.readFileSync(path.join(dir, file), "utf8");
138
+ const parsed = parseFrontmatter(raw);
139
+ if (!parsed) continue;
140
+ const fm = parsed.frontmatter;
141
+ entries.push({
142
+ id: fm.id || file.replace(".md", ""),
143
+ title: fm.title || file,
144
+ type: fm.type || (subdir === "policies" ? "policy" : "note"),
145
+ author: fm.author || "unknown",
146
+ created: fm.created || "",
147
+ updated: fm.updated || "",
148
+ tags: Array.isArray(fm.tags) ? fm.tags : [],
149
+ symbols: Array.isArray(fm.symbols) ? fm.symbols : [],
150
+ difficulty: fm.difficulty || "beginner",
151
+ file: `${CONTENT_DIR}/${subdir}/${file}`
152
+ });
153
+ } catch {
154
+ }
155
+ }
156
+ } catch {
157
+ }
158
+ }
159
+ const quizDir = path.join(contentBase, "quizzes");
160
+ if (fs.existsSync(quizDir)) {
161
+ try {
162
+ for (const file of fs.readdirSync(quizDir).filter((f) => f.endsWith(".yaml"))) {
163
+ try {
164
+ const data = yaml.load(fs.readFileSync(path.join(quizDir, file), "utf8"));
165
+ if (!data?.id) continue;
166
+ entries.push({
167
+ id: data.id,
168
+ title: data.title || file,
169
+ type: "quiz",
170
+ author: data.author || "unknown",
171
+ created: data.created || "",
172
+ updated: data.updated || "",
173
+ tags: data.tags || [],
174
+ symbols: data.symbols || [],
175
+ difficulty: data.difficulty || "beginner",
176
+ file: `${CONTENT_DIR}/quizzes/${file}`
177
+ });
178
+ } catch {
179
+ }
180
+ }
181
+ } catch {
182
+ }
183
+ }
184
+ const pathDir = path.join(contentBase, "paths");
185
+ if (fs.existsSync(pathDir)) {
186
+ try {
187
+ for (const file of fs.readdirSync(pathDir).filter((f) => f.endsWith(".yaml"))) {
188
+ try {
189
+ const data = yaml.load(fs.readFileSync(path.join(pathDir, file), "utf8"));
190
+ if (!data?.id) continue;
191
+ entries.push({
192
+ id: data.id,
193
+ title: data.title || file,
194
+ type: "path",
195
+ author: data.author || "unknown",
196
+ created: data.created || "",
197
+ updated: data.updated || "",
198
+ tags: data.tags || [],
199
+ symbols: [],
200
+ file: `${CONTENT_DIR}/paths/${file}`
201
+ });
202
+ } catch {
203
+ }
204
+ }
205
+ } catch {
206
+ }
207
+ }
208
+ let diplomaCount = 0;
209
+ const diplomaDir = path.join(uniDir, "diplomas");
210
+ if (fs.existsSync(diplomaDir)) {
211
+ try {
212
+ diplomaCount = fs.readdirSync(diplomaDir).filter((f) => f.endsWith(".yaml")).length;
213
+ } catch {
214
+ }
215
+ }
216
+ const index = {
217
+ version: "1.0",
218
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
219
+ totalContent: entries.length,
220
+ entries,
221
+ diplomaCount
222
+ };
223
+ fs.mkdirSync(uniDir, { recursive: true });
224
+ fs.writeFileSync(path.join(uniDir, "index.yaml"), yaml.dump(index, { lineWidth: -1, noRefs: true }), "utf8");
225
+ return index;
226
+ }
227
+ function searchContent(rootDir, filter) {
228
+ const index = loadUniversityIndex(rootDir);
229
+ if (!index) return [];
230
+ let results = [...index.entries];
231
+ if (filter.type) results = results.filter((e) => e.type === filter.type);
232
+ if (filter.tag) results = results.filter((e) => e.tags.some((t) => t.startsWith(filter.tag)));
233
+ if (filter.difficulty) results = results.filter((e) => e.difficulty === filter.difficulty);
234
+ if (filter.symbol) results = results.filter((e) => e.symbols.includes(filter.symbol));
235
+ if (filter.query) {
236
+ const q = filter.query.toLowerCase();
237
+ results = results.filter((e) => e.title.toLowerCase().includes(q) || e.id.toLowerCase().includes(q));
238
+ }
239
+ return results.slice(0, filter.limit || 20);
240
+ }
241
+
242
+ export {
243
+ loadUniversityIndex,
244
+ loadNote,
245
+ loadQuiz,
246
+ loadPath,
247
+ loadDiplomas,
248
+ saveNote,
249
+ saveQuiz,
250
+ saveDiploma,
251
+ rebuildUniversityIndex,
252
+ searchContent
253
+ };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  BackgroundOrchestrator
4
- } from "./chunk-3BGSDKWD.js";
4
+ } from "./chunk-QWA26UNO.js";
5
5
  import {
6
6
  AGENT_MODEL_RECOMMENDATIONS,
7
7
  addActivity,
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  getProvider,
7
7
  initializeProviders
8
- } from "./chunk-5SXMV4SP.js";
8
+ } from "./chunk-FS3WTUHY.js";
9
9
  import {
10
10
  loadAgentsManifest
11
11
  } from "./chunk-PMXRGPRQ.js";
@@ -0,0 +1,357 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ../paradigm-mcp/src/utils/integrity-checker.ts
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ function checkIntegrity(aggregation, rootDir) {
7
+ const symbols = aggregation.symbols;
8
+ return {
9
+ brokenReferences: findBrokenReferences(symbols),
10
+ duplicateSymbols: findDuplicateSymbols(symbols),
11
+ orphanedSymbols: findOrphanedSymbols(symbols),
12
+ missingAnchorFiles: findMissingAnchors(symbols, rootDir),
13
+ anchorOutOfBounds: findAnchorOutOfBounds(symbols, rootDir),
14
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
15
+ };
16
+ }
17
+ function findBrokenReferences(symbols) {
18
+ const broken = [];
19
+ const definedIds = new Set(symbols.map((s) => s.symbol));
20
+ for (const sym of symbols) {
21
+ if (sym.parentSymbol) {
22
+ const parentRef = normalizeSymbolRef(sym.parentSymbol);
23
+ if (parentRef && !definedIds.has(parentRef)) {
24
+ broken.push({
25
+ from: sym.symbol,
26
+ to: parentRef,
27
+ file: sym.filePath,
28
+ refType: "parent"
29
+ });
30
+ }
31
+ }
32
+ const data = sym.data;
33
+ if (data && typeof data === "object") {
34
+ if (sym.type === "flow") {
35
+ const steps = data.steps || [];
36
+ for (const step of steps) {
37
+ const ref = step.symbol || step.component;
38
+ if (ref) {
39
+ const normalized = normalizeSymbolRef(ref);
40
+ if (normalized && !definedIds.has(normalized)) {
41
+ broken.push({
42
+ from: sym.symbol,
43
+ to: normalized,
44
+ file: sym.filePath,
45
+ refType: "flow"
46
+ });
47
+ }
48
+ }
49
+ }
50
+ const gates = data.gates || [];
51
+ for (const gate of gates) {
52
+ const normalized = normalizeSymbolRef(gate);
53
+ if (normalized && !definedIds.has(normalized)) {
54
+ broken.push({
55
+ from: sym.symbol,
56
+ to: normalized,
57
+ file: sym.filePath,
58
+ refType: "gate"
59
+ });
60
+ }
61
+ }
62
+ const signals = data.signals || [];
63
+ for (const signal of signals) {
64
+ const normalized = normalizeSymbolRef(signal);
65
+ if (normalized && !definedIds.has(normalized)) {
66
+ broken.push({
67
+ from: sym.symbol,
68
+ to: normalized,
69
+ file: sym.filePath,
70
+ refType: "signal"
71
+ });
72
+ }
73
+ }
74
+ const components = data.components || [];
75
+ for (const comp of components) {
76
+ const normalized = normalizeSymbolRef(comp);
77
+ if (normalized && !definedIds.has(normalized)) {
78
+ broken.push({
79
+ from: sym.symbol,
80
+ to: normalized,
81
+ file: sym.filePath,
82
+ refType: "component"
83
+ });
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ const seen = /* @__PURE__ */ new Set();
90
+ return broken.filter((b) => {
91
+ const key = `${b.from}->${b.to}@${b.file}`;
92
+ if (seen.has(key)) return false;
93
+ seen.add(key);
94
+ return true;
95
+ });
96
+ }
97
+ function normalizeSymbolRef(ref) {
98
+ if (!ref || typeof ref !== "string") return null;
99
+ const trimmed = ref.trim();
100
+ if (!trimmed) return null;
101
+ if (/^[#$^!~@%?&]/.test(trimmed)) {
102
+ return trimmed;
103
+ }
104
+ return `#${trimmed}`;
105
+ }
106
+ function findDuplicateSymbols(symbols) {
107
+ const bySymbol = /* @__PURE__ */ new Map();
108
+ for (const sym of symbols) {
109
+ const entries = bySymbol.get(sym.symbol) || [];
110
+ const existing = entries.find((e) => e.file === sym.filePath);
111
+ if (!existing) {
112
+ entries.push({ file: sym.filePath, source: sym.source });
113
+ }
114
+ bySymbol.set(sym.symbol, entries);
115
+ }
116
+ const duplicates = [];
117
+ for (const [symbol, entries] of bySymbol) {
118
+ if (entries.length <= 1) continue;
119
+ if (entries.length === 2) {
120
+ const sources = entries.map((e) => e.source).sort();
121
+ if (sources[0] === "portal" && sources[1] === "purpose") continue;
122
+ }
123
+ duplicates.push({ symbol, files: entries.map((e) => e.file) });
124
+ }
125
+ return duplicates;
126
+ }
127
+ function findOrphanedSymbols(symbols) {
128
+ const orphaned = [];
129
+ for (const sym of symbols) {
130
+ if (sym.referencedBy.length === 0 && sym.references.length === 0) {
131
+ orphaned.push({
132
+ symbol: sym.symbol,
133
+ file: sym.filePath,
134
+ referenceCount: 0
135
+ });
136
+ }
137
+ }
138
+ return orphaned;
139
+ }
140
+ function findMissingAnchors(symbols, rootDir) {
141
+ const missing = [];
142
+ for (const sym of symbols) {
143
+ if (!sym.anchors || sym.anchors.length === 0) continue;
144
+ for (const anchor of sym.anchors) {
145
+ const filePath = resolveAnchorPath(anchor.path, rootDir, sym.filePath);
146
+ if (!fs.existsSync(filePath)) {
147
+ missing.push({
148
+ symbol: sym.symbol,
149
+ anchor: anchor.raw
150
+ });
151
+ }
152
+ }
153
+ }
154
+ return missing;
155
+ }
156
+ function findAnchorOutOfBounds(symbols, rootDir) {
157
+ const outOfBounds = [];
158
+ for (const sym of symbols) {
159
+ if (!sym.anchors || sym.anchors.length === 0) continue;
160
+ for (const anchor of sym.anchors) {
161
+ const filePath = resolveAnchorPath(anchor.path, rootDir, sym.filePath);
162
+ if (!fs.existsSync(filePath)) continue;
163
+ const maxLine = getMaxLine(anchor);
164
+ if (maxLine <= 0) continue;
165
+ try {
166
+ const content = fs.readFileSync(filePath, "utf8");
167
+ const lineCount = content.split("\n").length;
168
+ if (maxLine > lineCount) {
169
+ outOfBounds.push({
170
+ symbol: sym.symbol,
171
+ anchor: anchor.raw,
172
+ fileLines: lineCount
173
+ });
174
+ }
175
+ } catch {
176
+ }
177
+ }
178
+ }
179
+ return outOfBounds;
180
+ }
181
+ function checkComponentAnchors(symbols, rootDir) {
182
+ const report = {
183
+ valid: 0,
184
+ missing: 0,
185
+ outOfBounds: 0,
186
+ issues: []
187
+ };
188
+ for (const sym of symbols) {
189
+ if (!sym.anchors || sym.anchors.length === 0) continue;
190
+ for (const anchor of sym.anchors) {
191
+ const filePath = resolveAnchorPath(anchor.path, rootDir, sym.filePath);
192
+ if (!fs.existsSync(filePath)) {
193
+ report.missing++;
194
+ report.issues.push({
195
+ symbol: sym.symbol,
196
+ anchor: anchor.raw,
197
+ status: "missing"
198
+ });
199
+ continue;
200
+ }
201
+ const maxLine = getMaxLine(anchor);
202
+ if (maxLine > 0) {
203
+ try {
204
+ const content = fs.readFileSync(filePath, "utf8");
205
+ const lineCount = content.split("\n").length;
206
+ if (maxLine > lineCount) {
207
+ report.outOfBounds++;
208
+ report.issues.push({
209
+ symbol: sym.symbol,
210
+ anchor: anchor.raw,
211
+ status: "out-of-bounds"
212
+ });
213
+ continue;
214
+ }
215
+ } catch {
216
+ report.missing++;
217
+ report.issues.push({
218
+ symbol: sym.symbol,
219
+ anchor: anchor.raw,
220
+ status: "missing"
221
+ });
222
+ continue;
223
+ }
224
+ }
225
+ report.valid++;
226
+ report.issues.push({
227
+ symbol: sym.symbol,
228
+ anchor: anchor.raw,
229
+ status: "ok"
230
+ });
231
+ }
232
+ }
233
+ return report;
234
+ }
235
+ var SKIP_DIRS = /* @__PURE__ */ new Set([
236
+ "node_modules",
237
+ "dist",
238
+ ".git",
239
+ ".paradigm",
240
+ "coverage",
241
+ "build",
242
+ "__pycache__",
243
+ "target",
244
+ ".next",
245
+ ".nuxt"
246
+ ]);
247
+ var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
248
+ ".ts",
249
+ ".js",
250
+ ".tsx",
251
+ ".jsx",
252
+ ".py",
253
+ ".rs",
254
+ ".go",
255
+ ".swift"
256
+ ]);
257
+ function checkPurposeHealth(purposeFiles, rootDir) {
258
+ const oversized = [];
259
+ const stale = [];
260
+ for (const filePath of purposeFiles) {
261
+ const absPath = path.isAbsolute(filePath) ? filePath : path.join(rootDir, filePath);
262
+ if (!fs.existsSync(absPath)) continue;
263
+ let content;
264
+ try {
265
+ content = fs.readFileSync(absPath, "utf8");
266
+ } catch {
267
+ continue;
268
+ }
269
+ const lines = content.split("\n").length;
270
+ const symbolMatches = content.match(/^ [A-Za-z][A-Za-z0-9_-]*:/gm) || [];
271
+ const symbolCount = symbolMatches.length;
272
+ if (lines > 500) {
273
+ const severity = lines > 1e3 ? "strongly recommend" : "consider";
274
+ let suggestion;
275
+ if (symbolCount >= 10) {
276
+ suggestion = `${severity} splitting: ${symbolCount} top-level symbols across ${lines} lines. Split by component type or subdirectory.`;
277
+ } else {
278
+ suggestion = `${severity} splitting: ${lines} lines. Reduce descriptions or extract sub-components.`;
279
+ }
280
+ oversized.push({
281
+ file: path.relative(rootDir, absPath),
282
+ lines,
283
+ symbolCount,
284
+ suggestion
285
+ });
286
+ }
287
+ try {
288
+ const purposeStat = fs.statSync(absPath);
289
+ const purposeDir = path.dirname(absPath);
290
+ const newestSource = findNewestSourceFile(purposeDir, rootDir);
291
+ if (newestSource) {
292
+ const sourceStat = fs.statSync(newestSource.path);
293
+ const daysDiff = Math.floor(
294
+ (sourceStat.mtime.getTime() - purposeStat.mtime.getTime()) / (1e3 * 60 * 60 * 24)
295
+ );
296
+ if (daysDiff >= 7) {
297
+ stale.push({
298
+ file: path.relative(rootDir, absPath),
299
+ lastModified: purposeStat.mtime.toISOString(),
300
+ daysSinceUpdate: daysDiff,
301
+ newestSourceFile: path.relative(rootDir, newestSource.path)
302
+ });
303
+ }
304
+ }
305
+ } catch {
306
+ }
307
+ }
308
+ const score = Math.max(0, 100 - oversized.length * 10 - stale.length * 5);
309
+ return { oversized, stale, healthScore: score };
310
+ }
311
+ function resolveAnchorPath(anchorPath, rootDir, purposeFilePath) {
312
+ if (path.isAbsolute(anchorPath)) return anchorPath;
313
+ if (purposeFilePath) {
314
+ const purposeDir = path.dirname(purposeFilePath);
315
+ const relativePath = path.join(purposeDir, anchorPath);
316
+ if (fs.existsSync(relativePath)) return relativePath;
317
+ }
318
+ return path.join(rootDir, anchorPath);
319
+ }
320
+ function getMaxLine(anchor) {
321
+ if (typeof anchor.lines === "number") {
322
+ return anchor.lines;
323
+ }
324
+ if (Array.isArray(anchor.lines)) {
325
+ return Math.max(...anchor.lines);
326
+ }
327
+ return 0;
328
+ }
329
+ function findNewestSourceFile(dir, _rootDir) {
330
+ let newest = null;
331
+ try {
332
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
333
+ for (const entry of entries) {
334
+ if (!entry.isFile()) continue;
335
+ if (SKIP_DIRS.has(entry.name)) continue;
336
+ const ext = path.extname(entry.name);
337
+ if (!SOURCE_EXTENSIONS.has(ext)) continue;
338
+ const fullPath = path.join(dir, entry.name);
339
+ try {
340
+ const stat = fs.statSync(fullPath);
341
+ if (!newest || stat.mtime.getTime() > newest.mtime) {
342
+ newest = { path: fullPath, mtime: stat.mtime.getTime() };
343
+ }
344
+ } catch {
345
+ continue;
346
+ }
347
+ }
348
+ } catch {
349
+ }
350
+ return newest;
351
+ }
352
+
353
+ export {
354
+ checkIntegrity,
355
+ checkComponentAnchors,
356
+ checkPurposeHealth
357
+ };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  indexCommand
4
- } from "./chunk-S5TDFT5Q.js";
4
+ } from "./chunk-7COU5S2Z.js";
5
5
  import {
6
6
  log
7
7
  } from "./chunk-4NCFWYGG.js";
@@ -10,7 +10,7 @@ async function graphCommand(path, options) {
10
10
  const shouldOpen = options.open !== false;
11
11
  console.log(chalk.cyan("\nStarting Symbol Graph...\n"));
12
12
  try {
13
- const { startGraphServer } = await import("./graph-server-BZ73HTAT.js");
13
+ const { startGraphServer } = await import("./graph-server-ZPXRSGCW.js");
14
14
  console.log(chalk.gray(`Project: ${projectDir}`));
15
15
  console.log(chalk.gray(`Port: ${port}`));
16
16
  console.log();