@a-company/paradigm 5.9.0 → 5.10.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 (29) hide show
  1. package/dist/{accept-orchestration-GX2YRWM4.js → accept-orchestration-UQLM7PTQ.js} +4 -4
  2. package/dist/{agent-loader-X7TDYLFL.js → agent-loader-TFIANSF4.js} +1 -1
  3. package/dist/agent-state-S5DAWPTF.js +24 -0
  4. package/dist/{chunk-3UCH56D5.js → chunk-4BLYIB7J.js} +270 -928
  5. package/dist/chunk-4L3UTYQX.js +677 -0
  6. package/dist/chunk-54LTTQBH.js +138 -0
  7. package/dist/chunk-5OUOLN6M.js +659 -0
  8. package/dist/{chunk-SDDCVUCV.js → chunk-CL7JSK52.js} +23 -0
  9. package/dist/{chunk-MA7G4CTI.js → chunk-RJE5G7WO.js} +27 -1
  10. package/dist/{chunk-EI32ZBE6.js → chunk-RTHA3XRE.js} +19 -672
  11. package/dist/{chunk-V7BZBBI6.js → chunk-VPPK3SY4.js} +1 -1
  12. package/dist/{chunk-WQITYKHM.js → chunk-YRZ5RPEB.js} +7 -7
  13. package/dist/{diff-RQLLNAFI.js → diff-D4X53HAC.js} +4 -4
  14. package/dist/{docs-AIY6VNF7.js → docs-QIYKO3BR.js} +1 -1
  15. package/dist/index.js +19 -19
  16. package/dist/mcp.js +140 -66
  17. package/dist/model-discovery-D2H3VBGC.js +8 -0
  18. package/dist/{nomination-engine-LLREC5BZ.js → nomination-engine-RV5CNO5B.js} +2 -2
  19. package/dist/{orchestrate-XZA33TJC.js → orchestrate-JLILBBJE.js} +4 -4
  20. package/dist/{reindex-U2HEB6GW.js → reindex-5LTD53ZC.js} +3 -2
  21. package/dist/{serve-QWWJP2EW.js → serve-CAH3PHE7.js} +1 -1
  22. package/dist/session-tracker-C4BMD5WG.js +13 -0
  23. package/dist/{session-work-log-KDOH4GER.js → session-work-log-MZ47OAPB.js} +1 -1
  24. package/dist/{shift-VJUGMADR.js → shift-D2JOHHBF.js} +33 -5
  25. package/dist/{spawn-AW6GDECS.js → spawn-RCHNXDHE.js} +4 -4
  26. package/dist/{team-7HG7XK5C.js → team-O5MIIFMA.js} +6 -5
  27. package/package.json +1 -1
  28. package/dist/{chunk-LSRABQIY.js → chunk-45MUDW6E.js} +3 -3
  29. /package/dist/{platform-server-U5L2G3EU.js → platform-server-H5YO3DQD.js} +0 -0
@@ -4,15 +4,18 @@ import {
4
4
  checkIntegrity,
5
5
  checkPurposeHealth
6
6
  } from "./chunk-L27I3CPZ.js";
7
- import {
8
- init_session_work_log,
9
- session_work_log_exports
10
- } from "./chunk-SDDCVUCV.js";
11
7
  import {
12
8
  init_lore_loader,
13
9
  loadLoreEntries,
14
10
  loadLoreEntry
15
11
  } from "./chunk-5VKJBNJL.js";
12
+ import {
13
+ getSessionTracker,
14
+ loadPendingHandoffs,
15
+ markHandoffDelivered,
16
+ resetSessionTracker,
17
+ writePendingHandoff
18
+ } from "./chunk-4L3UTYQX.js";
16
19
  import {
17
20
  __esm,
18
21
  __export,
@@ -30,9 +33,9 @@ __export(aspect_fingerprint_exports, {
30
33
  searchSiblingFiles: () => searchSiblingFiles,
31
34
  slidingWindowSearch: () => slidingWindowSearch
32
35
  });
33
- import * as fs5 from "fs";
34
- import * as path6 from "path";
35
- import * as crypto2 from "crypto";
36
+ import * as fs3 from "fs";
37
+ import * as path4 from "path";
38
+ import * as crypto from "crypto";
36
39
  import { execSync } from "child_process";
37
40
  function generateFingerprint(content) {
38
41
  const lines = content.split("\n").filter((l) => l.trim() !== "");
@@ -48,7 +51,7 @@ function extractStructuralHash(lines) {
48
51
  const match = l.match(STRUCTURAL_TOKENS);
49
52
  return match ? match[1].trim() : "";
50
53
  }).join("|");
51
- return crypto2.createHash("sha256").update(structural).digest("hex").slice(0, 16);
54
+ return crypto.createHash("sha256").update(structural).digest("hex").slice(0, 16);
52
55
  }
53
56
  function normalizeLine(line) {
54
57
  return line.trim().replace(/\s+/g, " ").toLowerCase();
@@ -170,18 +173,18 @@ function detectFileRename(rootDir, oldPath) {
170
173
  }
171
174
  }
172
175
  function searchSiblingFiles(rootDir, dirPath, fingerprint, originalContent, maxFiles = 10) {
173
- const absoluteDir = path6.isAbsolute(dirPath) ? dirPath : path6.join(rootDir, dirPath);
174
- if (!fs5.existsSync(absoluteDir)) return [];
176
+ const absoluteDir = path4.isAbsolute(dirPath) ? dirPath : path4.join(rootDir, dirPath);
177
+ if (!fs3.existsSync(absoluteDir)) return [];
175
178
  const results = [];
176
179
  try {
177
- const files = fs5.readdirSync(absoluteDir).filter((f) => !f.startsWith(".") && fs5.statSync(path6.join(absoluteDir, f)).isFile()).slice(0, maxFiles);
180
+ const files = fs3.readdirSync(absoluteDir).filter((f) => !f.startsWith(".") && fs3.statSync(path4.join(absoluteDir, f)).isFile()).slice(0, maxFiles);
178
181
  for (const file of files) {
179
182
  try {
180
- const content = fs5.readFileSync(path6.join(absoluteDir, file), "utf8");
183
+ const content = fs3.readFileSync(path4.join(absoluteDir, file), "utf8");
181
184
  const lines = content.split("\n");
182
185
  const matches = slidingWindowSearch(lines, fingerprint, originalContent, 1);
183
186
  if (matches.length > 0 && matches[0].score >= 0.7) {
184
- const relPath = path6.relative(rootDir, path6.join(absoluteDir, file));
187
+ const relPath = path4.relative(rootDir, path4.join(absoluteDir, file));
185
188
  results.push({
186
189
  file: relPath,
187
190
  score: matches[0].score,
@@ -199,9 +202,9 @@ function searchSiblingFiles(rootDir, dirPath, fingerprint, originalContent, maxF
199
202
  }
200
203
  function contentSearch(rootDir, filePath, originalContent, autoHeal = true) {
201
204
  const fingerprint = generateFingerprint(originalContent);
202
- const absolutePath = path6.isAbsolute(filePath) ? filePath : path6.join(rootDir, filePath);
203
- if (fs5.existsSync(absolutePath)) {
204
- const fileContent = fs5.readFileSync(absolutePath, "utf8");
205
+ const absolutePath = path4.isAbsolute(filePath) ? filePath : path4.join(rootDir, filePath);
206
+ if (fs3.existsSync(absolutePath)) {
207
+ const fileContent = fs3.readFileSync(absolutePath, "utf8");
205
208
  const fileLines = fileContent.split("\n");
206
209
  const matches = slidingWindowSearch(fileLines, fingerprint, originalContent);
207
210
  if (matches.length > 0) {
@@ -217,9 +220,9 @@ function contentSearch(rootDir, filePath, originalContent, autoHeal = true) {
217
220
  }
218
221
  const renamedTo = detectFileRename(rootDir, filePath);
219
222
  if (renamedTo) {
220
- const renamedPath = path6.join(rootDir, renamedTo);
221
- if (fs5.existsSync(renamedPath)) {
222
- const renamedContent = fs5.readFileSync(renamedPath, "utf8");
223
+ const renamedPath = path4.join(rootDir, renamedTo);
224
+ if (fs3.existsSync(renamedPath)) {
225
+ const renamedContent = fs3.readFileSync(renamedPath, "utf8");
223
226
  const renamedLines = renamedContent.split("\n");
224
227
  const matches = slidingWindowSearch(renamedLines, fingerprint, originalContent);
225
228
  if (matches.length > 0 && matches[0].score >= 0.7) {
@@ -234,7 +237,7 @@ function contentSearch(rootDir, filePath, originalContent, autoHeal = true) {
234
237
  }
235
238
  }
236
239
  }
237
- const dirPath = path6.dirname(filePath);
240
+ const dirPath = path4.dirname(filePath);
238
241
  const siblingResults = searchSiblingFiles(rootDir, dirPath, fingerprint, originalContent);
239
242
  if (siblingResults.length > 0 && siblingResults[0].score >= 0.7) {
240
243
  const best = siblingResults[0];
@@ -263,9 +266,9 @@ var init_aspect_fingerprint = __esm({
263
266
  });
264
267
 
265
268
  // ../paradigm-mcp/src/tools/reindex.ts
266
- import * as fs10 from "fs";
267
- import * as path11 from "path";
268
- import * as yaml8 from "js-yaml";
269
+ import * as fs8 from "fs";
270
+ import * as path9 from "path";
271
+ import * as yaml7 from "js-yaml";
269
272
 
270
273
  // ../premise/core/dist/index.js
271
274
  import * as yaml3 from "js-yaml";
@@ -1932,661 +1935,6 @@ function serializeScanIndex(index) {
1932
1935
  return JSON.stringify(index, null, 2);
1933
1936
  }
1934
1937
 
1935
- // ../paradigm-mcp/src/utils/session-tracker.ts
1936
- import * as fs4 from "fs";
1937
- import * as path5 from "path";
1938
-
1939
- // ../paradigm-mcp/src/utils/global-store.ts
1940
- import * as fs3 from "fs";
1941
- import * as path4 from "path";
1942
- import * as os from "os";
1943
- import * as crypto from "crypto";
1944
- import * as yaml4 from "js-yaml";
1945
- function getGlobalDir() {
1946
- const dir = path4.join(os.homedir(), ".paradigm");
1947
- if (!fs3.existsSync(dir)) {
1948
- fs3.mkdirSync(dir, { recursive: true });
1949
- }
1950
- return dir;
1951
- }
1952
- function getProjectHash(rootDir) {
1953
- const absolute = path4.resolve(rootDir);
1954
- return crypto.createHash("sha256").update(absolute).digest("hex").slice(0, 12);
1955
- }
1956
- function getSessionDir(rootDir) {
1957
- const hash = getProjectHash(rootDir);
1958
- const dir = path4.join(getGlobalDir(), "sessions", hash);
1959
- if (!fs3.existsSync(dir)) {
1960
- fs3.mkdirSync(dir, { recursive: true });
1961
- }
1962
- const handoffsDir = path4.join(dir, "pending-handoffs");
1963
- if (!fs3.existsSync(handoffsDir)) {
1964
- fs3.mkdirSync(handoffsDir, { recursive: true });
1965
- }
1966
- return dir;
1967
- }
1968
- function writeProjectMeta(rootDir) {
1969
- const sessionDir = getSessionDir(rootDir);
1970
- const metaPath = path4.join(sessionDir, "_project-meta.json");
1971
- const projectName = path4.basename(path4.resolve(rootDir));
1972
- const meta = {
1973
- name: projectName,
1974
- path: path4.resolve(rootDir),
1975
- lastSeen: (/* @__PURE__ */ new Date()).toISOString()
1976
- };
1977
- fs3.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
1978
- }
1979
- function writePendingHandoff(rootDir, handoff) {
1980
- const sessionDir = getSessionDir(rootDir);
1981
- const filePath = path4.join(sessionDir, "pending-handoffs", `${handoff.id}.json`);
1982
- fs3.writeFileSync(filePath, JSON.stringify(handoff, null, 2));
1983
- }
1984
- function loadPendingHandoffs(rootDir) {
1985
- const sessionDir = getSessionDir(rootDir);
1986
- const handoffsDir = path4.join(sessionDir, "pending-handoffs");
1987
- if (!fs3.existsSync(handoffsDir)) {
1988
- return [];
1989
- }
1990
- const handoffs = [];
1991
- try {
1992
- const files = fs3.readdirSync(handoffsDir);
1993
- for (const file of files) {
1994
- if (!file.endsWith(".json")) continue;
1995
- try {
1996
- const content = fs3.readFileSync(path4.join(handoffsDir, file), "utf8");
1997
- const handoff = JSON.parse(content);
1998
- if (handoff.status === "pending") {
1999
- handoffs.push(handoff);
2000
- }
2001
- } catch {
2002
- }
2003
- }
2004
- } catch {
2005
- }
2006
- handoffs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
2007
- return handoffs;
2008
- }
2009
- function markHandoffDelivered(rootDir, handoffId) {
2010
- const sessionDir = getSessionDir(rootDir);
2011
- const filePath = path4.join(sessionDir, "pending-handoffs", `${handoffId}.json`);
2012
- if (!fs3.existsSync(filePath)) return;
2013
- try {
2014
- const content = fs3.readFileSync(filePath, "utf8");
2015
- const handoff = JSON.parse(content);
2016
- handoff.status = "delivered";
2017
- fs3.writeFileSync(filePath, JSON.stringify(handoff, null, 2));
2018
- } catch {
2019
- }
2020
- }
2021
- function getGlobalWisdomDir() {
2022
- const dir = path4.join(getGlobalDir(), "wisdom");
2023
- if (!fs3.existsSync(dir)) {
2024
- fs3.mkdirSync(dir, { recursive: true });
2025
- }
2026
- return dir;
2027
- }
2028
- function loadGlobalAntipatterns() {
2029
- const filePath = path4.join(getGlobalWisdomDir(), "antipatterns.yaml");
2030
- if (!fs3.existsSync(filePath)) return [];
2031
- try {
2032
- const content = fs3.readFileSync(filePath, "utf8");
2033
- const data = yaml4.load(content);
2034
- return data?.antipatterns || [];
2035
- } catch {
2036
- return [];
2037
- }
2038
- }
2039
- function loadGlobalDecisions() {
2040
- const decisionsDir = path4.join(getGlobalWisdomDir(), "decisions");
2041
- if (!fs3.existsSync(decisionsDir)) return [];
2042
- const decisions = [];
2043
- try {
2044
- const files = fs3.readdirSync(decisionsDir);
2045
- for (const file of files) {
2046
- if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
2047
- try {
2048
- const content = fs3.readFileSync(path4.join(decisionsDir, file), "utf8");
2049
- const decision = yaml4.load(content);
2050
- decisions.push(decision);
2051
- } catch {
2052
- }
2053
- }
2054
- } catch {
2055
- }
2056
- decisions.sort((a, b) => a.id.localeCompare(b.id));
2057
- return decisions;
2058
- }
2059
- function loadGlobalPreferences() {
2060
- const filePath = path4.join(getGlobalWisdomDir(), "preferences.yaml");
2061
- if (!fs3.existsSync(filePath)) return null;
2062
- try {
2063
- const content = fs3.readFileSync(filePath, "utf8");
2064
- return yaml4.load(content);
2065
- } catch {
2066
- return null;
2067
- }
2068
- }
2069
- function recordGlobalAntipattern(antipattern) {
2070
- const filePath = path4.join(getGlobalWisdomDir(), "antipatterns.yaml");
2071
- let data = { version: "1.0", antipatterns: [] };
2072
- if (fs3.existsSync(filePath)) {
2073
- try {
2074
- const content = fs3.readFileSync(filePath, "utf8");
2075
- data = yaml4.load(content);
2076
- if (!data.antipatterns) data.antipatterns = [];
2077
- } catch {
2078
- }
2079
- }
2080
- data.antipatterns.push({
2081
- ...antipattern,
2082
- added: (/* @__PURE__ */ new Date()).toISOString()
2083
- });
2084
- fs3.writeFileSync(filePath, yaml4.dump(data, { lineWidth: -1 }));
2085
- }
2086
- function recordGlobalDecision(decision) {
2087
- const decisionsDir = path4.join(getGlobalWisdomDir(), "decisions");
2088
- if (!fs3.existsSync(decisionsDir)) {
2089
- fs3.mkdirSync(decisionsDir, { recursive: true });
2090
- }
2091
- const slug = decision.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
2092
- const fileName = `${decision.id}-${slug}.yaml`;
2093
- const filePath = path4.join(decisionsDir, fileName);
2094
- fs3.writeFileSync(filePath, yaml4.dump(decision, { lineWidth: -1 }));
2095
- }
2096
-
2097
- // ../paradigm-mcp/src/utils/session-tracker.ts
2098
- var MODEL_PRICING = {
2099
- "claude-opus-4": { input: 15, output: 75, name: "Claude Opus 4" },
2100
- "claude-sonnet-4": { input: 3, output: 15, name: "Claude Sonnet 4" },
2101
- "claude-haiku-3.5": { input: 0.8, output: 4, name: "Claude Haiku 3.5" }
2102
- };
2103
- var MAX_BREADCRUMBS = 50;
2104
- var BREADCRUMBS_FILE = ".paradigm/session-breadcrumbs.json";
2105
- var CHECKPOINT_FILE = ".paradigm/session-checkpoint.json";
2106
- var CHECKPOINT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
2107
- var SessionTracker = class {
2108
- session;
2109
- rootDir = null;
2110
- _recovered = false;
2111
- lastLoreEntryId = null;
2112
- constructor() {
2113
- this.session = this.createNewSession();
2114
- }
2115
- /**
2116
- * Set the project root directory (for persisting breadcrumbs)
2117
- */
2118
- setRootDir(rootDir) {
2119
- this.rootDir = rootDir;
2120
- try {
2121
- const { clearSessionWorkLog } = (init_session_work_log(), __toCommonJS(session_work_log_exports));
2122
- clearSessionWorkLog(rootDir);
2123
- } catch {
2124
- }
2125
- }
2126
- createNewSession() {
2127
- return {
2128
- sessionId: `s${Date.now().toString(36)}`,
2129
- startTime: Date.now(),
2130
- lastActivity: Date.now(),
2131
- model: "claude-sonnet-4",
2132
- resourceReads: [],
2133
- toolCalls: [],
2134
- breadcrumbs: [],
2135
- totals: {
2136
- resourceReadCount: 0,
2137
- toolCallCount: 0,
2138
- totalBytes: 0,
2139
- totalTokens: 0,
2140
- estimatedCostUsd: 0
2141
- }
2142
- };
2143
- }
2144
- /**
2145
- * Add a breadcrumb (summarized action for session recovery)
2146
- */
2147
- addBreadcrumb(action, summary, options = {}) {
2148
- this.session.breadcrumbs.push({
2149
- timestamp: Date.now(),
2150
- action,
2151
- tool: options.tool,
2152
- symbol: options.symbol,
2153
- summary
2154
- });
2155
- if (this.session.breadcrumbs.length > MAX_BREADCRUMBS) {
2156
- this.session.breadcrumbs = this.session.breadcrumbs.slice(-MAX_BREADCRUMBS);
2157
- }
2158
- this.persistBreadcrumbs();
2159
- }
2160
- /**
2161
- * Get recent breadcrumbs
2162
- */
2163
- getBreadcrumbs(limit = 20) {
2164
- return this.session.breadcrumbs.slice(-limit);
2165
- }
2166
- /**
2167
- * Persist breadcrumbs to file (dual-write: local + global)
2168
- */
2169
- persistBreadcrumbs() {
2170
- if (!this.rootDir) return;
2171
- const data = {
2172
- sessionId: this.session.sessionId,
2173
- startTime: this.session.startTime,
2174
- lastActivity: this.session.lastActivity,
2175
- breadcrumbs: this.session.breadcrumbs,
2176
- symbolsModified: this.extractSymbolsFromBreadcrumbs(),
2177
- filesExplored: this.extractFilesFromBreadcrumbs()
2178
- };
2179
- let jsonData;
2180
- try {
2181
- jsonData = JSON.stringify(data, null, 2);
2182
- } catch (err) {
2183
- console.error("[paradigm-mcp] persistBreadcrumbs: JSON.stringify failed:", err.message);
2184
- return;
2185
- }
2186
- try {
2187
- const filePath = path5.join(this.rootDir, BREADCRUMBS_FILE);
2188
- const dir = path5.dirname(filePath);
2189
- if (!fs4.existsSync(dir)) {
2190
- fs4.mkdirSync(dir, { recursive: true });
2191
- }
2192
- fs4.writeFileSync(filePath, jsonData);
2193
- } catch (err) {
2194
- console.error("[paradigm-mcp] persistBreadcrumbs: local write failed:", err.message);
2195
- }
2196
- try {
2197
- const globalSessionDir = getSessionDir(this.rootDir);
2198
- fs4.writeFileSync(path5.join(globalSessionDir, "breadcrumbs.json"), jsonData);
2199
- writeProjectMeta(this.rootDir);
2200
- } catch (err) {
2201
- console.error("[paradigm-mcp] persistBreadcrumbs: global write failed:", err.message);
2202
- }
2203
- }
2204
- /**
2205
- * Load previous session breadcrumbs from file.
2206
- * Prefers global path (~/.paradigm/sessions/{hash}/breadcrumbs.json),
2207
- * falls back to local (.paradigm/session-breadcrumbs.json).
2208
- */
2209
- loadPreviousSession() {
2210
- if (!this.rootDir) return null;
2211
- try {
2212
- const globalSessionDir = getSessionDir(this.rootDir);
2213
- const globalPath = path5.join(globalSessionDir, "breadcrumbs.json");
2214
- if (fs4.existsSync(globalPath)) {
2215
- const content = fs4.readFileSync(globalPath, "utf8");
2216
- return JSON.parse(content);
2217
- }
2218
- } catch {
2219
- }
2220
- try {
2221
- const filePath = path5.join(this.rootDir, BREADCRUMBS_FILE);
2222
- if (!fs4.existsSync(filePath)) return null;
2223
- const content = fs4.readFileSync(filePath, "utf8");
2224
- return JSON.parse(content);
2225
- } catch {
2226
- return null;
2227
- }
2228
- }
2229
- /**
2230
- * Save a cognitive-transition checkpoint for crash recovery.
2231
- * Fills in timestamp, sessionId, and snapshots recent breadcrumbs.
2232
- * Returns the checkpoint and whether it was persisted to disk.
2233
- */
2234
- saveCheckpoint(data) {
2235
- const checkpoint = {
2236
- phase: data.phase,
2237
- context: data.context,
2238
- timestamp: Date.now(),
2239
- sessionId: this.session.sessionId,
2240
- externalId: data.externalId,
2241
- plan: data.plan,
2242
- modifiedFiles: data.modifiedFiles,
2243
- symbolsTouched: data.symbolsTouched,
2244
- decisions: data.decisions,
2245
- recentBreadcrumbs: this.session.breadcrumbs.slice(-10)
2246
- };
2247
- const persisted = this.persistCheckpoint(checkpoint);
2248
- return { checkpoint, persisted };
2249
- }
2250
- /**
2251
- * Load the most recent checkpoint.
2252
- * Prefers global path, falls back to local.
2253
- * Returns null for checkpoints older than 7 days.
2254
- */
2255
- loadCheckpoint() {
2256
- if (!this.rootDir) return null;
2257
- let checkpoint = null;
2258
- try {
2259
- const globalSessionDir = getSessionDir(this.rootDir);
2260
- const globalPath = path5.join(globalSessionDir, "checkpoint.json");
2261
- if (fs4.existsSync(globalPath)) {
2262
- const content = fs4.readFileSync(globalPath, "utf8");
2263
- checkpoint = JSON.parse(content);
2264
- }
2265
- } catch {
2266
- }
2267
- if (!checkpoint) {
2268
- try {
2269
- const localPath = path5.join(this.rootDir, CHECKPOINT_FILE);
2270
- if (fs4.existsSync(localPath)) {
2271
- const content = fs4.readFileSync(localPath, "utf8");
2272
- checkpoint = JSON.parse(content);
2273
- }
2274
- } catch {
2275
- }
2276
- }
2277
- if (checkpoint && Date.now() - checkpoint.timestamp > CHECKPOINT_MAX_AGE_MS) {
2278
- return null;
2279
- }
2280
- if (checkpoint) {
2281
- for (const key of ["modifiedFiles", "symbolsTouched", "decisions"]) {
2282
- const val = checkpoint[key];
2283
- if (typeof val === "string") {
2284
- try {
2285
- checkpoint[key] = JSON.parse(val);
2286
- } catch {
2287
- checkpoint[key] = [];
2288
- }
2289
- }
2290
- }
2291
- }
2292
- return checkpoint;
2293
- }
2294
- /**
2295
- * Persist checkpoint to both local and global paths.
2296
- * Returns which writes succeeded so callers can report accurately.
2297
- */
2298
- persistCheckpoint(checkpoint) {
2299
- const result = { local: false, global: false };
2300
- if (!this.rootDir) {
2301
- console.error("[paradigm-mcp] persistCheckpoint: rootDir not set, skipping write");
2302
- return result;
2303
- }
2304
- let jsonData;
2305
- try {
2306
- jsonData = JSON.stringify(checkpoint, null, 2);
2307
- } catch (err) {
2308
- console.error("[paradigm-mcp] persistCheckpoint: JSON.stringify failed:", err.message);
2309
- return result;
2310
- }
2311
- try {
2312
- const filePath = path5.join(this.rootDir, CHECKPOINT_FILE);
2313
- const dir = path5.dirname(filePath);
2314
- if (!fs4.existsSync(dir)) {
2315
- fs4.mkdirSync(dir, { recursive: true });
2316
- }
2317
- fs4.writeFileSync(filePath, jsonData);
2318
- result.local = true;
2319
- } catch (err) {
2320
- console.error("[paradigm-mcp] persistCheckpoint: local write failed:", err.message);
2321
- }
2322
- try {
2323
- const globalSessionDir = getSessionDir(this.rootDir);
2324
- fs4.writeFileSync(path5.join(globalSessionDir, "checkpoint.json"), jsonData);
2325
- writeProjectMeta(this.rootDir);
2326
- result.global = true;
2327
- } catch (err) {
2328
- console.error("[paradigm-mcp] persistCheckpoint: global write failed:", err.message);
2329
- }
2330
- return result;
2331
- }
2332
- /**
2333
- * Set the last lore entry ID recorded in this session
2334
- */
2335
- setLastLoreEntryId(id) {
2336
- this.lastLoreEntryId = id;
2337
- }
2338
- /**
2339
- * Get the last lore entry ID recorded in this session
2340
- */
2341
- getLastLoreEntryId() {
2342
- return this.lastLoreEntryId;
2343
- }
2344
- /**
2345
- * Check whether auto-recovery has already fired this session.
2346
- */
2347
- hasRecoveredThisSession() {
2348
- return this._recovered;
2349
- }
2350
- /**
2351
- * Mark that auto-recovery has fired (so it only fires once per session).
2352
- */
2353
- markRecovered() {
2354
- this._recovered = true;
2355
- }
2356
- /**
2357
- * Extract symbols from breadcrumbs
2358
- */
2359
- extractSymbolsFromBreadcrumbs() {
2360
- const symbols = /* @__PURE__ */ new Set();
2361
- for (const bc of this.session.breadcrumbs) {
2362
- if (bc.symbol) symbols.add(bc.symbol);
2363
- }
2364
- return Array.from(symbols);
2365
- }
2366
- /**
2367
- * Extract files from breadcrumbs
2368
- */
2369
- extractFilesFromBreadcrumbs() {
2370
- const files = /* @__PURE__ */ new Set();
2371
- for (const bc of this.session.breadcrumbs) {
2372
- const matches = bc.summary.match(/\b[\w./]+\.(ts|js|tsx|jsx|py|go|rs|yaml|json|md)\b/g);
2373
- if (matches) {
2374
- for (const m of matches) {
2375
- files.add(m);
2376
- }
2377
- }
2378
- }
2379
- return Array.from(files);
2380
- }
2381
- /**
2382
- * Estimate tokens from text (approx 3.5 chars per token)
2383
- */
2384
- estimateTokens(text) {
2385
- const len = typeof text === "number" ? text : text.length;
2386
- return Math.ceil(len / 3.5);
2387
- }
2388
- /**
2389
- * Calculate cost for tokens using current model pricing
2390
- */
2391
- calculateCost(tokens, isOutput = true) {
2392
- const pricing = MODEL_PRICING[this.session.model];
2393
- const rate = isOutput ? pricing.output : pricing.input;
2394
- return tokens / 1e6 * rate;
2395
- }
2396
- /**
2397
- * Set the model for cost calculations
2398
- */
2399
- setModel(model) {
2400
- this.session.model = model;
2401
- this.recalculateTotals();
2402
- }
2403
- /**
2404
- * Get current model
2405
- */
2406
- getModel() {
2407
- return this.session.model;
2408
- }
2409
- /**
2410
- * Track a resource read
2411
- */
2412
- trackResourceRead(uri, bytes) {
2413
- const resourceType = this.extractResourceType(uri);
2414
- const tokens = this.estimateTokens(bytes);
2415
- this.session.resourceReads.push({
2416
- timestamp: Date.now(),
2417
- resourceType,
2418
- uri,
2419
- bytes,
2420
- tokens
2421
- });
2422
- this.session.lastActivity = Date.now();
2423
- this.updateTotals(bytes, tokens);
2424
- }
2425
- /**
2426
- * Track a tool call
2427
- */
2428
- trackToolCall(toolName, responseBytes) {
2429
- const tokens = this.estimateTokens(responseBytes);
2430
- this.session.toolCalls.push({
2431
- timestamp: Date.now(),
2432
- toolName,
2433
- responseBytes,
2434
- responseTokens: tokens
2435
- });
2436
- this.session.lastActivity = Date.now();
2437
- this.updateTotals(responseBytes, tokens);
2438
- }
2439
- /**
2440
- * Update running totals
2441
- */
2442
- updateTotals(bytes, tokens) {
2443
- this.session.totals.resourceReadCount = this.session.resourceReads.length;
2444
- this.session.totals.toolCallCount = this.session.toolCalls.length;
2445
- this.session.totals.totalBytes += bytes;
2446
- this.session.totals.totalTokens += tokens;
2447
- this.session.totals.estimatedCostUsd = this.calculateCost(this.session.totals.totalTokens);
2448
- }
2449
- /**
2450
- * Recalculate totals (used when model changes)
2451
- */
2452
- recalculateTotals() {
2453
- this.session.totals.estimatedCostUsd = this.calculateCost(this.session.totals.totalTokens);
2454
- }
2455
- /**
2456
- * Extract resource type from URI
2457
- */
2458
- extractResourceType(uri) {
2459
- const path12 = uri.replace("paradigm://", "");
2460
- const firstPart = path12.split("/")[0];
2461
- return firstPart || "unknown";
2462
- }
2463
- /**
2464
- * Get session statistics
2465
- */
2466
- getStats() {
2467
- return { ...this.session };
2468
- }
2469
- /**
2470
- * Get detailed cost breakdown
2471
- */
2472
- getCostBreakdown() {
2473
- const resourcesByType = {};
2474
- let resourceBytes = 0;
2475
- let resourceTokens = 0;
2476
- for (const read of this.session.resourceReads) {
2477
- if (!resourcesByType[read.resourceType]) {
2478
- resourcesByType[read.resourceType] = { count: 0, bytes: 0, tokens: 0 };
2479
- }
2480
- resourcesByType[read.resourceType].count++;
2481
- resourcesByType[read.resourceType].bytes += read.bytes;
2482
- resourcesByType[read.resourceType].tokens += read.tokens;
2483
- resourceBytes += read.bytes;
2484
- resourceTokens += read.tokens;
2485
- }
2486
- const toolsByName = {};
2487
- let toolBytes = 0;
2488
- let toolTokens = 0;
2489
- for (const call of this.session.toolCalls) {
2490
- if (!toolsByName[call.toolName]) {
2491
- toolsByName[call.toolName] = { count: 0, bytes: 0, tokens: 0 };
2492
- }
2493
- toolsByName[call.toolName].count++;
2494
- toolsByName[call.toolName].bytes += call.responseBytes;
2495
- toolsByName[call.toolName].tokens += call.responseTokens;
2496
- toolBytes += call.responseBytes;
2497
- toolTokens += call.responseTokens;
2498
- }
2499
- const totalTokens = resourceTokens + toolTokens;
2500
- const totalCost = this.calculateCost(totalTokens);
2501
- return {
2502
- model: MODEL_PRICING[this.session.model].name,
2503
- modelId: this.session.model,
2504
- pricing: MODEL_PRICING[this.session.model],
2505
- resources: {
2506
- count: this.session.resourceReads.length,
2507
- bytes: resourceBytes,
2508
- tokens: resourceTokens,
2509
- costUsd: this.calculateCost(resourceTokens),
2510
- byType: resourcesByType
2511
- },
2512
- tools: {
2513
- count: this.session.toolCalls.length,
2514
- bytes: toolBytes,
2515
- tokens: toolTokens,
2516
- costUsd: this.calculateCost(toolTokens),
2517
- byName: toolsByName
2518
- },
2519
- total: {
2520
- tokens: totalTokens,
2521
- costUsd: totalCost
2522
- }
2523
- };
2524
- }
2525
- /**
2526
- * Get handoff recommendation based on context usage
2527
- */
2528
- getHandoffRecommendation(contextWindowSize = 2e5, estimatedTotalTokens) {
2529
- const mcpTokens = this.session.totals.totalTokens;
2530
- const estimatedConversationOverhead = mcpTokens * 4;
2531
- const totalEstimate = estimatedTotalTokens || mcpTokens + estimatedConversationOverhead;
2532
- const usagePercent = Math.round(totalEstimate / contextWindowSize * 100);
2533
- let recommendation;
2534
- let message;
2535
- if (usagePercent >= 85) {
2536
- recommendation = "handoff-urgent";
2537
- message = "Context is nearly full. Initiate handoff immediately to preserve session continuity.";
2538
- } else if (usagePercent >= 70) {
2539
- recommendation = "handoff-recommended";
2540
- message = "Context usage is high. Consider initiating handoff soon to ensure smooth transition.";
2541
- } else if (usagePercent >= 50) {
2542
- recommendation = "consider-handoff";
2543
- message = "Context usage is moderate. Plan a good stopping point for potential handoff.";
2544
- } else {
2545
- recommendation = "continue";
2546
- message = "Context usage is healthy. Continue working.";
2547
- }
2548
- const signals = [];
2549
- const durationMin = Math.round((Date.now() - this.session.startTime) / 6e4);
2550
- const totalCalls = this.session.toolCalls.length + this.session.resourceReads.length;
2551
- if (totalCalls > 50) {
2552
- signals.push(`High number of MCP interactions (${totalCalls})`);
2553
- }
2554
- if (durationMin > 30) {
2555
- signals.push(`Session duration >30 min (${durationMin} min)`);
2556
- }
2557
- if (this.session.totals.totalBytes > 5e5) {
2558
- signals.push(`Large data volume (${Math.round(this.session.totals.totalBytes / 1024)}KB)`);
2559
- }
2560
- return { recommendation, message, usagePercent, signals };
2561
- }
2562
- /**
2563
- * Get session duration in minutes
2564
- */
2565
- getDurationMinutes() {
2566
- return Math.round((Date.now() - this.session.startTime) / 6e4);
2567
- }
2568
- /**
2569
- * Reset session (for handoff or new session)
2570
- */
2571
- reset() {
2572
- this.session = this.createNewSession();
2573
- this._recovered = false;
2574
- this.lastLoreEntryId = null;
2575
- }
2576
- };
2577
- var tracker = null;
2578
- function getSessionTracker() {
2579
- if (!tracker) {
2580
- tracker = new SessionTracker();
2581
- }
2582
- return tracker;
2583
- }
2584
- function resetSessionTracker() {
2585
- if (tracker) {
2586
- tracker.reset();
2587
- }
2588
- }
2589
-
2590
1938
  // ../paradigm-mcp/src/tools/context.ts
2591
1939
  function trackToolCall(responseSize, toolName = "unknown") {
2592
1940
  getSessionTracker().trackToolCall(toolName, responseSize);
@@ -2694,9 +2042,9 @@ function extractBreadcrumbInfo(toolName, args) {
2694
2042
  }
2695
2043
  }
2696
2044
  function addToolBreadcrumb(toolName, args) {
2697
- const tracker2 = getSessionTracker();
2045
+ const tracker = getSessionTracker();
2698
2046
  const { summary, symbol } = extractBreadcrumbInfo(toolName, args);
2699
- tracker2.addBreadcrumb("tool-call", summary, { tool: toolName, symbol });
2047
+ tracker.addBreadcrumb("tool-call", summary, { tool: toolName, symbol });
2700
2048
  }
2701
2049
  function getContextToolsList() {
2702
2050
  return [
@@ -2878,16 +2226,16 @@ function getContextToolsList() {
2878
2226
  ];
2879
2227
  }
2880
2228
  async function handleContextTool(name, args, _ctx) {
2881
- const tracker2 = getSessionTracker();
2229
+ const tracker = getSessionTracker();
2882
2230
  if (name === "paradigm_context_check") {
2883
2231
  const contextWindowSize = args.contextWindowSize || 2e5;
2884
2232
  const estimatedTotal = args.estimatedTotalTokens;
2885
- const stats = tracker2.getStats();
2886
- const { recommendation, message, usagePercent, signals } = tracker2.getHandoffRecommendation(
2233
+ const stats = tracker.getStats();
2234
+ const { recommendation, message, usagePercent, signals } = tracker.getHandoffRecommendation(
2887
2235
  contextWindowSize,
2888
2236
  estimatedTotal
2889
2237
  );
2890
- const durationMin = tracker2.getDurationMinutes();
2238
+ const durationMin = tracker.getDurationMinutes();
2891
2239
  return {
2892
2240
  handled: true,
2893
2241
  text: JSON.stringify({
@@ -2914,8 +2262,8 @@ async function handleContextTool(name, args, _ctx) {
2914
2262
  const modifiedFiles = args.modifiedFiles || [];
2915
2263
  const symbolsTouched = args.symbolsTouched || [];
2916
2264
  const openQuestions = args.openQuestions || [];
2917
- const stats = tracker2.getStats();
2918
- const breakdown = tracker2.getCostBreakdown();
2265
+ const stats = tracker.getStats();
2266
+ const breakdown = tracker.getCostBreakdown();
2919
2267
  const handoffId = `h${Date.now().toString(36)}`;
2920
2268
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2921
2269
  const handoffPayload = {
@@ -2929,7 +2277,7 @@ async function handleContextTool(name, args, _ctx) {
2929
2277
  symbolsTouched,
2930
2278
  openQuestions,
2931
2279
  sessionStats: {
2932
- duration: tracker2.getDurationMinutes(),
2280
+ duration: tracker.getDurationMinutes(),
2933
2281
  mcpCalls: stats.totals.toolCallCount + stats.totals.resourceReadCount,
2934
2282
  estimatedTokens: stats.totals.totalTokens,
2935
2283
  estimatedCostUsd: breakdown.total.costUsd,
@@ -2966,9 +2314,9 @@ ${nextSteps.map((step, i) => `${i + 1}. ${step}`).join("\n") || "(none specified
2966
2314
  };
2967
2315
  }
2968
2316
  if (name === "paradigm_session_stats") {
2969
- const stats = tracker2.getStats();
2970
- const breakdown = tracker2.getCostBreakdown();
2971
- const durationMin = tracker2.getDurationMinutes();
2317
+ const stats = tracker.getStats();
2318
+ const breakdown = tracker.getCostBreakdown();
2319
+ const durationMin = tracker.getDurationMinutes();
2972
2320
  return {
2973
2321
  handled: true,
2974
2322
  text: JSON.stringify({
@@ -3013,9 +2361,9 @@ ${nextSteps.map((step, i) => `${i + 1}. ${step}`).join("\n") || "(none specified
3013
2361
  };
3014
2362
  }
3015
2363
  if (name === "paradigm_session_recover") {
3016
- tracker2.setRootDir(_ctx.rootDir);
3017
- const previousSession = tracker2.loadPreviousSession();
3018
- const checkpoint = tracker2.loadCheckpoint();
2364
+ tracker.setRootDir(_ctx.rootDir);
2365
+ const previousSession = tracker.loadPreviousSession();
2366
+ const checkpoint = tracker.loadCheckpoint();
3019
2367
  let pendingHandoffs = [];
3020
2368
  try {
3021
2369
  pendingHandoffs = loadPendingHandoffs(_ctx.rootDir);
@@ -3121,14 +2469,14 @@ ${nextSteps.map((step, i) => `${i + 1}. ${step}`).join("\n") || "(none specified
3121
2469
  }
3122
2470
  result.suggestion = suggestion;
3123
2471
  result.agentInstruction = "Present a brief summary of the previous session, then ask the user what they would like to do: (1) Continue \u2014 pick up where the last session left off, (2) Discard \u2014 ignore the previous session and start fresh, or (3) let them describe what they want to work on instead. Do NOT automatically continue without asking.";
3124
- tracker2.markRecovered();
2472
+ tracker.markRecovered();
3125
2473
  return {
3126
2474
  handled: true,
3127
2475
  text: JSON.stringify(result, null, 2)
3128
2476
  };
3129
2477
  }
3130
2478
  if (name === "paradigm_session_checkpoint") {
3131
- tracker2.setRootDir(_ctx.rootDir);
2479
+ tracker.setRootDir(_ctx.rootDir);
3132
2480
  const phase = args.phase;
3133
2481
  const context = args.context;
3134
2482
  const externalId = args.externalId;
@@ -3136,7 +2484,7 @@ ${nextSteps.map((step, i) => `${i + 1}. ${step}`).join("\n") || "(none specified
3136
2484
  const modifiedFiles = args.modifiedFiles;
3137
2485
  const symbolsTouched = args.symbolsTouched;
3138
2486
  const decisions = args.decisions;
3139
- const { checkpoint, persisted } = tracker2.saveCheckpoint({
2487
+ const { checkpoint, persisted } = tracker.saveCheckpoint({
3140
2488
  phase,
3141
2489
  context,
3142
2490
  externalId,
@@ -3169,9 +2517,9 @@ ${nextSteps.map((step, i) => `${i + 1}. ${step}`).join("\n") || "(none specified
3169
2517
  return { handled: false, text: "" };
3170
2518
  }
3171
2519
  async function buildRecoveryPreamble(rootDir) {
3172
- const tracker2 = getSessionTracker();
3173
- tracker2.setRootDir(rootDir);
3174
- const checkpoint = tracker2.loadCheckpoint();
2520
+ const tracker = getSessionTracker();
2521
+ tracker.setRootDir(rootDir);
2522
+ const checkpoint = tracker.loadCheckpoint();
3175
2523
  let pendingHandoffs = [];
3176
2524
  try {
3177
2525
  pendingHandoffs = loadPendingHandoffs(rootDir);
@@ -3244,7 +2592,7 @@ async function buildRecoveryPreamble(rootDir) {
3244
2592
  } catch {
3245
2593
  }
3246
2594
  try {
3247
- const { loadNominations } = await import("./nomination-engine-LLREC5BZ.js");
2595
+ const { loadNominations } = await import("./nomination-engine-RV5CNO5B.js");
3248
2596
  const urgent = loadNominations(rootDir, { pending_only: true }).filter((n) => n.urgency === "critical" || n.urgency === "high");
3249
2597
  if (urgent.length > 0) {
3250
2598
  lines.push("");
@@ -3315,9 +2663,9 @@ var ToolCache = class {
3315
2663
  var toolCache = new ToolCache(3e4);
3316
2664
 
3317
2665
  // ../paradigm-mcp/src/utils/aspect-graph.ts
3318
- import * as fs6 from "fs";
3319
- import * as path7 from "path";
3320
- import * as crypto3 from "crypto";
2666
+ import * as fs4 from "fs";
2667
+ import * as path5 from "path";
2668
+ import * as crypto2 from "crypto";
3321
2669
  import { execSync as execSync2 } from "child_process";
3322
2670
  import initSqlJs from "sql.js";
3323
2671
  var cachedSQL = null;
@@ -3438,15 +2786,15 @@ function queryOne(db, sql, params) {
3438
2786
  }
3439
2787
  async function openAspectGraph(rootDir) {
3440
2788
  const SQL = await getSqlJs();
3441
- const dbDir = path7.join(rootDir, ".paradigm");
3442
- const dbPath = path7.join(dbDir, "aspect-graph.db");
2789
+ const dbDir = path5.join(rootDir, ".paradigm");
2790
+ const dbPath = path5.join(dbDir, "aspect-graph.db");
3443
2791
  let db;
3444
- if (fs6.existsSync(dbPath)) {
3445
- const buffer = fs6.readFileSync(dbPath);
2792
+ if (fs4.existsSync(dbPath)) {
2793
+ const buffer = fs4.readFileSync(dbPath);
3446
2794
  db = new SQL.Database(buffer);
3447
2795
  } else {
3448
- if (!fs6.existsSync(dbDir)) {
3449
- fs6.mkdirSync(dbDir, { recursive: true });
2796
+ if (!fs4.existsSync(dbDir)) {
2797
+ fs4.mkdirSync(dbDir, { recursive: true });
3450
2798
  }
3451
2799
  db = new SQL.Database();
3452
2800
  }
@@ -3467,13 +2815,13 @@ async function openAspectGraph(rootDir) {
3467
2815
  }
3468
2816
  function closeAspectGraph(db, rootDir) {
3469
2817
  if (rootDir) {
3470
- const dbDir = path7.join(rootDir, ".paradigm");
3471
- if (!fs6.existsSync(dbDir)) {
3472
- fs6.mkdirSync(dbDir, { recursive: true });
2818
+ const dbDir = path5.join(rootDir, ".paradigm");
2819
+ if (!fs4.existsSync(dbDir)) {
2820
+ fs4.mkdirSync(dbDir, { recursive: true });
3473
2821
  }
3474
- const dbPath = path7.join(dbDir, "aspect-graph.db");
2822
+ const dbPath = path5.join(dbDir, "aspect-graph.db");
3475
2823
  const data = db.export();
3476
- fs6.writeFileSync(dbPath, Buffer.from(data));
2824
+ fs4.writeFileSync(dbPath, Buffer.from(data));
3477
2825
  }
3478
2826
  db.close();
3479
2827
  }
@@ -3609,8 +2957,8 @@ function checkDrift(db, rootDir, aspectId, autoHeal = true) {
3609
2957
  const anchorRows = aspectId ? queryRows(db, "SELECT * FROM anchors WHERE aspect_id = ?", [aspectId]) : queryRows(db, "SELECT * FROM anchors");
3610
2958
  const results = [];
3611
2959
  for (const anchor of anchorRows) {
3612
- const absolutePath = path7.isAbsolute(anchor.file_path) ? anchor.file_path : path7.join(rootDir, anchor.file_path);
3613
- if (!fs6.existsSync(absolutePath)) {
2960
+ const absolutePath = path5.isAbsolute(anchor.file_path) ? anchor.file_path : path5.join(rootDir, anchor.file_path);
2961
+ if (!fs4.existsSync(absolutePath)) {
3614
2962
  results.push({
3615
2963
  aspectId: anchor.aspect_id,
3616
2964
  path: anchor.file_path,
@@ -3624,12 +2972,12 @@ function checkDrift(db, rootDir, aspectId, autoHeal = true) {
3624
2972
  continue;
3625
2973
  }
3626
2974
  try {
3627
- const fileContent = fs6.readFileSync(absolutePath, "utf8");
2975
+ const fileContent = fs4.readFileSync(absolutePath, "utf8");
3628
2976
  const lines = fileContent.split("\n");
3629
2977
  const startIdx = Math.max(0, anchor.start_line - 1);
3630
2978
  const endIdx = Math.min(lines.length, anchor.end_line);
3631
2979
  const sliceContent = lines.slice(startIdx, endIdx).join("\n");
3632
- const currentExactHash = crypto3.createHash("sha256").update(sliceContent).digest("hex");
2980
+ const currentExactHash = crypto2.createHash("sha256").update(sliceContent).digest("hex");
3633
2981
  if (anchor.content_hash != null && currentExactHash === anchor.content_hash) {
3634
2982
  results.push({
3635
2983
  aspectId: anchor.aspect_id,
@@ -3646,7 +2994,7 @@ function checkDrift(db, rootDir, aspectId, autoHeal = true) {
3646
2994
  }
3647
2995
  continue;
3648
2996
  }
3649
- const currentNormalizedHash = crypto3.createHash("sha256").update(normalizeForHash(sliceContent)).digest("hex");
2997
+ const currentNormalizedHash = crypto2.createHash("sha256").update(normalizeForHash(sliceContent)).digest("hex");
3650
2998
  if (anchor.normalized_hash != null && currentNormalizedHash === anchor.normalized_hash) {
3651
2999
  db.run("UPDATE anchors SET content_hash = ?, drifted = 0 WHERE id = ?", [currentExactHash, anchor.id]);
3652
3000
  results.push({
@@ -3691,7 +3039,7 @@ function checkDrift(db, rootDir, aspectId, autoHeal = true) {
3691
3039
  const shiftedStartIdx = Math.max(0, mapping.currentStart - 1);
3692
3040
  const shiftedEndIdx = Math.min(lines.length, mapping.currentEnd);
3693
3041
  const shiftedContent = lines.slice(shiftedStartIdx, shiftedEndIdx).join("\n");
3694
- const shiftedExactHash = crypto3.createHash("sha256").update(shiftedContent).digest("hex");
3042
+ const shiftedExactHash = crypto2.createHash("sha256").update(shiftedContent).digest("hex");
3695
3043
  if (anchor.content_hash != null && shiftedExactHash === anchor.content_hash) {
3696
3044
  const healed = autoHeal;
3697
3045
  if (healed) {
@@ -3731,10 +3079,10 @@ function checkDrift(db, rootDir, aspectId, autoHeal = true) {
3731
3079
  });
3732
3080
  resolvedByGit = true;
3733
3081
  } else {
3734
- const shiftedNormalized = crypto3.createHash("sha256").update(normalizeForHash(shiftedContent)).digest("hex");
3082
+ const shiftedNormalized = crypto2.createHash("sha256").update(normalizeForHash(shiftedContent)).digest("hex");
3735
3083
  if (anchor.normalized_hash != null && shiftedNormalized === anchor.normalized_hash) {
3736
3084
  if (autoHeal) {
3737
- const shiftedNewHash = crypto3.createHash("sha256").update(shiftedContent).digest("hex");
3085
+ const shiftedNewHash = crypto2.createHash("sha256").update(shiftedContent).digest("hex");
3738
3086
  db.run(
3739
3087
  "UPDATE anchors SET start_line = ?, end_line = ?, content_hash = ?, drifted = 0 WHERE id = ?",
3740
3088
  [mapping.currentStart, mapping.currentEnd, shiftedNewHash, anchor.id]
@@ -3934,15 +3282,15 @@ function computeLineShift(rootDir, filePath, fromCommit, originalStart, original
3934
3282
  };
3935
3283
  }
3936
3284
  function healAnchorInPurposeFile(rootDir, purposeFilePath, anchorFilePath, oldStart, oldEnd, newStart, newEnd) {
3937
- const absolutePurpose = path7.isAbsolute(purposeFilePath) ? purposeFilePath : path7.join(rootDir, purposeFilePath);
3938
- if (!fs6.existsSync(absolutePurpose)) return false;
3285
+ const absolutePurpose = path5.isAbsolute(purposeFilePath) ? purposeFilePath : path5.join(rootDir, purposeFilePath);
3286
+ if (!fs4.existsSync(absolutePurpose)) return false;
3939
3287
  try {
3940
- const content = fs6.readFileSync(absolutePurpose, "utf8");
3288
+ const content = fs4.readFileSync(absolutePurpose, "utf8");
3941
3289
  const oldAnchor = oldStart === oldEnd ? `${anchorFilePath}:${oldStart}` : `${anchorFilePath}:${oldStart}-${oldEnd}`;
3942
3290
  const newAnchor = newStart === newEnd ? `${anchorFilePath}:${newStart}` : `${anchorFilePath}:${newStart}-${newEnd}`;
3943
3291
  if (!content.includes(oldAnchor)) return false;
3944
3292
  const updated = content.replace(oldAnchor, newAnchor);
3945
- fs6.writeFileSync(absolutePurpose, updated, "utf8");
3293
+ fs4.writeFileSync(absolutePurpose, updated, "utf8");
3946
3294
  return true;
3947
3295
  } catch {
3948
3296
  return false;
@@ -3953,18 +3301,18 @@ function normalizeForHash(content) {
3953
3301
  }
3954
3302
  function computeAnchorHash(anchor, rootDir) {
3955
3303
  if (!rootDir) return { exact: null, normalized: null, normalizedContent: null };
3956
- const absolutePath = path7.isAbsolute(anchor.path) ? anchor.path : path7.join(rootDir, anchor.path);
3957
- if (!fs6.existsSync(absolutePath)) return { exact: null, normalized: null, normalizedContent: null };
3304
+ const absolutePath = path5.isAbsolute(anchor.path) ? anchor.path : path5.join(rootDir, anchor.path);
3305
+ if (!fs4.existsSync(absolutePath)) return { exact: null, normalized: null, normalizedContent: null };
3958
3306
  try {
3959
- const fileContent = fs6.readFileSync(absolutePath, "utf8");
3307
+ const fileContent = fs4.readFileSync(absolutePath, "utf8");
3960
3308
  const lines = fileContent.split("\n");
3961
3309
  const { startLine, endLine } = resolveAnchorLines(anchor);
3962
3310
  const startIdx = Math.max(0, startLine - 1);
3963
3311
  const endIdx = Math.min(lines.length, endLine);
3964
3312
  const sliceContent = lines.slice(startIdx, endIdx).join("\n");
3965
3313
  const normalizedContent = normalizeForHash(sliceContent);
3966
- const exact = crypto3.createHash("sha256").update(sliceContent).digest("hex");
3967
- const normalized = crypto3.createHash("sha256").update(normalizedContent).digest("hex");
3314
+ const exact = crypto2.createHash("sha256").update(sliceContent).digest("hex");
3315
+ const normalized = crypto2.createHash("sha256").update(normalizedContent).digest("hex");
3968
3316
  return { exact, normalized, normalizedContent };
3969
3317
  } catch {
3970
3318
  return { exact: null, normalized: null, normalizedContent: null };
@@ -4184,20 +3532,20 @@ function toLoreSummary(entry) {
4184
3532
  }
4185
3533
 
4186
3534
  // ../paradigm-mcp/src/utils/personas-loader.ts
4187
- import * as fs7 from "fs";
4188
- import * as path8 from "path";
4189
- import * as yaml5 from "js-yaml";
3535
+ import * as fs5 from "fs";
3536
+ import * as path6 from "path";
3537
+ import * as yaml4 from "js-yaml";
4190
3538
  var PERSONAS_ROOT = ".paradigm/personas";
4191
3539
  var INDEX_FILE = "index.yaml";
4192
3540
  async function loadPersonas(rootDir, filter) {
4193
- const personasDir = path8.join(rootDir, PERSONAS_ROOT);
4194
- if (!fs7.existsSync(personasDir)) return [];
4195
- const files = fs7.readdirSync(personasDir).filter((f) => f.endsWith(".persona"));
3541
+ const personasDir = path6.join(rootDir, PERSONAS_ROOT);
3542
+ if (!fs5.existsSync(personasDir)) return [];
3543
+ const files = fs5.readdirSync(personasDir).filter((f) => f.endsWith(".persona"));
4196
3544
  const personas = [];
4197
3545
  for (const file of files) {
4198
3546
  try {
4199
- const content = fs7.readFileSync(path8.join(personasDir, file), "utf8");
4200
- const persona = yaml5.load(content);
3547
+ const content = fs5.readFileSync(path6.join(personasDir, file), "utf8");
3548
+ const persona = yaml4.load(content);
4201
3549
  if (persona && persona.id) {
4202
3550
  personas.push(persona);
4203
3551
  }
@@ -4207,10 +3555,10 @@ async function loadPersonas(rootDir, filter) {
4207
3555
  return applyFilter(personas, filter);
4208
3556
  }
4209
3557
  async function loadPersona(rootDir, id) {
4210
- const filePath = path8.join(rootDir, PERSONAS_ROOT, `${id}.persona`);
4211
- if (!fs7.existsSync(filePath)) return null;
3558
+ const filePath = path6.join(rootDir, PERSONAS_ROOT, `${id}.persona`);
3559
+ if (!fs5.existsSync(filePath)) return null;
4212
3560
  try {
4213
- return yaml5.load(fs7.readFileSync(filePath, "utf8"));
3561
+ return yaml4.load(fs5.readFileSync(filePath, "utf8"));
4214
3562
  } catch {
4215
3563
  return null;
4216
3564
  }
@@ -4240,10 +3588,10 @@ function applyFilter(personas, filter) {
4240
3588
  return result;
4241
3589
  }
4242
3590
  async function createPersona(rootDir, data) {
4243
- const personasDir = path8.join(rootDir, PERSONAS_ROOT);
4244
- fs7.mkdirSync(personasDir, { recursive: true });
4245
- const filePath = path8.join(personasDir, `${data.id}.persona`);
4246
- if (fs7.existsSync(filePath)) {
3591
+ const personasDir = path6.join(rootDir, PERSONAS_ROOT);
3592
+ fs5.mkdirSync(personasDir, { recursive: true });
3593
+ const filePath = path6.join(personasDir, `${data.id}.persona`);
3594
+ if (fs5.existsSync(filePath)) {
4247
3595
  throw new Error(`Persona ${data.id} already exists`);
4248
3596
  }
4249
3597
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -4260,14 +3608,14 @@ async function createPersona(rootDir, data) {
4260
3608
  created: now,
4261
3609
  updated: now
4262
3610
  };
4263
- fs7.writeFileSync(filePath, yaml5.dump(persona, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false }));
3611
+ fs5.writeFileSync(filePath, yaml4.dump(persona, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false }));
4264
3612
  await rebuildPersonaIndex(rootDir);
4265
3613
  return data.id;
4266
3614
  }
4267
3615
  async function updatePersona(rootDir, id, partial) {
4268
3616
  const persona = await loadPersona(rootDir, id);
4269
3617
  if (!persona) return false;
4270
- const filePath = path8.join(rootDir, PERSONAS_ROOT, `${id}.persona`);
3618
+ const filePath = path6.join(rootDir, PERSONAS_ROOT, `${id}.persona`);
4271
3619
  const updated = {
4272
3620
  ...persona,
4273
3621
  ...partial,
@@ -4279,13 +3627,13 @@ async function updatePersona(rootDir, id, partial) {
4279
3627
  // immutable
4280
3628
  updated: (/* @__PURE__ */ new Date()).toISOString()
4281
3629
  };
4282
- fs7.writeFileSync(filePath, yaml5.dump(updated, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false }));
3630
+ fs5.writeFileSync(filePath, yaml4.dump(updated, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false }));
4283
3631
  await rebuildPersonaIndex(rootDir);
4284
3632
  return true;
4285
3633
  }
4286
3634
  async function deletePersona(rootDir, id) {
4287
- const filePath = path8.join(rootDir, PERSONAS_ROOT, `${id}.persona`);
4288
- if (!fs7.existsSync(filePath)) {
3635
+ const filePath = path6.join(rootDir, PERSONAS_ROOT, `${id}.persona`);
3636
+ if (!fs5.existsSync(filePath)) {
4289
3637
  return { deleted: false, warnings: [] };
4290
3638
  }
4291
3639
  const warnings = [];
@@ -4301,7 +3649,7 @@ async function deletePersona(rootDir, id) {
4301
3649
  }
4302
3650
  }
4303
3651
  }
4304
- fs7.unlinkSync(filePath);
3652
+ fs5.unlinkSync(filePath);
4305
3653
  await rebuildPersonaIndex(rootDir);
4306
3654
  return { deleted: true, warnings };
4307
3655
  }
@@ -4403,12 +3751,12 @@ async function validatePersona(rootDir, persona, deep = false) {
4403
3751
  }
4404
3752
  }
4405
3753
  if (deep) {
4406
- const portalPath = path8.join(rootDir, "portal.yaml");
3754
+ const portalPath = path6.join(rootDir, "portal.yaml");
4407
3755
  let portalGates = [];
4408
3756
  let portalRoutes = [];
4409
- if (fs7.existsSync(portalPath)) {
3757
+ if (fs5.existsSync(portalPath)) {
4410
3758
  try {
4411
- const portal = yaml5.load(fs7.readFileSync(portalPath, "utf8"));
3759
+ const portal = yaml4.load(fs5.readFileSync(portalPath, "utf8"));
4412
3760
  if (portal.gates && typeof portal.gates === "object") {
4413
3761
  portalGates = Object.keys(portal.gates);
4414
3762
  }
@@ -4459,10 +3807,10 @@ async function validatePersona(rootDir, persona, deep = false) {
4459
3807
  }
4460
3808
  }
4461
3809
  let allFlows = [];
4462
- const flowIndexPath = path8.join(rootDir, ".paradigm", "flow-index.json");
4463
- if (fs7.existsSync(flowIndexPath)) {
3810
+ const flowIndexPath = path6.join(rootDir, ".paradigm", "flow-index.json");
3811
+ if (fs5.existsSync(flowIndexPath)) {
4464
3812
  try {
4465
- const flowIndex = JSON.parse(fs7.readFileSync(flowIndexPath, "utf8"));
3813
+ const flowIndex = JSON.parse(fs5.readFileSync(flowIndexPath, "utf8"));
4466
3814
  allFlows = Object.keys(flowIndex.flows || {});
4467
3815
  } catch {
4468
3816
  }
@@ -4539,8 +3887,8 @@ async function detectSpawnCycle(rootDir, startId) {
4539
3887
  return visit(startId);
4540
3888
  }
4541
3889
  async function rebuildPersonaIndex(rootDir) {
4542
- const personasDir = path8.join(rootDir, PERSONAS_ROOT);
4543
- fs7.mkdirSync(personasDir, { recursive: true });
3890
+ const personasDir = path6.join(rootDir, PERSONAS_ROOT);
3891
+ fs5.mkdirSync(personasDir, { recursive: true });
4544
3892
  const personas = await loadPersonas(rootDir);
4545
3893
  const entries = {};
4546
3894
  const gateCoverage = {};
@@ -4579,10 +3927,10 @@ async function rebuildPersonaIndex(rootDir) {
4579
3927
  }
4580
3928
  }
4581
3929
  let uncoveredRoutes = [];
4582
- const portalPath = path8.join(rootDir, "portal.yaml");
4583
- if (fs7.existsSync(portalPath)) {
3930
+ const portalPath = path6.join(rootDir, "portal.yaml");
3931
+ if (fs5.existsSync(portalPath)) {
4584
3932
  try {
4585
- const portal = yaml5.load(fs7.readFileSync(portalPath, "utf8"));
3933
+ const portal = yaml4.load(fs5.readFileSync(portalPath, "utf8"));
4586
3934
  if (portal.routes && typeof portal.routes === "object") {
4587
3935
  const portalRoutes = Object.keys(portal.routes);
4588
3936
  uncoveredRoutes = portalRoutes.filter((pr) => {
@@ -4593,13 +3941,13 @@ async function rebuildPersonaIndex(rootDir) {
4593
3941
  }
4594
3942
  }
4595
3943
  const chains = {};
4596
- const chainsDir = path8.join(personasDir, "chains");
4597
- if (fs7.existsSync(chainsDir)) {
4598
- const chainFiles = fs7.readdirSync(chainsDir).filter((f) => f.endsWith(".yaml"));
3944
+ const chainsDir = path6.join(personasDir, "chains");
3945
+ if (fs5.existsSync(chainsDir)) {
3946
+ const chainFiles = fs5.readdirSync(chainsDir).filter((f) => f.endsWith(".yaml"));
4599
3947
  for (const file of chainFiles) {
4600
3948
  try {
4601
- const content = fs7.readFileSync(path8.join(chainsDir, file), "utf8");
4602
- const chain = yaml5.load(content);
3949
+ const content = fs5.readFileSync(path6.join(chainsDir, file), "utf8");
3950
+ const chain = yaml4.load(content);
4603
3951
  if (chain && chain.id) {
4604
3952
  const orderIds = chain.order.map((o) => o.persona);
4605
3953
  let totalSteps = 0;
@@ -4631,9 +3979,9 @@ async function rebuildPersonaIndex(rootDir) {
4631
3979
  route_coverage: routeCoverage,
4632
3980
  uncovered_routes: uncoveredRoutes
4633
3981
  };
4634
- fs7.writeFileSync(
4635
- path8.join(personasDir, INDEX_FILE),
4636
- yaml5.dump(index, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false })
3982
+ fs5.writeFileSync(
3983
+ path6.join(personasDir, INDEX_FILE),
3984
+ yaml4.dump(index, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false })
4637
3985
  );
4638
3986
  return index;
4639
3987
  }
@@ -4651,20 +3999,20 @@ async function getPersonaCoverage(rootDir) {
4651
3999
  }
4652
4000
  let portalGates = [];
4653
4001
  let portalRoutes = [];
4654
- const portalPath = path8.join(rootDir, "portal.yaml");
4655
- if (fs7.existsSync(portalPath)) {
4002
+ const portalPath = path6.join(rootDir, "portal.yaml");
4003
+ if (fs5.existsSync(portalPath)) {
4656
4004
  try {
4657
- const portal = yaml5.load(fs7.readFileSync(portalPath, "utf8"));
4005
+ const portal = yaml4.load(fs5.readFileSync(portalPath, "utf8"));
4658
4006
  if (portal.gates && typeof portal.gates === "object") portalGates = Object.keys(portal.gates);
4659
4007
  if (portal.routes && typeof portal.routes === "object") portalRoutes = Object.keys(portal.routes);
4660
4008
  } catch {
4661
4009
  }
4662
4010
  }
4663
4011
  let allFlows = [];
4664
- const flowIndexPath = path8.join(rootDir, ".paradigm", "flow-index.json");
4665
- if (fs7.existsSync(flowIndexPath)) {
4012
+ const flowIndexPath = path6.join(rootDir, ".paradigm", "flow-index.json");
4013
+ if (fs5.existsSync(flowIndexPath)) {
4666
4014
  try {
4667
- const flowIndex = JSON.parse(fs7.readFileSync(flowIndexPath, "utf8"));
4015
+ const flowIndex = JSON.parse(fs5.readFileSync(flowIndexPath, "utf8"));
4668
4016
  allFlows = Object.keys(flowIndex.flows || {});
4669
4017
  } catch {
4670
4018
  }
@@ -4713,8 +4061,8 @@ async function getAffectedPersonas(rootDir, symbol) {
4713
4061
  }
4714
4062
  return results;
4715
4063
  }
4716
- function deepGet(obj, path12) {
4717
- const parts = path12.split(/[.\[\]]+/).filter(Boolean);
4064
+ function deepGet(obj, path10) {
4065
+ const parts = path10.split(/[.\[\]]+/).filter(Boolean);
4718
4066
  let current = obj;
4719
4067
  for (const part of parts) {
4720
4068
  if (current == null || typeof current !== "object") return void 0;
@@ -4883,22 +4231,22 @@ async function validateAgainstSentinel(persona, options = {}) {
4883
4231
  }
4884
4232
 
4885
4233
  // ../paradigm-mcp/src/utils/protocol-loader.ts
4886
- import * as fs8 from "fs";
4887
- import * as path9 from "path";
4888
- import * as yaml6 from "js-yaml";
4234
+ import * as fs6 from "fs";
4235
+ import * as path7 from "path";
4236
+ import * as yaml5 from "js-yaml";
4889
4237
  var PROTOCOLS_DIR = ".paradigm/protocols";
4890
4238
  var INDEX_FILE2 = "index.yaml";
4891
4239
  async function loadProtocols(rootDir) {
4892
- const protocolsDir = path9.join(rootDir, PROTOCOLS_DIR);
4893
- if (!fs8.existsSync(protocolsDir)) {
4240
+ const protocolsDir = path7.join(rootDir, PROTOCOLS_DIR);
4241
+ if (!fs6.existsSync(protocolsDir)) {
4894
4242
  return [];
4895
4243
  }
4896
- const files = fs8.readdirSync(protocolsDir).filter((f) => f.endsWith(".protocol")).sort();
4244
+ const files = fs6.readdirSync(protocolsDir).filter((f) => f.endsWith(".protocol")).sort();
4897
4245
  const protocols = [];
4898
4246
  for (const file of files) {
4899
4247
  try {
4900
- const content = fs8.readFileSync(path9.join(protocolsDir, file), "utf8");
4901
- const protocol = yaml6.load(content);
4248
+ const content = fs6.readFileSync(path7.join(protocolsDir, file), "utf8");
4249
+ const protocol = yaml5.load(content);
4902
4250
  if (protocol?.id && protocol?.name) {
4903
4251
  protocols.push(protocol);
4904
4252
  }
@@ -4909,11 +4257,11 @@ async function loadProtocols(rootDir) {
4909
4257
  }
4910
4258
  async function loadProtocol(rootDir, id) {
4911
4259
  const slug = id.replace(/^P-/, "");
4912
- const filePath = path9.join(rootDir, PROTOCOLS_DIR, `${slug}.protocol`);
4913
- if (fs8.existsSync(filePath)) {
4260
+ const filePath = path7.join(rootDir, PROTOCOLS_DIR, `${slug}.protocol`);
4261
+ if (fs6.existsSync(filePath)) {
4914
4262
  try {
4915
- const content = fs8.readFileSync(filePath, "utf8");
4916
- return yaml6.load(content);
4263
+ const content = fs6.readFileSync(filePath, "utf8");
4264
+ return yaml5.load(content);
4917
4265
  } catch {
4918
4266
  return null;
4919
4267
  }
@@ -4922,13 +4270,13 @@ async function loadProtocol(rootDir, id) {
4922
4270
  return protocols.find((p) => p.id === id) || null;
4923
4271
  }
4924
4272
  async function loadProtocolIndex(rootDir) {
4925
- const indexPath = path9.join(rootDir, PROTOCOLS_DIR, INDEX_FILE2);
4926
- if (!fs8.existsSync(indexPath)) {
4273
+ const indexPath = path7.join(rootDir, PROTOCOLS_DIR, INDEX_FILE2);
4274
+ if (!fs6.existsSync(indexPath)) {
4927
4275
  return null;
4928
4276
  }
4929
4277
  try {
4930
- const content = fs8.readFileSync(indexPath, "utf8");
4931
- return yaml6.load(content);
4278
+ const content = fs6.readFileSync(indexPath, "utf8");
4279
+ return yaml5.load(content);
4932
4280
  } catch {
4933
4281
  return null;
4934
4282
  }
@@ -4979,9 +4327,9 @@ async function searchProtocols(rootDir, task, limit = 3) {
4979
4327
  return scored.slice(0, limit);
4980
4328
  }
4981
4329
  async function recordProtocol(rootDir, protocol) {
4982
- const protocolsDir = path9.join(rootDir, PROTOCOLS_DIR);
4983
- if (!fs8.existsSync(protocolsDir)) {
4984
- fs8.mkdirSync(protocolsDir, { recursive: true });
4330
+ const protocolsDir = path7.join(rootDir, PROTOCOLS_DIR);
4331
+ if (!fs6.existsSync(protocolsDir)) {
4332
+ fs6.mkdirSync(protocolsDir, { recursive: true });
4985
4333
  }
4986
4334
  const slug = slugify(protocol.name);
4987
4335
  const id = `P-${slug}`;
@@ -5001,8 +4349,8 @@ async function recordProtocol(rootDir, protocol) {
5001
4349
  verified_by: protocol.verified_by || "claude-opus-4-6",
5002
4350
  status: "current"
5003
4351
  };
5004
- const filePath = path9.join(protocolsDir, `${slug}.protocol`);
5005
- fs8.writeFileSync(filePath, yaml6.dump(full, { lineWidth: -1, noRefs: true }), "utf8");
4352
+ const filePath = path7.join(protocolsDir, `${slug}.protocol`);
4353
+ fs6.writeFileSync(filePath, yaml5.dump(full, { lineWidth: -1, noRefs: true }), "utf8");
5006
4354
  return id;
5007
4355
  }
5008
4356
  async function updateProtocol(rootDir, id, partial, refresh = false) {
@@ -5022,20 +4370,20 @@ async function updateProtocol(rootDir, id, partial, refresh = false) {
5022
4370
  protocol.verified_by = partial.verified_by || "claude-opus-4-6";
5023
4371
  }
5024
4372
  const slug = id.replace(/^P-/, "");
5025
- const filePath = path9.join(rootDir, PROTOCOLS_DIR, `${slug}.protocol`);
5026
- fs8.writeFileSync(filePath, yaml6.dump(protocol, { lineWidth: -1, noRefs: true }), "utf8");
4373
+ const filePath = path7.join(rootDir, PROTOCOLS_DIR, `${slug}.protocol`);
4374
+ fs6.writeFileSync(filePath, yaml5.dump(protocol, { lineWidth: -1, noRefs: true }), "utf8");
5027
4375
  return true;
5028
4376
  }
5029
4377
  function validateProtocol(rootDir, protocol) {
5030
4378
  const issues = [];
5031
4379
  let status = "current";
5032
4380
  if (protocol.exemplar) {
5033
- const exemplarPath = path9.join(rootDir, protocol.exemplar);
5034
- if (!fs8.existsSync(exemplarPath)) {
4381
+ const exemplarPath = path7.join(rootDir, protocol.exemplar);
4382
+ if (!fs6.existsSync(exemplarPath)) {
5035
4383
  issues.push(`Exemplar missing: ${protocol.exemplar}`);
5036
4384
  status = "broken";
5037
4385
  } else {
5038
- const stat = fs8.statSync(exemplarPath);
4386
+ const stat = fs6.statSync(exemplarPath);
5039
4387
  if (stat.mtime.toISOString() > protocol.last_verified) {
5040
4388
  issues.push(`Exemplar modified since last verified: ${protocol.exemplar}`);
5041
4389
  if (status !== "broken") status = "stale";
@@ -5044,15 +4392,15 @@ function validateProtocol(rootDir, protocol) {
5044
4392
  }
5045
4393
  for (const step of protocol.steps) {
5046
4394
  if (step.template_from) {
5047
- const templatePath = path9.join(rootDir, step.template_from);
5048
- if (!fs8.existsSync(templatePath)) {
4395
+ const templatePath = path7.join(rootDir, step.template_from);
4396
+ if (!fs6.existsSync(templatePath)) {
5049
4397
  issues.push(`Template file missing: ${step.template_from}`);
5050
4398
  status = "broken";
5051
4399
  }
5052
4400
  }
5053
4401
  if (step.action === "modify" && step.target) {
5054
- const targetPath = path9.join(rootDir, step.target);
5055
- if (!step.target.includes("{") && !fs8.existsSync(targetPath)) {
4402
+ const targetPath = path7.join(rootDir, step.target);
4403
+ if (!step.target.includes("{") && !fs6.existsSync(targetPath)) {
5056
4404
  issues.push(`Modify target missing: ${step.target}`);
5057
4405
  status = "broken";
5058
4406
  }
@@ -5071,9 +4419,9 @@ async function rebuildProtocolIndex(rootDir) {
5071
4419
  if (protocol.status !== validation.status) {
5072
4420
  protocol.status = validation.status;
5073
4421
  const slug = protocol.id.replace(/^P-/, "");
5074
- const filePath = path9.join(rootDir, PROTOCOLS_DIR, `${slug}.protocol`);
5075
- if (fs8.existsSync(filePath)) {
5076
- fs8.writeFileSync(filePath, yaml6.dump(protocol, { lineWidth: -1, noRefs: true }), "utf8");
4422
+ const filePath = path7.join(rootDir, PROTOCOLS_DIR, `${slug}.protocol`);
4423
+ if (fs6.existsSync(filePath)) {
4424
+ fs6.writeFileSync(filePath, yaml5.dump(protocol, { lineWidth: -1, noRefs: true }), "utf8");
5077
4425
  }
5078
4426
  }
5079
4427
  switch (validation.status) {
@@ -5107,13 +4455,13 @@ async function rebuildProtocolIndex(rootDir) {
5107
4455
  broken
5108
4456
  }
5109
4457
  };
5110
- const protocolsDir = path9.join(rootDir, PROTOCOLS_DIR);
4458
+ const protocolsDir = path7.join(rootDir, PROTOCOLS_DIR);
5111
4459
  if (protocols.length > 0) {
5112
- if (!fs8.existsSync(protocolsDir)) {
5113
- fs8.mkdirSync(protocolsDir, { recursive: true });
4460
+ if (!fs6.existsSync(protocolsDir)) {
4461
+ fs6.mkdirSync(protocolsDir, { recursive: true });
5114
4462
  }
5115
- const indexPath = path9.join(protocolsDir, INDEX_FILE2);
5116
- fs8.writeFileSync(indexPath, yaml6.dump(index, { lineWidth: -1, noRefs: true }), "utf8");
4463
+ const indexPath = path7.join(protocolsDir, INDEX_FILE2);
4464
+ fs6.writeFileSync(indexPath, yaml5.dump(index, { lineWidth: -1, noRefs: true }), "utf8");
5117
4465
  }
5118
4466
  return index;
5119
4467
  }
@@ -5121,21 +4469,21 @@ function detectProtocolSuggestion(rootDir, filesCreated, filesModified) {
5121
4469
  if (!filesCreated || filesCreated.length < 2) return null;
5122
4470
  const dirGroups = {};
5123
4471
  for (const file of filesCreated) {
5124
- const dir = path9.dirname(file);
4472
+ const dir = path7.dirname(file);
5125
4473
  if (!dirGroups[dir]) dirGroups[dir] = [];
5126
4474
  dirGroups[dir].push(file);
5127
4475
  }
5128
4476
  for (const [dir, created] of Object.entries(dirGroups)) {
5129
4477
  if (created.length < 2) continue;
5130
- const absDir = path9.join(rootDir, dir);
5131
- if (!fs8.existsSync(absDir)) continue;
5132
- const existing = fs8.readdirSync(absDir).filter((f) => {
5133
- const ext = path9.extname(f);
4478
+ const absDir = path7.join(rootDir, dir);
4479
+ if (!fs6.existsSync(absDir)) continue;
4480
+ const existing = fs6.readdirSync(absDir).filter((f) => {
4481
+ const ext = path7.extname(f);
5134
4482
  return [".ts", ".tsx", ".js", ".jsx", ".rs", ".py"].includes(ext);
5135
4483
  });
5136
- const preExisting = existing.filter((f) => !created.some((c) => path9.basename(c) === f));
4484
+ const preExisting = existing.filter((f) => !created.some((c) => path7.basename(c) === f));
5137
4485
  if (preExisting.length > 0) {
5138
- const exemplar = path9.join(dir, preExisting[0]);
4486
+ const exemplar = path7.join(dir, preExisting[0]);
5139
4487
  const steps = [
5140
4488
  ...created.map((f) => ({ action: "create", target: f })),
5141
4489
  ...filesModified.map((f) => ({ action: "modify", target: f }))
@@ -5143,7 +4491,7 @@ function detectProtocolSuggestion(rootDir, filesCreated, filesModified) {
5143
4491
  return {
5144
4492
  hint: `This session created ${created.length} new files in ${dir}/ following existing patterns. Consider recording a protocol.`,
5145
4493
  draft: {
5146
- name: `Add a ${path9.basename(dir).replace(/s$/, "")}`,
4494
+ name: `Add a ${path7.basename(dir).replace(/s$/, "")}`,
5147
4495
  exemplar,
5148
4496
  steps
5149
4497
  }
@@ -5218,9 +4566,9 @@ function slugify(name) {
5218
4566
  }
5219
4567
 
5220
4568
  // ../paradigm-mcp/src/utils/university-loader.ts
5221
- import * as fs9 from "fs";
5222
- import * as path10 from "path";
5223
- import * as yaml7 from "js-yaml";
4569
+ import * as fs7 from "fs";
4570
+ import * as path8 from "path";
4571
+ import * as yaml6 from "js-yaml";
5224
4572
  var UNIVERSITY_DIR = ".paradigm/university";
5225
4573
  var CONTENT_DIR = "content";
5226
4574
  var NOTES_DIR = "notes";
@@ -5261,13 +4609,13 @@ var DEFAULT_CONFIG = {
5261
4609
  }
5262
4610
  };
5263
4611
  function loadUniversityConfig(rootDir) {
5264
- const configPath = path10.join(rootDir, UNIVERSITY_DIR, CONFIG_FILE);
5265
- if (!fs9.existsSync(configPath)) {
4612
+ const configPath = path8.join(rootDir, UNIVERSITY_DIR, CONFIG_FILE);
4613
+ if (!fs7.existsSync(configPath)) {
5266
4614
  return { ...DEFAULT_CONFIG };
5267
4615
  }
5268
4616
  try {
5269
- const raw = fs9.readFileSync(configPath, "utf8");
5270
- const data = yaml7.load(raw);
4617
+ const raw = fs7.readFileSync(configPath, "utf8");
4618
+ const data = yaml6.load(raw);
5271
4619
  if (!data) return { ...DEFAULT_CONFIG };
5272
4620
  return {
5273
4621
  branding: { ...DEFAULT_BRANDING, ...data.branding || {} },
@@ -5288,11 +4636,11 @@ function loadUniversityConfig(rootDir) {
5288
4636
  }
5289
4637
  }
5290
4638
  function loadUniversityIndex(rootDir) {
5291
- const indexPath = path10.join(rootDir, UNIVERSITY_DIR, INDEX_FILE3);
5292
- if (!fs9.existsSync(indexPath)) return null;
4639
+ const indexPath = path8.join(rootDir, UNIVERSITY_DIR, INDEX_FILE3);
4640
+ if (!fs7.existsSync(indexPath)) return null;
5293
4641
  try {
5294
- const raw = fs9.readFileSync(indexPath, "utf8");
5295
- return yaml7.load(raw);
4642
+ const raw = fs7.readFileSync(indexPath, "utf8");
4643
+ return yaml6.load(raw);
5296
4644
  } catch {
5297
4645
  return null;
5298
4646
  }
@@ -5301,14 +4649,14 @@ function parseFrontmatter(content) {
5301
4649
  const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
5302
4650
  if (!match) return null;
5303
4651
  try {
5304
- const frontmatter = yaml7.load(match[1]);
4652
+ const frontmatter = yaml6.load(match[1]);
5305
4653
  return { frontmatter, body: match[2].trim() };
5306
4654
  } catch {
5307
4655
  return null;
5308
4656
  }
5309
4657
  }
5310
4658
  function serializeFrontmatter(frontmatter, body) {
5311
- const fm = yaml7.dump(frontmatter, { lineWidth: -1, noRefs: true, sortKeys: false });
4659
+ const fm = yaml6.dump(frontmatter, { lineWidth: -1, noRefs: true, sortKeys: false });
5312
4660
  return `---
5313
4661
  ${fm}---
5314
4662
 
@@ -5319,7 +4667,7 @@ function loadNote(rootDir, id) {
5319
4667
  const filePath = resolveContentFile(rootDir, id, ".md");
5320
4668
  if (!filePath) return null;
5321
4669
  try {
5322
- const raw = fs9.readFileSync(filePath, "utf8");
4670
+ const raw = fs7.readFileSync(filePath, "utf8");
5323
4671
  const parsed = parseFrontmatter(raw);
5324
4672
  if (!parsed) return null;
5325
4673
  const fm = parsed.frontmatter;
@@ -5330,19 +4678,19 @@ function loadNote(rootDir, id) {
5330
4678
  }
5331
4679
  function saveNote(rootDir, frontmatter, body) {
5332
4680
  const subdir = frontmatter.type === "policy" ? POLICIES_DIR : NOTES_DIR;
5333
- const dir = path10.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR, subdir);
5334
- fs9.mkdirSync(dir, { recursive: true });
5335
- const filePath = path10.join(dir, `${frontmatter.id}.md`);
4681
+ const dir = path8.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR, subdir);
4682
+ fs7.mkdirSync(dir, { recursive: true });
4683
+ const filePath = path8.join(dir, `${frontmatter.id}.md`);
5336
4684
  const content = serializeFrontmatter(frontmatter, body);
5337
- fs9.writeFileSync(filePath, content, "utf8");
4685
+ fs7.writeFileSync(filePath, content, "utf8");
5338
4686
  return filePath;
5339
4687
  }
5340
4688
  function loadQuiz(rootDir, id) {
5341
4689
  const filePath = resolveContentFile(rootDir, id, ".yaml");
5342
4690
  if (!filePath) return null;
5343
4691
  try {
5344
- const raw = fs9.readFileSync(filePath, "utf8");
5345
- const data = yaml7.load(raw);
4692
+ const raw = fs7.readFileSync(filePath, "utf8");
4693
+ const data = yaml6.load(raw);
5346
4694
  if (!data || !data.id) return null;
5347
4695
  return normalizeQuiz(data);
5348
4696
  } catch {
@@ -5350,18 +4698,18 @@ function loadQuiz(rootDir, id) {
5350
4698
  }
5351
4699
  }
5352
4700
  function saveQuiz(rootDir, quiz) {
5353
- const dir = path10.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR, QUIZZES_DIR);
5354
- fs9.mkdirSync(dir, { recursive: true });
5355
- const filePath = path10.join(dir, `${quiz.id}.yaml`);
5356
- fs9.writeFileSync(filePath, yaml7.dump(quiz, { lineWidth: -1, noRefs: true }), "utf8");
4701
+ const dir = path8.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR, QUIZZES_DIR);
4702
+ fs7.mkdirSync(dir, { recursive: true });
4703
+ const filePath = path8.join(dir, `${quiz.id}.yaml`);
4704
+ fs7.writeFileSync(filePath, yaml6.dump(quiz, { lineWidth: -1, noRefs: true }), "utf8");
5357
4705
  return filePath;
5358
4706
  }
5359
4707
  function loadPath(rootDir, id) {
5360
4708
  const filePath = resolveContentFile(rootDir, id, ".yaml");
5361
4709
  if (!filePath) return null;
5362
4710
  try {
5363
- const raw = fs9.readFileSync(filePath, "utf8");
5364
- const data = yaml7.load(raw);
4711
+ const raw = fs7.readFileSync(filePath, "utf8");
4712
+ const data = yaml6.load(raw);
5365
4713
  if (!data || !data.id) return null;
5366
4714
  return data;
5367
4715
  } catch {
@@ -5369,22 +4717,22 @@ function loadPath(rootDir, id) {
5369
4717
  }
5370
4718
  }
5371
4719
  function savePath(rootDir, lp) {
5372
- const dir = path10.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR, PATHS_DIR);
5373
- fs9.mkdirSync(dir, { recursive: true });
5374
- const filePath = path10.join(dir, `${lp.id}.yaml`);
5375
- fs9.writeFileSync(filePath, yaml7.dump(lp, { lineWidth: -1, noRefs: true }), "utf8");
4720
+ const dir = path8.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR, PATHS_DIR);
4721
+ fs7.mkdirSync(dir, { recursive: true });
4722
+ const filePath = path8.join(dir, `${lp.id}.yaml`);
4723
+ fs7.writeFileSync(filePath, yaml6.dump(lp, { lineWidth: -1, noRefs: true }), "utf8");
5376
4724
  return filePath;
5377
4725
  }
5378
4726
  function loadDiplomas(rootDir, filter) {
5379
- const dir = path10.join(rootDir, UNIVERSITY_DIR, DIPLOMAS_DIR);
5380
- if (!fs9.existsSync(dir)) return [];
4727
+ const dir = path8.join(rootDir, UNIVERSITY_DIR, DIPLOMAS_DIR);
4728
+ if (!fs7.existsSync(dir)) return [];
5381
4729
  const results = [];
5382
4730
  try {
5383
- const files = fs9.readdirSync(dir).filter((f) => f.endsWith(".yaml"));
4731
+ const files = fs7.readdirSync(dir).filter((f) => f.endsWith(".yaml"));
5384
4732
  for (const file of files) {
5385
4733
  try {
5386
- const raw = fs9.readFileSync(path10.join(dir, file), "utf8");
5387
- const diploma = yaml7.load(raw);
4734
+ const raw = fs7.readFileSync(path8.join(dir, file), "utf8");
4735
+ const diploma = yaml6.load(raw);
5388
4736
  if (!diploma || !diploma.id) continue;
5389
4737
  if (filter?.student && diploma.student !== filter.student) continue;
5390
4738
  if (filter?.type && diploma.type !== filter.type) continue;
@@ -5397,10 +4745,10 @@ function loadDiplomas(rootDir, filter) {
5397
4745
  return results.sort((a, b) => b.earnedAt.localeCompare(a.earnedAt));
5398
4746
  }
5399
4747
  function saveDiploma(rootDir, diploma) {
5400
- const dir = path10.join(rootDir, UNIVERSITY_DIR, DIPLOMAS_DIR);
5401
- fs9.mkdirSync(dir, { recursive: true });
5402
- const filePath = path10.join(dir, `${diploma.id}.yaml`);
5403
- fs9.writeFileSync(filePath, yaml7.dump(diploma, { lineWidth: -1, noRefs: true }), "utf8");
4748
+ const dir = path8.join(rootDir, UNIVERSITY_DIR, DIPLOMAS_DIR);
4749
+ fs7.mkdirSync(dir, { recursive: true });
4750
+ const filePath = path8.join(dir, `${diploma.id}.yaml`);
4751
+ fs7.writeFileSync(filePath, yaml6.dump(diploma, { lineWidth: -1, noRefs: true }), "utf8");
5404
4752
  return filePath;
5405
4753
  }
5406
4754
  function searchContent(rootDir, filter) {
@@ -5446,16 +4794,16 @@ function searchContent(rootDir, filter) {
5446
4794
  return results.slice(0, limit);
5447
4795
  }
5448
4796
  function rebuildUniversityIndex(rootDir) {
5449
- const uniDir = path10.join(rootDir, UNIVERSITY_DIR);
5450
- const contentDir = path10.join(uniDir, CONTENT_DIR);
4797
+ const uniDir = path8.join(rootDir, UNIVERSITY_DIR);
4798
+ const contentDir = path8.join(uniDir, CONTENT_DIR);
5451
4799
  const entries = [];
5452
4800
  for (const subdir of [NOTES_DIR, POLICIES_DIR]) {
5453
- const dir = path10.join(contentDir, subdir);
5454
- if (!fs9.existsSync(dir)) continue;
4801
+ const dir = path8.join(contentDir, subdir);
4802
+ if (!fs7.existsSync(dir)) continue;
5455
4803
  try {
5456
- for (const file of fs9.readdirSync(dir).filter((f) => f.endsWith(".md"))) {
4804
+ for (const file of fs7.readdirSync(dir).filter((f) => f.endsWith(".md"))) {
5457
4805
  try {
5458
- const raw = fs9.readFileSync(path10.join(dir, file), "utf8");
4806
+ const raw = fs7.readFileSync(path8.join(dir, file), "utf8");
5459
4807
  const parsed = parseFrontmatter(raw);
5460
4808
  if (!parsed) continue;
5461
4809
  const fm = parsed.frontmatter;
@@ -5478,13 +4826,13 @@ function rebuildUniversityIndex(rootDir) {
5478
4826
  } catch {
5479
4827
  }
5480
4828
  }
5481
- const quizDir = path10.join(contentDir, QUIZZES_DIR);
5482
- if (fs9.existsSync(quizDir)) {
4829
+ const quizDir = path8.join(contentDir, QUIZZES_DIR);
4830
+ if (fs7.existsSync(quizDir)) {
5483
4831
  try {
5484
- for (const file of fs9.readdirSync(quizDir).filter((f) => f.endsWith(".yaml"))) {
4832
+ for (const file of fs7.readdirSync(quizDir).filter((f) => f.endsWith(".yaml"))) {
5485
4833
  try {
5486
- const raw = fs9.readFileSync(path10.join(quizDir, file), "utf8");
5487
- const quiz = yaml7.load(raw);
4834
+ const raw = fs7.readFileSync(path8.join(quizDir, file), "utf8");
4835
+ const quiz = yaml6.load(raw);
5488
4836
  if (!quiz || !quiz.id) continue;
5489
4837
  entries.push({
5490
4838
  id: quiz.id,
@@ -5505,13 +4853,13 @@ function rebuildUniversityIndex(rootDir) {
5505
4853
  } catch {
5506
4854
  }
5507
4855
  }
5508
- const pathDir = path10.join(contentDir, PATHS_DIR);
5509
- if (fs9.existsSync(pathDir)) {
4856
+ const pathDir = path8.join(contentDir, PATHS_DIR);
4857
+ if (fs7.existsSync(pathDir)) {
5510
4858
  try {
5511
- for (const file of fs9.readdirSync(pathDir).filter((f) => f.endsWith(".yaml"))) {
4859
+ for (const file of fs7.readdirSync(pathDir).filter((f) => f.endsWith(".yaml"))) {
5512
4860
  try {
5513
- const raw = fs9.readFileSync(path10.join(pathDir, file), "utf8");
5514
- const lp = yaml7.load(raw);
4861
+ const raw = fs7.readFileSync(path8.join(pathDir, file), "utf8");
4862
+ const lp = yaml6.load(raw);
5515
4863
  if (!lp || !lp.id) continue;
5516
4864
  entries.push({
5517
4865
  id: lp.id,
@@ -5532,10 +4880,10 @@ function rebuildUniversityIndex(rootDir) {
5532
4880
  }
5533
4881
  }
5534
4882
  let diplomaCount = 0;
5535
- const diplomaDir = path10.join(uniDir, DIPLOMAS_DIR);
5536
- if (fs9.existsSync(diplomaDir)) {
4883
+ const diplomaDir = path8.join(uniDir, DIPLOMAS_DIR);
4884
+ if (fs7.existsSync(diplomaDir)) {
5537
4885
  try {
5538
- diplomaCount = fs9.readdirSync(diplomaDir).filter((f) => f.endsWith(".yaml")).length;
4886
+ diplomaCount = fs7.readdirSync(diplomaDir).filter((f) => f.endsWith(".yaml")).length;
5539
4887
  } catch {
5540
4888
  }
5541
4889
  }
@@ -5546,9 +4894,9 @@ function rebuildUniversityIndex(rootDir) {
5546
4894
  entries,
5547
4895
  diplomaCount
5548
4896
  };
5549
- fs9.mkdirSync(uniDir, { recursive: true });
5550
- const indexPath = path10.join(uniDir, INDEX_FILE3);
5551
- fs9.writeFileSync(indexPath, yaml7.dump(index, { lineWidth: -1, noRefs: true }), "utf8");
4897
+ fs7.mkdirSync(uniDir, { recursive: true });
4898
+ const indexPath = path8.join(uniDir, INDEX_FILE3);
4899
+ fs7.writeFileSync(indexPath, yaml6.dump(index, { lineWidth: -1, noRefs: true }), "utf8");
5552
4900
  return index;
5553
4901
  }
5554
4902
  function validateUniversityContent(rootDir, options) {
@@ -5740,10 +5088,10 @@ function getOnboardingSequence(rootDir, student) {
5740
5088
  };
5741
5089
  }
5742
5090
  function resolveContentFile(rootDir, id, ext) {
5743
- const contentDir = path10.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR);
5091
+ const contentDir = path8.join(rootDir, UNIVERSITY_DIR, CONTENT_DIR);
5744
5092
  for (const subdir of [NOTES_DIR, POLICIES_DIR, QUIZZES_DIR, PATHS_DIR]) {
5745
- const filePath = path10.join(contentDir, subdir, `${id}${ext}`);
5746
- if (fs9.existsSync(filePath)) return filePath;
5093
+ const filePath = path8.join(contentDir, subdir, `${id}${ext}`);
5094
+ if (fs7.existsSync(filePath)) return filePath;
5747
5095
  }
5748
5096
  return null;
5749
5097
  }
@@ -5775,10 +5123,10 @@ function normalizeQuiz(quiz) {
5775
5123
  }
5776
5124
  function loadKnownSymbols(rootDir) {
5777
5125
  const symbols = /* @__PURE__ */ new Set();
5778
- const scanIndexPath = path10.join(rootDir, ".paradigm", "scan-index.json");
5779
- if (!fs9.existsSync(scanIndexPath)) return symbols;
5126
+ const scanIndexPath = path8.join(rootDir, ".paradigm", "scan-index.json");
5127
+ if (!fs7.existsSync(scanIndexPath)) return symbols;
5780
5128
  try {
5781
- const raw = fs9.readFileSync(scanIndexPath, "utf8");
5129
+ const raw = fs7.readFileSync(scanIndexPath, "utf8");
5782
5130
  const index = JSON.parse(raw);
5783
5131
  if (index.symbols && Array.isArray(index.symbols)) {
5784
5132
  for (const sym of index.symbols) {
@@ -5810,17 +5158,17 @@ function isContentStale(rootDir, entry, _symbol) {
5810
5158
  if (!entry.updated) return false;
5811
5159
  const contentUpdated = new Date(entry.updated).getTime();
5812
5160
  if (isNaN(contentUpdated)) return false;
5813
- const scanIndexPath = path10.join(rootDir, ".paradigm", "scan-index.json");
5814
- if (!fs9.existsSync(scanIndexPath)) return false;
5161
+ const scanIndexPath = path8.join(rootDir, ".paradigm", "scan-index.json");
5162
+ if (!fs7.existsSync(scanIndexPath)) return false;
5815
5163
  try {
5816
- const raw = fs9.readFileSync(scanIndexPath, "utf8");
5164
+ const raw = fs7.readFileSync(scanIndexPath, "utf8");
5817
5165
  const index = JSON.parse(raw);
5818
5166
  if (index.symbols && Array.isArray(index.symbols)) {
5819
5167
  for (const sym of index.symbols) {
5820
5168
  if (sym.symbol === _symbol && sym.filePath) {
5821
- const purposePath = path10.join(rootDir, sym.filePath);
5822
- if (fs9.existsSync(purposePath)) {
5823
- const stat = fs9.statSync(purposePath);
5169
+ const purposePath = path8.join(rootDir, sym.filePath);
5170
+ if (fs7.existsSync(purposePath)) {
5171
+ const stat = fs7.statSync(purposePath);
5824
5172
  if (stat.mtime.getTime() > contentUpdated) {
5825
5173
  return true;
5826
5174
  }
@@ -5935,10 +5283,10 @@ async function rebuildStaticFiles(rootDir, ctx) {
5935
5283
  } else {
5936
5284
  aggregation = await aggregateFromDirectory(rootDir);
5937
5285
  }
5938
- const projectName = ctx?.projectName || path11.basename(rootDir);
5939
- const paradigmDir = path11.join(rootDir, ".paradigm");
5940
- if (!fs10.existsSync(paradigmDir)) {
5941
- fs10.mkdirSync(paradigmDir, { recursive: true });
5286
+ const projectName = ctx?.projectName || path9.basename(rootDir);
5287
+ const paradigmDir = path9.join(rootDir, ".paradigm");
5288
+ if (!fs8.existsSync(paradigmDir)) {
5289
+ fs8.mkdirSync(paradigmDir, { recursive: true });
5942
5290
  }
5943
5291
  const scanIndex = generateScanIndex(
5944
5292
  {
@@ -5948,22 +5296,22 @@ async function rebuildStaticFiles(rootDir, ctx) {
5948
5296
  },
5949
5297
  { projectName }
5950
5298
  );
5951
- const scanIndexPath = path11.join(paradigmDir, "scan-index.json");
5952
- fs10.writeFileSync(scanIndexPath, serializeScanIndex(scanIndex), "utf8");
5299
+ const scanIndexPath = path9.join(paradigmDir, "scan-index.json");
5300
+ fs8.writeFileSync(scanIndexPath, serializeScanIndex(scanIndex), "utf8");
5953
5301
  filesWritten.push(".paradigm/scan-index.json");
5954
5302
  const navigatorData = buildNavigatorData(rootDir, aggregation);
5955
- const navigatorPath = path11.join(paradigmDir, "navigator.yaml");
5956
- fs10.writeFileSync(
5303
+ const navigatorPath = path9.join(paradigmDir, "navigator.yaml");
5304
+ fs8.writeFileSync(
5957
5305
  navigatorPath,
5958
- yaml8.dump(navigatorData, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false }),
5306
+ yaml7.dump(navigatorData, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false }),
5959
5307
  "utf8"
5960
5308
  );
5961
5309
  filesWritten.push(".paradigm/navigator.yaml");
5962
5310
  const flowIndex = generateFlowIndex(rootDir, aggregation.purposeFiles);
5963
5311
  let flowCount = 0;
5964
5312
  if (flowIndex && Object.keys(flowIndex.flows).length > 0) {
5965
- const flowIndexPath = path11.join(paradigmDir, "flow-index.json");
5966
- fs10.writeFileSync(flowIndexPath, JSON.stringify(flowIndex, null, 2), "utf8");
5313
+ const flowIndexPath = path9.join(paradigmDir, "flow-index.json");
5314
+ fs8.writeFileSync(flowIndexPath, JSON.stringify(flowIndex, null, 2), "utf8");
5967
5315
  filesWritten.push(".paradigm/flow-index.json");
5968
5316
  flowCount = Object.keys(flowIndex.flows).length;
5969
5317
  }
@@ -6006,8 +5354,8 @@ async function rebuildStaticFiles(rootDir, ctx) {
6006
5354
  }
6007
5355
  let universityStats;
6008
5356
  try {
6009
- const uniDir = path11.join(rootDir, ".paradigm", "university");
6010
- if (fs10.existsSync(uniDir)) {
5357
+ const uniDir = path9.join(rootDir, ".paradigm", "university");
5358
+ if (fs8.existsSync(uniDir)) {
6011
5359
  const uniIndex = rebuildUniversityIndex(rootDir);
6012
5360
  if (uniIndex.totalContent > 0 || uniIndex.diplomaCount > 0) {
6013
5361
  universityStats = {
@@ -6105,7 +5453,7 @@ function buildNavigatorData(rootDir, aggregation) {
6105
5453
  function buildStructure(rootDir) {
6106
5454
  const structure = {};
6107
5455
  for (const [category, patterns] of Object.entries(DIRECTORY_PATTERNS)) {
6108
- const existingPaths = patterns.filter((p) => fs10.existsSync(path11.join(rootDir, p)));
5456
+ const existingPaths = patterns.filter((p) => fs8.existsSync(path9.join(rootDir, p)));
6109
5457
  if (existingPaths.length > 0) {
6110
5458
  const symbolInfo = Object.values(SYMBOL_CATEGORIES).find((s) => s.category === category);
6111
5459
  structure[category] = { paths: existingPaths, symbol: symbolInfo?.prefix || "@" };
@@ -6116,7 +5464,7 @@ function buildStructure(rootDir) {
6116
5464
  function buildKeyFiles(rootDir) {
6117
5465
  const keyFiles = {};
6118
5466
  for (const [category, patterns] of Object.entries(KEY_FILE_PATTERNS)) {
6119
- const existingPaths = patterns.filter((p) => fs10.existsSync(path11.join(rootDir, p)));
5467
+ const existingPaths = patterns.filter((p) => fs8.existsSync(path9.join(rootDir, p)));
6120
5468
  if (existingPaths.length > 0) {
6121
5469
  keyFiles[category] = existingPaths;
6122
5470
  }
@@ -6132,10 +5480,10 @@ function buildSkipPatterns(rootDir) {
6132
5480
  unless_testing: [...DEFAULT_SKIP_PATTERNS.unless_testing],
6133
5481
  unless_docs: [...DEFAULT_SKIP_PATTERNS.unless_docs]
6134
5482
  };
6135
- const gitignorePath = path11.join(rootDir, ".gitignore");
6136
- if (fs10.existsSync(gitignorePath)) {
5483
+ const gitignorePath = path9.join(rootDir, ".gitignore");
5484
+ if (fs8.existsSync(gitignorePath)) {
6137
5485
  try {
6138
- const content = fs10.readFileSync(gitignorePath, "utf8");
5486
+ const content = fs8.readFileSync(gitignorePath, "utf8");
6139
5487
  const gitignorePatterns = content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).filter(
6140
5488
  (line) => line.endsWith("/") || line.includes("*") || ["node_modules", "dist", "build", ".cache"].some((p) => line.includes(p))
6141
5489
  ).slice(0, 20);
@@ -6184,11 +5532,11 @@ function buildSymbolMap(symbols, purposeFiles, _rootDir) {
6184
5532
  symbolMap[symbolId] = symbol.filePath;
6185
5533
  } else {
6186
5534
  const matchingPurpose = purposeFiles.find((pf) => {
6187
- const dir = path11.dirname(pf);
5535
+ const dir = path9.dirname(pf);
6188
5536
  return dir.toLowerCase().includes(symbol.id.toLowerCase());
6189
5537
  });
6190
5538
  if (matchingPurpose) {
6191
- symbolMap[symbolId] = path11.dirname(matchingPurpose) + "/";
5539
+ symbolMap[symbolId] = path9.dirname(matchingPurpose) + "/";
6192
5540
  }
6193
5541
  }
6194
5542
  }
@@ -6199,8 +5547,8 @@ function generateFlowIndex(rootDir, purposeFiles) {
6199
5547
  const symbolToFlows = {};
6200
5548
  for (const filePath of purposeFiles) {
6201
5549
  try {
6202
- const content = fs10.readFileSync(filePath, "utf8");
6203
- const data = yaml8.load(content);
5550
+ const content = fs8.readFileSync(filePath, "utf8");
5551
+ const data = yaml7.load(content);
6204
5552
  if (!data?.flows) continue;
6205
5553
  if (Array.isArray(data.flows)) {
6206
5554
  for (const flowItem of data.flows) {
@@ -6213,7 +5561,7 @@ function generateFlowIndex(rootDir, purposeFiles) {
6213
5561
  id: flowId,
6214
5562
  description: flow.description || "",
6215
5563
  steps,
6216
- definedIn: path11.relative(rootDir, filePath)
5564
+ definedIn: path9.relative(rootDir, filePath)
6217
5565
  };
6218
5566
  indexFlowSymbols(flowId, steps, symbolToFlows);
6219
5567
  }
@@ -6229,7 +5577,7 @@ function generateFlowIndex(rootDir, purposeFiles) {
6229
5577
  trigger: flowDef.trigger,
6230
5578
  steps,
6231
5579
  validation: flowDef.validation,
6232
- definedIn: path11.relative(rootDir, filePath)
5580
+ definedIn: path9.relative(rootDir, filePath)
6233
5581
  };
6234
5582
  indexFlowSymbols(flowId, steps, symbolToFlows);
6235
5583
  }
@@ -6296,12 +5644,6 @@ export {
6296
5644
  getReferencesFrom,
6297
5645
  getSymbolCounts,
6298
5646
  getAllSymbols,
6299
- loadGlobalAntipatterns,
6300
- loadGlobalDecisions,
6301
- loadGlobalPreferences,
6302
- recordGlobalAntipattern,
6303
- recordGlobalDecision,
6304
- getSessionTracker,
6305
5647
  trackToolCall,
6306
5648
  trackResourceRead,
6307
5649
  addToolBreadcrumb,