@a-company/paradigm 3.1.2 → 3.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.js CHANGED
@@ -1,35 +1,11 @@
1
1
  #!/usr/bin/env node
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
- }) : x)(function(x) {
11
- if (typeof require !== "undefined") return require.apply(this, arguments);
12
- throw Error('Dynamic require of "' + x + '" is not supported');
13
- });
14
- var __commonJS = (cb, mod) => function __require2() {
15
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
16
- };
17
- var __copyProps = (to, from, except, desc) => {
18
- if (from && typeof from === "object" || typeof from === "function") {
19
- for (let key of __getOwnPropNames(from))
20
- if (!__hasOwnProp.call(to, key) && key !== except)
21
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
22
- }
23
- return to;
24
- };
25
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
26
- // If the importer is in node compatibility mode or this is not an ESM
27
- // file that has been converted to a CommonJS file using a Babel-
28
- // compatible transform (i.e. "__esModule" has not been set), then set
29
- // "default" to the CommonJS "module.exports" for node compatibility.
30
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
31
- mod
32
- ));
2
+ import {
3
+ __commonJS,
4
+ __require,
5
+ __toESM,
6
+ getPluginUpdateNotice,
7
+ schedulePluginUpdateCheck
8
+ } from "./chunk-4G54C4VM.js";
33
9
 
34
10
  // ../../node_modules/sql.js/dist/sql-wasm.js
35
11
  var require_sql_wasm = __commonJS({
@@ -525,15 +501,15 @@ var require_sql_wasm = __commonJS({
525
501
  "undefined" != typeof __filename ? ya = __filename : ba && (ya = self.location.href);
526
502
  var za = "", Aa, Ba;
527
503
  if (ca) {
528
- var fs26 = __require("fs");
504
+ var fs27 = __require("fs");
529
505
  za = __dirname + "/";
530
506
  Ba = (a) => {
531
507
  a = Ca(a) ? new URL(a) : a;
532
- return fs26.readFileSync(a);
508
+ return fs27.readFileSync(a);
533
509
  };
534
510
  Aa = async (a) => {
535
511
  a = Ca(a) ? new URL(a) : a;
536
- return fs26.readFileSync(a, void 0);
512
+ return fs27.readFileSync(a, void 0);
537
513
  };
538
514
  1 < process.argv.length && (wa = process.argv[1].replace(/\\/g, "/"));
539
515
  process.argv.slice(2);
@@ -815,7 +791,7 @@ var require_sql_wasm = __commonJS({
815
791
  if (ca) {
816
792
  var b = Buffer.alloc(256), c = 0, d = process.stdin.fd;
817
793
  try {
818
- c = fs26.readSync(d, b, 0, 256);
794
+ c = fs27.readSync(d, b, 0, 256);
819
795
  } catch (e) {
820
796
  if (e.toString().includes("EOF")) c = 0;
821
797
  else throw e;
@@ -4291,8 +4267,8 @@ var SessionTracker = class {
4291
4267
  * Extract resource type from URI
4292
4268
  */
4293
4269
  extractResourceType(uri) {
4294
- const path30 = uri.replace("paradigm://", "");
4295
- const firstPart = path30.split("/")[0];
4270
+ const path31 = uri.replace("paradigm://", "");
4271
+ const firstPart = path31.split("/")[0];
4296
4272
  return firstPart || "unknown";
4297
4273
  }
4298
4274
  /**
@@ -7003,7 +6979,7 @@ function navigateExplore(config, target, rootDir) {
7003
6979
  }
7004
6980
  if (result.paths.length === 0) {
7005
6981
  const areaSymbols = Object.entries(config.symbols).filter(
7006
- ([sym, path30]) => sym.toLowerCase().includes(targetLower) || path30.toLowerCase().includes(targetLower)
6982
+ ([sym, path31]) => sym.toLowerCase().includes(targetLower) || path31.toLowerCase().includes(targetLower)
7007
6983
  ).slice(0, 10);
7008
6984
  result.paths = [...new Set(areaSymbols.map(([, p]) => p))];
7009
6985
  result.symbols = areaSymbols.map(([s]) => s);
@@ -12095,6 +12071,10 @@ async function handleTagsTool(name, args, ctx) {
12095
12071
  }
12096
12072
  }
12097
12073
 
12074
+ // ../paradigm-mcp/src/tools/purpose-portal.ts
12075
+ import * as fs21 from "fs";
12076
+ import * as path23 from "path";
12077
+
12098
12078
  // ../paradigm-mcp/src/utils/purpose-writer.ts
12099
12079
  import * as fs19 from "fs";
12100
12080
  import * as path21 from "path";
@@ -13067,6 +13047,21 @@ async function handleAddAspect(args, ctx, reloadContext2) {
13067
13047
  }
13068
13048
  }
13069
13049
  const filePath = resolvePurposeFilePath(purposeFile, ctx.rootDir);
13050
+ const purposeDir = path23.dirname(filePath);
13051
+ for (const anchor of anchors) {
13052
+ const anchorFile = anchor.replace(/:.*$/, "");
13053
+ const resolved = path23.resolve(purposeDir, anchorFile);
13054
+ if (!fs21.existsSync(resolved)) {
13055
+ const rootResolved = path23.resolve(ctx.rootDir, anchorFile);
13056
+ if (fs21.existsSync(rootResolved)) {
13057
+ const corrected = path23.relative(purposeDir, rootResolved);
13058
+ const idx = anchors.indexOf(anchor);
13059
+ anchors[idx] = anchor.replace(anchorFile, corrected);
13060
+ } else {
13061
+ return err(`Anchor file not found: "${anchorFile}". Anchors must be relative to the .purpose file directory (${purposeDir}).`);
13062
+ }
13063
+ }
13064
+ }
13070
13065
  const data = readPurposeFile(filePath);
13071
13066
  if (!data.aspects) data.aspects = {};
13072
13067
  const bareId = stripSymbolPrefix(id);
@@ -13466,12 +13461,12 @@ async function handleValidate(args, ctx) {
13466
13461
  }
13467
13462
 
13468
13463
  // ../paradigm-mcp/src/tools/pm.ts
13469
- import * as fs22 from "fs";
13470
- import * as path25 from "path";
13464
+ import * as fs23 from "fs";
13465
+ import * as path26 from "path";
13471
13466
 
13472
13467
  // ../paradigm-mcp/src/utils/habits-loader.ts
13473
- import * as fs21 from "fs";
13474
- import * as path23 from "path";
13468
+ import * as fs22 from "fs";
13469
+ import * as path24 from "path";
13475
13470
  import * as yaml13 from "js-yaml";
13476
13471
  var SEED_HABITS = [
13477
13472
  {
@@ -13578,7 +13573,7 @@ var SEED_HABITS = [
13578
13573
  var HABITS_CACHE_TTL_MS = 30 * 1e3;
13579
13574
  var habitsCache = /* @__PURE__ */ new Map();
13580
13575
  function loadHabits(rootDir) {
13581
- const absoluteRoot = path23.resolve(rootDir);
13576
+ const absoluteRoot = path24.resolve(rootDir);
13582
13577
  const cached = habitsCache.get(absoluteRoot);
13583
13578
  if (cached && Date.now() - cached.loadedAt < HABITS_CACHE_TTL_MS) {
13584
13579
  return cached.habits;
@@ -13593,16 +13588,16 @@ function loadHabitsFresh(rootDir) {
13593
13588
  habitsById.set(seed.id, { ...seed });
13594
13589
  }
13595
13590
  const home = process.env.HOME || process.env.USERPROFILE || "~";
13596
- const globalConfig = loadHabitsYaml(path23.join(home, ".paradigm", "habits.yaml"));
13591
+ const globalConfig = loadHabitsYaml(path24.join(home, ".paradigm", "habits.yaml"));
13597
13592
  if (globalConfig) mergeHabits(habitsById, globalConfig);
13598
- const projectConfig = loadHabitsYaml(path23.join(rootDir, ".paradigm", "habits.yaml"));
13593
+ const projectConfig = loadHabitsYaml(path24.join(rootDir, ".paradigm", "habits.yaml"));
13599
13594
  if (projectConfig) mergeHabits(habitsById, projectConfig);
13600
13595
  return Array.from(habitsById.values());
13601
13596
  }
13602
13597
  function loadHabitsYaml(filePath) {
13603
- if (!fs21.existsSync(filePath)) return null;
13598
+ if (!fs22.existsSync(filePath)) return null;
13604
13599
  try {
13605
- const content = fs21.readFileSync(filePath, "utf8");
13600
+ const content = fs22.readFileSync(filePath, "utf8");
13606
13601
  return yaml13.load(content);
13607
13602
  } catch {
13608
13603
  return null;
@@ -13749,7 +13744,7 @@ function evalFileModified(habit, ctx) {
13749
13744
  const patterns = habit.check.params.patterns || [];
13750
13745
  if (patterns.length === 0) return { habit, result: "followed", reason: "No patterns specified" };
13751
13746
  const matched = ctx.filesModified.filter(
13752
- (f) => patterns.some((p) => f.includes(p) || path23.basename(f) === p)
13747
+ (f) => patterns.some((p) => f.includes(p) || path24.basename(f) === p)
13753
13748
  );
13754
13749
  if (matched.length > 0) {
13755
13750
  return { habit, result: "followed", reason: `Matching files: ${matched.join(", ")}`, evidence: matched };
@@ -13768,12 +13763,12 @@ function evalGitClean(habit, ctx) {
13768
13763
  }
13769
13764
 
13770
13765
  // ../paradigm-mcp/src/utils/practice-store.ts
13771
- import * as path24 from "path";
13766
+ import * as path25 from "path";
13772
13767
  var storageInstance = null;
13773
13768
  var storageInitialized2 = false;
13774
13769
  async function getStorage2(rootDir) {
13775
13770
  if (!storageInstance) {
13776
- const dbPath = path24.join(rootDir, ".paradigm", "sentinel", "sentinel.db");
13771
+ const dbPath = path25.join(rootDir, ".paradigm", "sentinel", "sentinel.db");
13777
13772
  storageInstance = new SentinelStorage(dbPath);
13778
13773
  await storageInstance.ensureReady();
13779
13774
  storageInitialized2 = true;
@@ -14064,11 +14059,11 @@ function runPostflightCheck(filesModified, symbolsTouched, ctx) {
14064
14059
  const violations = [];
14065
14060
  const declaredRoutes = ctx.gateConfig?.routes ? Object.keys(ctx.gateConfig.routes) : [];
14066
14061
  for (const file of filesModified) {
14067
- const absPath = path25.isAbsolute(file) ? file : path25.join(ctx.rootDir, file);
14068
- if (!fs22.existsSync(absPath)) continue;
14062
+ const absPath = path26.isAbsolute(file) ? file : path26.join(ctx.rootDir, file);
14063
+ if (!fs23.existsSync(absPath)) continue;
14069
14064
  let content;
14070
14065
  try {
14071
- content = fs22.readFileSync(absPath, "utf-8");
14066
+ content = fs23.readFileSync(absPath, "utf-8");
14072
14067
  } catch {
14073
14068
  continue;
14074
14069
  }
@@ -14086,8 +14081,8 @@ function runPostflightCheck(filesModified, symbolsTouched, ctx) {
14086
14081
  violations.push({
14087
14082
  type: "missing-portal-gate",
14088
14083
  severity: "warning",
14089
- message: `Route "${routePath}" in ${path25.relative(ctx.rootDir, absPath)} not in portal.yaml`,
14090
- file: path25.relative(ctx.rootDir, absPath),
14084
+ message: `Route "${routePath}" in ${path26.relative(ctx.rootDir, absPath)} not in portal.yaml`,
14085
+ file: path26.relative(ctx.rootDir, absPath),
14091
14086
  suggestion: "Add route to portal.yaml with ^gates. Use paradigm_gates_for_route for suggestions."
14092
14087
  });
14093
14088
  } else if (!ctx.gateConfig && routePath.startsWith("/api/")) {
@@ -14095,7 +14090,7 @@ function runPostflightCheck(filesModified, symbolsTouched, ctx) {
14095
14090
  type: "missing-portal-gate",
14096
14091
  severity: "warning",
14097
14092
  message: `API route "${routePath}" found but no portal.yaml exists`,
14098
- file: path25.relative(ctx.rootDir, absPath),
14093
+ file: path26.relative(ctx.rootDir, absPath),
14099
14094
  suggestion: "Create portal.yaml to declare gates for API routes."
14100
14095
  });
14101
14096
  }
@@ -14153,8 +14148,8 @@ function runPostflightCheck(filesModified, symbolsTouched, ctx) {
14153
14148
  });
14154
14149
  } else {
14155
14150
  for (const anchor of anchors) {
14156
- const filePath = path25.isAbsolute(anchor.path) ? anchor.path : path25.join(ctx.rootDir, anchor.path);
14157
- if (!fs22.existsSync(filePath)) {
14151
+ const filePath = path26.isAbsolute(anchor.path) ? anchor.path : path26.join(ctx.rootDir, anchor.path);
14152
+ if (!fs23.existsSync(filePath)) {
14158
14153
  violations.push({
14159
14154
  type: "stale-aspect",
14160
14155
  severity: "warning",
@@ -14235,12 +14230,12 @@ function runPostflightCheck(filesModified, symbolsTouched, ctx) {
14235
14230
  reason: e.reason
14236
14231
  }))
14237
14232
  };
14238
- const markerPath = path25.join(ctx.rootDir, ".paradigm", ".habits-blocking");
14233
+ const markerPath = path26.join(ctx.rootDir, ".paradigm", ".habits-blocking");
14239
14234
  if (evalResult.blocksCompletion) {
14240
14235
  const blocking = evalResult.evaluations.filter((e) => e.result === "skipped" && e.habit.severity === "block").map((e) => `${e.habit.name}: ${e.reason}`);
14241
- fs22.writeFileSync(markerPath, blocking.join("\n"), "utf8");
14242
- } else if (fs22.existsSync(markerPath)) {
14243
- fs22.unlinkSync(markerPath);
14236
+ fs23.writeFileSync(markerPath, blocking.join("\n"), "utf8");
14237
+ } else if (fs23.existsSync(markerPath)) {
14238
+ fs23.unlinkSync(markerPath);
14244
14239
  }
14245
14240
  } catch {
14246
14241
  }
@@ -14259,8 +14254,8 @@ function runPostflightCheck(filesModified, symbolsTouched, ctx) {
14259
14254
  }
14260
14255
 
14261
14256
  // ../paradigm-mcp/src/tools/reindex.ts
14262
- import * as fs23 from "fs";
14263
- import * as path26 from "path";
14257
+ import * as fs24 from "fs";
14258
+ import * as path27 from "path";
14264
14259
  import * as yaml14 from "js-yaml";
14265
14260
 
14266
14261
  // ../probe/core/dist/generator.js
@@ -14599,10 +14594,10 @@ async function rebuildStaticFiles(rootDir, ctx) {
14599
14594
  } else {
14600
14595
  aggregation = await aggregateFromDirectory(rootDir);
14601
14596
  }
14602
- const projectName = ctx?.projectName || path26.basename(rootDir);
14603
- const paradigmDir = path26.join(rootDir, ".paradigm");
14604
- if (!fs23.existsSync(paradigmDir)) {
14605
- fs23.mkdirSync(paradigmDir, { recursive: true });
14597
+ const projectName = ctx?.projectName || path27.basename(rootDir);
14598
+ const paradigmDir = path27.join(rootDir, ".paradigm");
14599
+ if (!fs24.existsSync(paradigmDir)) {
14600
+ fs24.mkdirSync(paradigmDir, { recursive: true });
14606
14601
  }
14607
14602
  const scanIndex = generateScanIndex(
14608
14603
  {
@@ -14612,12 +14607,12 @@ async function rebuildStaticFiles(rootDir, ctx) {
14612
14607
  },
14613
14608
  { projectName }
14614
14609
  );
14615
- const scanIndexPath = path26.join(paradigmDir, "scan-index.json");
14616
- fs23.writeFileSync(scanIndexPath, serializeScanIndex(scanIndex), "utf8");
14610
+ const scanIndexPath = path27.join(paradigmDir, "scan-index.json");
14611
+ fs24.writeFileSync(scanIndexPath, serializeScanIndex(scanIndex), "utf8");
14617
14612
  filesWritten.push(".paradigm/scan-index.json");
14618
14613
  const navigatorData = buildNavigatorData(rootDir, aggregation);
14619
- const navigatorPath = path26.join(paradigmDir, "navigator.yaml");
14620
- fs23.writeFileSync(
14614
+ const navigatorPath = path27.join(paradigmDir, "navigator.yaml");
14615
+ fs24.writeFileSync(
14621
14616
  navigatorPath,
14622
14617
  yaml14.dump(navigatorData, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: false }),
14623
14618
  "utf8"
@@ -14626,8 +14621,8 @@ async function rebuildStaticFiles(rootDir, ctx) {
14626
14621
  const flowIndex = generateFlowIndex(rootDir, aggregation.purposeFiles);
14627
14622
  let flowCount = 0;
14628
14623
  if (flowIndex && Object.keys(flowIndex.flows).length > 0) {
14629
- const flowIndexPath = path26.join(paradigmDir, "flow-index.json");
14630
- fs23.writeFileSync(flowIndexPath, JSON.stringify(flowIndex, null, 2), "utf8");
14624
+ const flowIndexPath = path27.join(paradigmDir, "flow-index.json");
14625
+ fs24.writeFileSync(flowIndexPath, JSON.stringify(flowIndex, null, 2), "utf8");
14631
14626
  filesWritten.push(".paradigm/flow-index.json");
14632
14627
  flowCount = Object.keys(flowIndex.flows).length;
14633
14628
  }
@@ -14656,7 +14651,7 @@ function buildNavigatorData(rootDir, aggregation) {
14656
14651
  function buildStructure(rootDir) {
14657
14652
  const structure = {};
14658
14653
  for (const [category, patterns] of Object.entries(DIRECTORY_PATTERNS)) {
14659
- const existingPaths = patterns.filter((p) => fs23.existsSync(path26.join(rootDir, p)));
14654
+ const existingPaths = patterns.filter((p) => fs24.existsSync(path27.join(rootDir, p)));
14660
14655
  if (existingPaths.length > 0) {
14661
14656
  const symbolInfo = Object.values(SYMBOL_CATEGORIES).find((s) => s.category === category);
14662
14657
  structure[category] = { paths: existingPaths, symbol: symbolInfo?.prefix || "@" };
@@ -14667,7 +14662,7 @@ function buildStructure(rootDir) {
14667
14662
  function buildKeyFiles(rootDir) {
14668
14663
  const keyFiles = {};
14669
14664
  for (const [category, patterns] of Object.entries(KEY_FILE_PATTERNS)) {
14670
- const existingPaths = patterns.filter((p) => fs23.existsSync(path26.join(rootDir, p)));
14665
+ const existingPaths = patterns.filter((p) => fs24.existsSync(path27.join(rootDir, p)));
14671
14666
  if (existingPaths.length > 0) {
14672
14667
  keyFiles[category] = existingPaths;
14673
14668
  }
@@ -14683,10 +14678,10 @@ function buildSkipPatterns(rootDir) {
14683
14678
  unless_testing: [...DEFAULT_SKIP_PATTERNS.unless_testing],
14684
14679
  unless_docs: [...DEFAULT_SKIP_PATTERNS.unless_docs]
14685
14680
  };
14686
- const gitignorePath = path26.join(rootDir, ".gitignore");
14687
- if (fs23.existsSync(gitignorePath)) {
14681
+ const gitignorePath = path27.join(rootDir, ".gitignore");
14682
+ if (fs24.existsSync(gitignorePath)) {
14688
14683
  try {
14689
- const content = fs23.readFileSync(gitignorePath, "utf8");
14684
+ const content = fs24.readFileSync(gitignorePath, "utf8");
14690
14685
  const gitignorePatterns = content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).filter(
14691
14686
  (line) => line.endsWith("/") || line.includes("*") || ["node_modules", "dist", "build", ".cache"].some((p) => line.includes(p))
14692
14687
  ).slice(0, 20);
@@ -14735,11 +14730,11 @@ function buildSymbolMap(symbols, purposeFiles, _rootDir) {
14735
14730
  symbolMap[symbolId] = symbol.filePath;
14736
14731
  } else {
14737
14732
  const matchingPurpose = purposeFiles.find((pf) => {
14738
- const dir = path26.dirname(pf);
14733
+ const dir = path27.dirname(pf);
14739
14734
  return dir.toLowerCase().includes(symbol.id.toLowerCase());
14740
14735
  });
14741
14736
  if (matchingPurpose) {
14742
- symbolMap[symbolId] = path26.dirname(matchingPurpose) + "/";
14737
+ symbolMap[symbolId] = path27.dirname(matchingPurpose) + "/";
14743
14738
  }
14744
14739
  }
14745
14740
  }
@@ -14750,7 +14745,7 @@ function generateFlowIndex(rootDir, purposeFiles) {
14750
14745
  const symbolToFlows = {};
14751
14746
  for (const filePath of purposeFiles) {
14752
14747
  try {
14753
- const content = fs23.readFileSync(filePath, "utf8");
14748
+ const content = fs24.readFileSync(filePath, "utf8");
14754
14749
  const data = yaml14.load(content);
14755
14750
  if (!data?.flows) continue;
14756
14751
  if (Array.isArray(data.flows)) {
@@ -14764,7 +14759,7 @@ function generateFlowIndex(rootDir, purposeFiles) {
14764
14759
  id: flowId,
14765
14760
  description: flow.description || "",
14766
14761
  steps,
14767
- definedIn: path26.relative(rootDir, filePath)
14762
+ definedIn: path27.relative(rootDir, filePath)
14768
14763
  };
14769
14764
  indexFlowSymbols(flowId, steps, symbolToFlows);
14770
14765
  }
@@ -14780,7 +14775,7 @@ function generateFlowIndex(rootDir, purposeFiles) {
14780
14775
  trigger: flowDef.trigger,
14781
14776
  steps,
14782
14777
  validation: flowDef.validation,
14783
- definedIn: path26.relative(rootDir, filePath)
14778
+ definedIn: path27.relative(rootDir, filePath)
14784
14779
  };
14785
14780
  indexFlowSymbols(flowId, steps, symbolToFlows);
14786
14781
  }
@@ -14833,28 +14828,28 @@ function indexFlowSymbols(flowId, steps, symbolToFlows) {
14833
14828
  }
14834
14829
 
14835
14830
  // ../paradigm-mcp/src/utils/lore-loader.ts
14836
- import * as fs24 from "fs";
14837
- import * as path27 from "path";
14831
+ import * as fs25 from "fs";
14832
+ import * as path28 from "path";
14838
14833
  import * as yaml15 from "js-yaml";
14839
14834
  var LORE_DIR = ".paradigm/lore";
14840
14835
  var ENTRIES_DIR = "entries";
14841
14836
  var TIMELINE_FILE = "timeline.yaml";
14842
14837
  async function loadLoreEntries(rootDir, filter) {
14843
- const entriesPath = path27.join(rootDir, LORE_DIR, ENTRIES_DIR);
14844
- if (!fs24.existsSync(entriesPath)) {
14838
+ const entriesPath = path28.join(rootDir, LORE_DIR, ENTRIES_DIR);
14839
+ if (!fs25.existsSync(entriesPath)) {
14845
14840
  return [];
14846
14841
  }
14847
14842
  migrateLegacyEntries(rootDir);
14848
14843
  const entries = [];
14849
- const dateDirs = fs24.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
14844
+ const dateDirs = fs25.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
14850
14845
  for (const dateDir of dateDirs) {
14851
14846
  if (filter?.dateFrom && dateDir < filter.dateFrom.slice(0, 10)) continue;
14852
14847
  if (filter?.dateTo && dateDir > filter.dateTo.slice(0, 10)) continue;
14853
- const dirPath = path27.join(entriesPath, dateDir);
14854
- const files = fs24.readdirSync(dirPath).filter((f) => f.endsWith(".yaml")).sort();
14848
+ const dirPath = path28.join(entriesPath, dateDir);
14849
+ const files = fs25.readdirSync(dirPath).filter((f) => f.endsWith(".yaml")).sort();
14855
14850
  for (const file of files) {
14856
14851
  try {
14857
- const content = fs24.readFileSync(path27.join(dirPath, file), "utf8");
14852
+ const content = fs25.readFileSync(path28.join(dirPath, file), "utf8");
14858
14853
  const entry = yaml15.load(content);
14859
14854
  entries.push(entry);
14860
14855
  } catch {
@@ -14867,10 +14862,10 @@ async function loadLoreEntry(rootDir, entryId) {
14867
14862
  const dateMatch = entryId.match(/^L-(\d{4}-\d{2}-\d{2})-/);
14868
14863
  if (dateMatch) {
14869
14864
  const dateStr = dateMatch[1];
14870
- const entryPath = path27.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
14871
- if (fs24.existsSync(entryPath)) {
14865
+ const entryPath = path28.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
14866
+ if (fs25.existsSync(entryPath)) {
14872
14867
  try {
14873
- const content = fs24.readFileSync(entryPath, "utf8");
14868
+ const content = fs25.readFileSync(entryPath, "utf8");
14874
14869
  return yaml15.load(content);
14875
14870
  } catch {
14876
14871
  return null;
@@ -14881,47 +14876,47 @@ async function loadLoreEntry(rootDir, entryId) {
14881
14876
  return entries.find((e) => e.id === entryId) || null;
14882
14877
  }
14883
14878
  async function loadLoreTimeline(rootDir) {
14884
- const timelinePath = path27.join(rootDir, LORE_DIR, TIMELINE_FILE);
14885
- if (!fs24.existsSync(timelinePath)) {
14879
+ const timelinePath = path28.join(rootDir, LORE_DIR, TIMELINE_FILE);
14880
+ if (!fs25.existsSync(timelinePath)) {
14886
14881
  return null;
14887
14882
  }
14888
14883
  try {
14889
- const content = fs24.readFileSync(timelinePath, "utf8");
14884
+ const content = fs25.readFileSync(timelinePath, "utf8");
14890
14885
  return yaml15.load(content);
14891
14886
  } catch {
14892
14887
  return null;
14893
14888
  }
14894
14889
  }
14895
14890
  async function recordLoreEntry(rootDir, entry) {
14896
- const lorePath = path27.join(rootDir, LORE_DIR);
14891
+ const lorePath = path28.join(rootDir, LORE_DIR);
14897
14892
  const dateStr = entry.timestamp.slice(0, 10);
14898
- const datePath = path27.join(lorePath, ENTRIES_DIR, dateStr);
14899
- if (!fs24.existsSync(datePath)) {
14900
- fs24.mkdirSync(datePath, { recursive: true });
14893
+ const datePath = path28.join(lorePath, ENTRIES_DIR, dateStr);
14894
+ if (!fs25.existsSync(datePath)) {
14895
+ fs25.mkdirSync(datePath, { recursive: true });
14901
14896
  }
14902
14897
  if (!entry.id) {
14903
14898
  entry.id = generateLoreId(rootDir, dateStr);
14904
14899
  }
14905
- const entryPath = path27.join(datePath, `${entry.id}.yaml`);
14906
- fs24.writeFileSync(entryPath, yaml15.dump(entry, { lineWidth: -1, noRefs: true }));
14900
+ const entryPath = path28.join(datePath, `${entry.id}.yaml`);
14901
+ fs25.writeFileSync(entryPath, yaml15.dump(entry, { lineWidth: -1, noRefs: true }));
14907
14902
  await rebuildTimeline(rootDir);
14908
14903
  return entry.id;
14909
14904
  }
14910
14905
  async function rebuildTimeline(rootDir) {
14911
- const lorePath = path27.join(rootDir, LORE_DIR);
14912
- const entriesPath = path27.join(lorePath, ENTRIES_DIR);
14913
- if (!fs24.existsSync(entriesPath)) return;
14906
+ const lorePath = path28.join(rootDir, LORE_DIR);
14907
+ const entriesPath = path28.join(lorePath, ENTRIES_DIR);
14908
+ if (!fs25.existsSync(entriesPath)) return;
14914
14909
  migrateLegacyEntries(rootDir);
14915
14910
  const authors = /* @__PURE__ */ new Set();
14916
14911
  let entryCount = 0;
14917
14912
  let lastUpdated = "";
14918
- const dateDirs = fs24.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d));
14913
+ const dateDirs = fs25.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d));
14919
14914
  for (const dateDir of dateDirs) {
14920
- const dirPath = path27.join(entriesPath, dateDir);
14921
- const files = fs24.readdirSync(dirPath).filter((f) => f.endsWith(".yaml"));
14915
+ const dirPath = path28.join(entriesPath, dateDir);
14916
+ const files = fs25.readdirSync(dirPath).filter((f) => f.endsWith(".yaml"));
14922
14917
  for (const file of files) {
14923
14918
  try {
14924
- const content = fs24.readFileSync(path27.join(dirPath, file), "utf8");
14919
+ const content = fs25.readFileSync(path28.join(dirPath, file), "utf8");
14925
14920
  const entry = yaml15.load(content);
14926
14921
  authors.add(entry.author.id);
14927
14922
  entryCount++;
@@ -14933,10 +14928,10 @@ async function rebuildTimeline(rootDir) {
14933
14928
  }
14934
14929
  }
14935
14930
  let project = "unknown";
14936
- const configPath = path27.join(rootDir, ".paradigm", "config.yaml");
14937
- if (fs24.existsSync(configPath)) {
14931
+ const configPath = path28.join(rootDir, ".paradigm", "config.yaml");
14932
+ if (fs25.existsSync(configPath)) {
14938
14933
  try {
14939
- const config = yaml15.load(fs24.readFileSync(configPath, "utf8"));
14934
+ const config = yaml15.load(fs25.readFileSync(configPath, "utf8"));
14940
14935
  project = config.project || config.name || "unknown";
14941
14936
  } catch {
14942
14937
  }
@@ -14948,31 +14943,31 @@ async function rebuildTimeline(rootDir) {
14948
14943
  last_updated: lastUpdated || (/* @__PURE__ */ new Date()).toISOString(),
14949
14944
  authors: Array.from(authors)
14950
14945
  };
14951
- if (!fs24.existsSync(lorePath)) {
14952
- fs24.mkdirSync(lorePath, { recursive: true });
14946
+ if (!fs25.existsSync(lorePath)) {
14947
+ fs25.mkdirSync(lorePath, { recursive: true });
14953
14948
  }
14954
- fs24.writeFileSync(
14955
- path27.join(lorePath, TIMELINE_FILE),
14949
+ fs25.writeFileSync(
14950
+ path28.join(lorePath, TIMELINE_FILE),
14956
14951
  yaml15.dump(timeline, { lineWidth: -1, noRefs: true })
14957
14952
  );
14958
14953
  }
14959
14954
  function migrateLegacyEntries(rootDir) {
14960
- const entriesPath = path27.join(rootDir, LORE_DIR, ENTRIES_DIR);
14961
- if (!fs24.existsSync(entriesPath)) return 0;
14962
- const rootFiles = fs24.readdirSync(entriesPath).filter((f) => f.endsWith(".yaml") && !f.startsWith("."));
14955
+ const entriesPath = path28.join(rootDir, LORE_DIR, ENTRIES_DIR);
14956
+ if (!fs25.existsSync(entriesPath)) return 0;
14957
+ const rootFiles = fs25.readdirSync(entriesPath).filter((f) => f.endsWith(".yaml") && !f.startsWith("."));
14963
14958
  let migrated = 0;
14964
14959
  for (const file of rootFiles) {
14965
- const filePath = path27.join(entriesPath, file);
14966
- const stat = fs24.statSync(filePath);
14960
+ const filePath = path28.join(entriesPath, file);
14961
+ const stat = fs25.statSync(filePath);
14967
14962
  if (!stat.isFile()) continue;
14968
14963
  try {
14969
- const content = fs24.readFileSync(filePath, "utf8");
14964
+ const content = fs25.readFileSync(filePath, "utf8");
14970
14965
  const raw = yaml15.load(content);
14971
14966
  if (raw.author && typeof raw.author === "object") continue;
14972
14967
  const dateStr = typeof raw.date === "string" ? raw.date.slice(0, 10) : (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
14973
- const datePath = path27.join(entriesPath, dateStr);
14974
- if (!fs24.existsSync(datePath)) {
14975
- fs24.mkdirSync(datePath, { recursive: true });
14968
+ const datePath = path28.join(entriesPath, dateStr);
14969
+ if (!fs25.existsSync(datePath)) {
14970
+ fs25.mkdirSync(datePath, { recursive: true });
14976
14971
  }
14977
14972
  const id = generateLoreId(rootDir, dateStr);
14978
14973
  const oldType = String(raw.type || "agent-session");
@@ -14997,11 +14992,11 @@ function migrateLegacyEntries(rootDir) {
14997
14992
  ...verification ? { verification } : {},
14998
14993
  tags: ["migrated", oldType]
14999
14994
  };
15000
- fs24.writeFileSync(
15001
- path27.join(datePath, `${id}.yaml`),
14995
+ fs25.writeFileSync(
14996
+ path28.join(datePath, `${id}.yaml`),
15002
14997
  yaml15.dump(v2Entry, { lineWidth: -1, noRefs: true })
15003
14998
  );
15004
- fs24.unlinkSync(filePath);
14999
+ fs25.unlinkSync(filePath);
15005
15000
  migrated++;
15006
15001
  } catch {
15007
15002
  }
@@ -15012,8 +15007,8 @@ async function updateLoreEntry(rootDir, entryId, partial) {
15012
15007
  const entry = await loadLoreEntry(rootDir, entryId);
15013
15008
  if (!entry) return false;
15014
15009
  const dateStr = entry.timestamp.slice(0, 10);
15015
- const entryPath = path27.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
15016
- if (!fs24.existsSync(entryPath)) return false;
15010
+ const entryPath = path28.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
15011
+ if (!fs25.existsSync(entryPath)) return false;
15017
15012
  if (partial.title !== void 0) entry.title = partial.title;
15018
15013
  if (partial.summary !== void 0) entry.summary = partial.summary;
15019
15014
  if (partial.type !== void 0) entry.type = partial.type;
@@ -15030,7 +15025,7 @@ async function updateLoreEntry(rootDir, entryId, partial) {
15030
15025
  if (partial.learnings !== void 0) entry.learnings = partial.learnings;
15031
15026
  if (partial.verification !== void 0) entry.verification = partial.verification;
15032
15027
  if (partial.tags !== void 0) entry.tags = partial.tags;
15033
- fs24.writeFileSync(entryPath, yaml15.dump(entry, { lineWidth: -1, noRefs: true }));
15028
+ fs25.writeFileSync(entryPath, yaml15.dump(entry, { lineWidth: -1, noRefs: true }));
15034
15029
  await rebuildTimeline(rootDir);
15035
15030
  return true;
15036
15031
  }
@@ -15038,13 +15033,13 @@ async function deleteLoreEntry(rootDir, entryId) {
15038
15033
  const entry = await loadLoreEntry(rootDir, entryId);
15039
15034
  if (!entry) return false;
15040
15035
  const dateStr = entry.timestamp.slice(0, 10);
15041
- const entryPath = path27.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
15042
- if (!fs24.existsSync(entryPath)) return false;
15043
- fs24.unlinkSync(entryPath);
15044
- const dateDir = path27.dirname(entryPath);
15045
- const remaining = fs24.readdirSync(dateDir).filter((f) => f.endsWith(".yaml"));
15036
+ const entryPath = path28.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
15037
+ if (!fs25.existsSync(entryPath)) return false;
15038
+ fs25.unlinkSync(entryPath);
15039
+ const dateDir = path28.dirname(entryPath);
15040
+ const remaining = fs25.readdirSync(dateDir).filter((f) => f.endsWith(".yaml"));
15046
15041
  if (remaining.length === 0) {
15047
- fs24.rmdirSync(dateDir);
15042
+ fs25.rmdirSync(dateDir);
15048
15043
  }
15049
15044
  await rebuildTimeline(rootDir);
15050
15045
  return true;
@@ -15085,11 +15080,11 @@ function applyFilter(entries, filter) {
15085
15080
  return result;
15086
15081
  }
15087
15082
  function generateLoreId(rootDir, dateStr) {
15088
- const datePath = path27.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr);
15089
- if (!fs24.existsSync(datePath)) {
15083
+ const datePath = path28.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr);
15084
+ if (!fs25.existsSync(datePath)) {
15090
15085
  return `L-${dateStr}-001`;
15091
15086
  }
15092
- const existing = fs24.readdirSync(datePath).filter((f) => f.startsWith("L-") && f.endsWith(".yaml")).map((f) => {
15087
+ const existing = fs25.readdirSync(datePath).filter((f) => f.startsWith("L-") && f.endsWith(".yaml")).map((f) => {
15093
15088
  const match = f.match(/L-\d{4}-\d{2}-\d{2}-(\d+)\.yaml/);
15094
15089
  return match ? parseInt(match[1], 10) : 0;
15095
15090
  });
@@ -15592,8 +15587,8 @@ function summarizeEntry(entry) {
15592
15587
  }
15593
15588
 
15594
15589
  // ../paradigm-mcp/src/tools/habits.ts
15595
- import * as fs25 from "fs";
15596
- import * as path28 from "path";
15590
+ import * as fs26 from "fs";
15591
+ import * as path29 from "path";
15597
15592
  import { execSync as execSync2 } from "child_process";
15598
15593
  function getHabitsToolsList() {
15599
15594
  return [
@@ -15842,13 +15837,13 @@ async function handleHabitsCheck(args, ctx) {
15842
15837
  } catch {
15843
15838
  }
15844
15839
  }
15845
- const markerPath = path28.join(ctx.rootDir, ".paradigm", ".habits-blocking");
15840
+ const markerPath = path29.join(ctx.rootDir, ".paradigm", ".habits-blocking");
15846
15841
  try {
15847
15842
  if (trigger === "on-stop" && evaluation.blocksCompletion) {
15848
15843
  const blocking = evaluation.evaluations.filter((e) => e.result === "skipped" && e.habit.severity === "block").map((e) => `${e.habit.name}: ${e.reason}`);
15849
- fs25.writeFileSync(markerPath, blocking.join("\n"), "utf8");
15844
+ fs26.writeFileSync(markerPath, blocking.join("\n"), "utf8");
15850
15845
  } else if (trigger === "on-stop") {
15851
- if (fs25.existsSync(markerPath)) fs25.unlinkSync(markerPath);
15846
+ if (fs26.existsSync(markerPath)) fs26.unlinkSync(markerPath);
15852
15847
  }
15853
15848
  } catch {
15854
15849
  }
@@ -16061,7 +16056,7 @@ async function handlePracticeContext(args, ctx) {
16061
16056
  }
16062
16057
 
16063
16058
  // ../paradigm-mcp/src/tools/fallback-grep.ts
16064
- import * as path29 from "path";
16059
+ import * as path30 from "path";
16065
16060
  import { execSync as execSync3 } from "child_process";
16066
16061
  function grepForReferences(rootDir, symbol, options = {}) {
16067
16062
  const { maxResults = 20 } = options;
@@ -16090,7 +16085,7 @@ function grepForReferences(rootDir, symbol, options = {}) {
16090
16085
  const match = line.match(/^(.+?):(\d+):(.*)$/);
16091
16086
  if (match) {
16092
16087
  const [, filePath, lineNum, content] = match;
16093
- const relativePath = path29.relative(rootDir, filePath);
16088
+ const relativePath = path30.relative(rootDir, filePath);
16094
16089
  let context2 = "unknown";
16095
16090
  if (relativePath.includes(".purpose") || relativePath.includes("portal.yaml")) {
16096
16091
  context2 = "purpose";
@@ -16335,7 +16330,20 @@ function registerTools(server, getContext2, reloadContext2) {
16335
16330
  // Lore tools
16336
16331
  ...getLoreToolsList(),
16337
16332
  // Habits tools
16338
- ...getHabitsToolsList()
16333
+ ...getHabitsToolsList(),
16334
+ // Plugin update check
16335
+ {
16336
+ name: "paradigm_plugin_check",
16337
+ description: "Check for updates to installed Claude Code plugins. Reports which marketplace clones have newer remote commits and which cached versions are stale.",
16338
+ inputSchema: {
16339
+ type: "object",
16340
+ properties: {}
16341
+ },
16342
+ annotations: {
16343
+ readOnlyHint: true,
16344
+ destructiveHint: false
16345
+ }
16346
+ }
16339
16347
  ]
16340
16348
  };
16341
16349
  }
@@ -16349,8 +16357,11 @@ function registerTools(server, getContext2, reloadContext2) {
16349
16357
  const tracker2 = getSessionTracker();
16350
16358
  tracker2.setRootDir(ctx.rootDir);
16351
16359
  let recoveryPreamble = null;
16360
+ let updateNotice = null;
16352
16361
  if (!tracker2.hasRecoveredThisSession()) {
16353
16362
  recoveryPreamble = buildRecoveryPreamble(ctx.rootDir);
16363
+ updateNotice = getPluginUpdateNotice();
16364
+ schedulePluginUpdateCheck();
16354
16365
  tracker2.markRecovered();
16355
16366
  }
16356
16367
  const toolResult = await (async () => {
@@ -16783,6 +16794,37 @@ function registerTools(server, getContext2, reloadContext2) {
16783
16794
  }]
16784
16795
  };
16785
16796
  }
16797
+ case "paradigm_plugin_check": {
16798
+ const { runPluginUpdateCheck } = await import("./plugin-update-checker-EWT7YMDF.js");
16799
+ const results = await runPluginUpdateCheck();
16800
+ const updatable = results.filter((r) => r.hasRemoteUpdate || r.hasCacheStale);
16801
+ if (updatable.length === 0) {
16802
+ const msg = results.length === 0 ? "No Claude Code plugins found in ~/.claude/plugins/marketplaces/." : "All installed plugins are up to date.";
16803
+ trackToolCall(msg.length, name);
16804
+ return { content: [{ type: "text", text: msg }] };
16805
+ }
16806
+ const lines = ["Plugin updates available:\n"];
16807
+ const pullCmds = [];
16808
+ for (const r of updatable) {
16809
+ if (r.hasRemoteUpdate) {
16810
+ lines.push(` ${r.plugin} (${r.repo}): remote has newer commits`);
16811
+ pullCmds.push(`git -C ${r.marketplacePath} pull origin main`);
16812
+ } else if (r.hasCacheStale) {
16813
+ lines.push(` ${r.plugin} (${r.repo}): ${r.installedVersion} \u2192 ${r.localVersion} (restart needed)`);
16814
+ }
16815
+ }
16816
+ if (pullCmds.length > 0) {
16817
+ lines.push(`
16818
+ Update command:
16819
+ ${pullCmds.join(" && \\\n ")}`);
16820
+ lines.push("\nAfter running, restart the session to apply updates.");
16821
+ } else {
16822
+ lines.push("\nRestart the session to apply cached updates.");
16823
+ }
16824
+ const pluginText = lines.join("\n");
16825
+ trackToolCall(pluginText.length, name);
16826
+ return { content: [{ type: "text", text: pluginText }] };
16827
+ }
16786
16828
  default: {
16787
16829
  if (name === "paradigm_navigate") {
16788
16830
  const result = await handleNavigateTool(name, args, ctx);
@@ -16915,10 +16957,11 @@ function registerTools(server, getContext2, reloadContext2) {
16915
16957
  }
16916
16958
  }
16917
16959
  })();
16918
- if (recoveryPreamble) {
16960
+ if (recoveryPreamble || updateNotice) {
16919
16961
  const first = toolResult.content?.[0];
16920
16962
  if (first && typeof first === "object" && "text" in first && typeof first.text === "string") {
16921
- first.text = recoveryPreamble + "\n\n" + first.text;
16963
+ const preamble = [updateNotice, recoveryPreamble].filter(Boolean).join("\n\n");
16964
+ first.text = preamble + "\n\n" + first.text;
16922
16965
  }
16923
16966
  }
16924
16967
  return toolResult;