@a-company/paradigm 3.18.0 → 3.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.js CHANGED
@@ -7,16 +7,6 @@ import {
7
7
  shelveTask,
8
8
  updateTask
9
9
  } from "./chunk-CSD7IHSN.js";
10
- import {
11
- closeArc,
12
- createArc,
13
- loadArc,
14
- loadArcs,
15
- loadEntries,
16
- loadEntry,
17
- recordEntry,
18
- searchEntries
19
- } from "./chunk-DSXS42FY.js";
20
10
  import {
21
11
  PatternMatcher,
22
12
  PatternSuggester,
@@ -34,7 +24,6 @@ import {
34
24
  checkDrift,
35
25
  closeAspectGraph,
36
26
  createPersona,
37
- deleteLoreEntry,
38
27
  deletePersona,
39
28
  detectProtocolSuggestion,
40
29
  findPurposeFiles,
@@ -62,9 +51,6 @@ import {
62
51
  loadGlobalAntipatterns,
63
52
  loadGlobalDecisions,
64
53
  loadGlobalPreferences,
65
- loadLoreEntries,
66
- loadLoreEntry,
67
- loadLoreTimeline,
68
54
  loadPersona,
69
55
  loadPersonas,
70
56
  loadProtocol,
@@ -76,7 +62,6 @@ import {
76
62
  rebuildStaticFiles,
77
63
  recordGlobalAntipattern,
78
64
  recordGlobalDecision,
79
- recordLoreEntry,
80
65
  recordProtocol,
81
66
  removeStep,
82
67
  searchProtocols,
@@ -85,14 +70,21 @@ import {
85
70
  toolCache,
86
71
  trackResourceRead,
87
72
  trackToolCall,
88
- updateLoreEntry,
89
73
  updatePersona,
90
74
  updateProtocol,
91
75
  validateAgainstSentinel,
92
76
  validatePersona,
93
77
  validateProtocol,
94
78
  validatePurposeFile
95
- } from "./chunk-TUW27EIC.js";
79
+ } from "./chunk-EZ6XW6FB.js";
80
+ import {
81
+ deleteLoreEntry,
82
+ loadLoreEntries,
83
+ loadLoreEntry,
84
+ loadLoreTimeline,
85
+ recordLoreEntry,
86
+ updateLoreEntry
87
+ } from "./chunk-3DYYXGDC.js";
96
88
  import {
97
89
  getPluginUpdateNotice,
98
90
  schedulePluginUpdateCheck
@@ -2033,8 +2025,8 @@ function registerResources(server, getContext2) {
2033
2025
  }
2034
2026
 
2035
2027
  // ../paradigm-mcp/src/tools/index.ts
2036
- import * as os2 from "os";
2037
- import * as path24 from "path";
2028
+ import * as os3 from "os";
2029
+ import * as path25 from "path";
2038
2030
  import {
2039
2031
  ListToolsRequestSchema,
2040
2032
  CallToolRequestSchema
@@ -2798,7 +2790,7 @@ function navigateExplore(config, target, rootDir) {
2798
2790
  }
2799
2791
  if (result.paths.length === 0) {
2800
2792
  const areaSymbols = Object.entries(config.symbols).filter(
2801
- ([sym, path25]) => sym.toLowerCase().includes(targetLower) || path25.toLowerCase().includes(targetLower)
2793
+ ([sym, path26]) => sym.toLowerCase().includes(targetLower) || path26.toLowerCase().includes(targetLower)
2802
2794
  ).slice(0, 10);
2803
2795
  result.paths = [...new Set(areaSymbols.map(([, p]) => p))];
2804
2796
  result.symbols = areaSymbols.map(([s]) => s);
@@ -8262,9 +8254,17 @@ function getLoreToolsList() {
8262
8254
  },
8263
8255
  type: {
8264
8256
  type: "string",
8265
- enum: ["agent-session", "human-note", "decision", "review", "incident", "milestone"],
8257
+ enum: ["agent-session", "human-note", "decision", "review", "incident", "milestone", "retro", "insight"],
8266
8258
  description: "Filter by entry type"
8267
8259
  },
8260
+ tag: {
8261
+ type: "string",
8262
+ description: 'Filter by tag prefix (e.g., "arc:lore-evolution" for arc entries)'
8263
+ },
8264
+ hasBody: {
8265
+ type: "boolean",
8266
+ description: "Filter for entries with/without long-form body content"
8267
+ },
8268
8268
  dateFrom: {
8269
8269
  type: "string",
8270
8270
  description: 'Filter from date (ISO 8601, e.g., "2026-02-20")'
@@ -8305,7 +8305,7 @@ function getLoreToolsList() {
8305
8305
  properties: {
8306
8306
  type: {
8307
8307
  type: "string",
8308
- enum: ["agent-session", "human-note", "decision", "review", "incident", "milestone"],
8308
+ enum: ["agent-session", "human-note", "decision", "review", "incident", "milestone", "retro", "insight"],
8309
8309
  description: "Entry type"
8310
8310
  },
8311
8311
  title: {
@@ -8391,9 +8391,28 @@ function getLoreToolsList() {
8391
8391
  meta: {
8392
8392
  type: "object",
8393
8393
  description: 'Project-defined metadata (open-ended key-value pairs, e.g., { meeting_type: "design-review", sprint: 12 })'
8394
+ },
8395
+ body: {
8396
+ type: "string",
8397
+ description: "Long-form content (detailed retrospective notes, decision rationale, etc.)"
8398
+ },
8399
+ linked_lore: {
8400
+ type: "array",
8401
+ items: { type: "string" },
8402
+ description: "Cross-references to other lore entry IDs"
8403
+ },
8404
+ linked_tasks: {
8405
+ type: "array",
8406
+ items: { type: "string" },
8407
+ description: "References to paradigm task IDs"
8408
+ },
8409
+ linked_commits: {
8410
+ type: "array",
8411
+ items: { type: "string" },
8412
+ description: "Git commit SHAs related to this entry"
8394
8413
  }
8395
8414
  },
8396
- required: ["type", "title", "summary", "symbols_touched"]
8415
+ required: ["title", "summary", "symbols_touched"]
8397
8416
  },
8398
8417
  annotations: {
8399
8418
  readOnlyHint: false,
@@ -8449,7 +8468,7 @@ function getLoreToolsList() {
8449
8468
  summary: { type: "string", description: "New summary" },
8450
8469
  type: {
8451
8470
  type: "string",
8452
- enum: ["agent-session", "human-note", "decision", "review", "incident", "milestone"],
8471
+ enum: ["agent-session", "human-note", "decision", "review", "incident", "milestone", "retro", "insight"],
8453
8472
  description: "New entry type"
8454
8473
  },
8455
8474
  symbols_touched: {
@@ -8533,6 +8552,8 @@ async function handleLoreTool(name, args, ctx) {
8533
8552
  dateFrom: args.dateFrom,
8534
8553
  dateTo: args.dateTo,
8535
8554
  type: args.type,
8555
+ tag: args.tag,
8556
+ hasBody: args.hasBody,
8536
8557
  tags: args.tags,
8537
8558
  hasReview: args.hasReview,
8538
8559
  limit: args.limit || 20,
@@ -8568,7 +8589,11 @@ async function handleLoreTool(name, args, ctx) {
8568
8589
  learnings,
8569
8590
  verification,
8570
8591
  tags,
8571
- meta
8592
+ meta,
8593
+ body,
8594
+ linked_lore,
8595
+ linked_tasks,
8596
+ linked_commits
8572
8597
  } = args;
8573
8598
  let habit_compliance;
8574
8599
  try {
@@ -8590,7 +8615,7 @@ async function handleLoreTool(name, args, ctx) {
8590
8615
  const entry = {
8591
8616
  id: "",
8592
8617
  // Will be generated
8593
- type,
8618
+ type: type || "agent-session",
8594
8619
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
8595
8620
  duration_minutes,
8596
8621
  author: resolveAuthorForMcp(),
@@ -8610,7 +8635,11 @@ async function handleLoreTool(name, args, ctx) {
8610
8635
  verification,
8611
8636
  tags,
8612
8637
  meta: meta || void 0,
8613
- habit_compliance
8638
+ habit_compliance,
8639
+ body,
8640
+ linked_lore,
8641
+ linked_tasks,
8642
+ linked_commits
8614
8643
  };
8615
8644
  const id = await recordLoreEntry(ctx.rootDir, entry);
8616
8645
  getSessionTracker().setLastLoreEntryId(id);
@@ -10225,8 +10254,8 @@ function getTasksToolsList() {
10225
10254
  priority: { type: "string", enum: ["high", "medium", "low"] },
10226
10255
  status: { type: "string", enum: ["open", "done", "shelved"] },
10227
10256
  tags: { type: "array", items: { type: "string" }, description: "Replace tags" },
10228
- related_lore: { type: "array", items: { type: "string" } },
10229
- related_assessments: { type: "array", items: { type: "string" } }
10257
+ related_lore: { type: "array", items: { type: "string" }, description: "Related lore entry IDs (includes former assessment entries)" },
10258
+ related_assessments: { type: "array", items: { type: "string" }, description: "(Deprecated \u2014 use related_lore) Alias for related_lore" }
10230
10259
  },
10231
10260
  required: ["id"]
10232
10261
  },
@@ -10316,7 +10345,7 @@ async function handleTasksTool(name, args, ctx) {
10316
10345
  text: JSON.stringify({
10317
10346
  completed: id,
10318
10347
  task,
10319
- hint: "Consider updating related assessment arcs if this was a significant milestone."
10348
+ hint: "Consider recording a lore entry with arc:* tags if this was a significant milestone."
10320
10349
  }, null, 2)
10321
10350
  };
10322
10351
  }
@@ -10334,18 +10363,228 @@ async function handleTasksTool(name, args, ctx) {
10334
10363
  }
10335
10364
  }
10336
10365
 
10366
+ // ../paradigm-mcp/src/utils/assessment-loader.ts
10367
+ import * as fs21 from "fs";
10368
+ import * as path23 from "path";
10369
+ import * as yaml12 from "js-yaml";
10370
+ var ASSESSMENTS_DIR = ".paradigm/assessments";
10371
+ var ARCS_DIR = "arcs";
10372
+ var INDEX_FILE = "index.yaml";
10373
+ function computeArcStats(rootDir, arc) {
10374
+ const entriesPath = path23.join(rootDir, ASSESSMENTS_DIR, ARCS_DIR, arc.id, "entries");
10375
+ const symbolSet = /* @__PURE__ */ new Set();
10376
+ let entryCount = 0;
10377
+ let latestDate;
10378
+ if (fs21.existsSync(entriesPath)) {
10379
+ const files = fs21.readdirSync(entriesPath).filter((f) => f.endsWith(".yaml"));
10380
+ for (const file of files) {
10381
+ try {
10382
+ const entry = yaml12.load(fs21.readFileSync(path23.join(entriesPath, file), "utf8"));
10383
+ entryCount++;
10384
+ if (entry.symbols) entry.symbols.forEach((s) => symbolSet.add(s));
10385
+ if (!latestDate || entry.date > latestDate) latestDate = entry.date;
10386
+ } catch {
10387
+ }
10388
+ }
10389
+ }
10390
+ return { ...arc, entry_count: entryCount, symbols: Array.from(symbolSet), latest_entry: latestDate };
10391
+ }
10392
+ async function loadArcs(rootDir, status) {
10393
+ const arcsPath = path23.join(rootDir, ASSESSMENTS_DIR, ARCS_DIR);
10394
+ if (!fs21.existsSync(arcsPath)) return [];
10395
+ const arcDirs = fs21.readdirSync(arcsPath).filter((d) => {
10396
+ try {
10397
+ return fs21.statSync(path23.join(arcsPath, d)).isDirectory();
10398
+ } catch {
10399
+ return false;
10400
+ }
10401
+ });
10402
+ const arcs = [];
10403
+ for (const arcDir of arcDirs) {
10404
+ const arcFile = path23.join(arcsPath, arcDir, "arc.yaml");
10405
+ if (!fs21.existsSync(arcFile)) continue;
10406
+ try {
10407
+ const arc = yaml12.load(fs21.readFileSync(arcFile, "utf8"));
10408
+ if (status && status !== "all" && arc.status !== status) continue;
10409
+ arcs.push(computeArcStats(rootDir, arc));
10410
+ } catch {
10411
+ }
10412
+ }
10413
+ arcs.sort((a, b) => {
10414
+ const aDate = a.latest_entry || a.created;
10415
+ const bDate = b.latest_entry || b.created;
10416
+ return bDate.localeCompare(aDate);
10417
+ });
10418
+ return arcs;
10419
+ }
10420
+ async function loadArc(rootDir, arcId) {
10421
+ const arcFile = path23.join(rootDir, ASSESSMENTS_DIR, ARCS_DIR, arcId, "arc.yaml");
10422
+ if (!fs21.existsSync(arcFile)) return null;
10423
+ try {
10424
+ const arc = yaml12.load(fs21.readFileSync(arcFile, "utf8"));
10425
+ return computeArcStats(rootDir, arc);
10426
+ } catch {
10427
+ return null;
10428
+ }
10429
+ }
10430
+ async function closeArc(rootDir, arcId, status) {
10431
+ const arcFile = path23.join(rootDir, ASSESSMENTS_DIR, ARCS_DIR, arcId, "arc.yaml");
10432
+ if (!fs21.existsSync(arcFile)) return false;
10433
+ try {
10434
+ const arc = yaml12.load(fs21.readFileSync(arcFile, "utf8"));
10435
+ arc.status = status;
10436
+ fs21.writeFileSync(arcFile, yaml12.dump(arc, { lineWidth: -1, noRefs: true }));
10437
+ await rebuildAssessmentIndex(rootDir);
10438
+ return true;
10439
+ } catch {
10440
+ return false;
10441
+ }
10442
+ }
10443
+ async function loadEntries(rootDir, arcId) {
10444
+ const entriesPath = path23.join(rootDir, ASSESSMENTS_DIR, ARCS_DIR, arcId, "entries");
10445
+ if (!fs21.existsSync(entriesPath)) return [];
10446
+ const entries = [];
10447
+ const files = fs21.readdirSync(entriesPath).filter((f) => f.endsWith(".yaml")).sort();
10448
+ for (const file of files) {
10449
+ try {
10450
+ const entry = yaml12.load(fs21.readFileSync(path23.join(entriesPath, file), "utf8"));
10451
+ entries.push(entry);
10452
+ } catch {
10453
+ }
10454
+ }
10455
+ entries.sort((a, b) => b.date.localeCompare(a.date));
10456
+ return entries;
10457
+ }
10458
+ async function loadEntry(rootDir, entryId) {
10459
+ const arcsPath = path23.join(rootDir, ASSESSMENTS_DIR, ARCS_DIR);
10460
+ if (!fs21.existsSync(arcsPath)) return null;
10461
+ const arcDirs = fs21.readdirSync(arcsPath).filter((d) => {
10462
+ try {
10463
+ return fs21.statSync(path23.join(arcsPath, d)).isDirectory();
10464
+ } catch {
10465
+ return false;
10466
+ }
10467
+ });
10468
+ for (const arcDir of arcDirs) {
10469
+ const entryFile = path23.join(arcsPath, arcDir, "entries", `${entryId}.yaml`);
10470
+ if (fs21.existsSync(entryFile)) {
10471
+ try {
10472
+ const entry = yaml12.load(fs21.readFileSync(entryFile, "utf8"));
10473
+ const arcFile = path23.join(arcsPath, arcDir, "arc.yaml");
10474
+ const arc = yaml12.load(fs21.readFileSync(arcFile, "utf8"));
10475
+ return { entry, arc };
10476
+ } catch {
10477
+ return null;
10478
+ }
10479
+ }
10480
+ }
10481
+ return null;
10482
+ }
10483
+ async function searchEntries(rootDir, filter) {
10484
+ const arcsPath = path23.join(rootDir, ASSESSMENTS_DIR, ARCS_DIR);
10485
+ if (!fs21.existsSync(arcsPath)) return [];
10486
+ const limit = filter.limit || 20;
10487
+ const results = [];
10488
+ const arcDirs = fs21.readdirSync(arcsPath).filter((d) => {
10489
+ try {
10490
+ return fs21.statSync(path23.join(arcsPath, d)).isDirectory();
10491
+ } catch {
10492
+ return false;
10493
+ }
10494
+ });
10495
+ for (const arcDir of arcDirs) {
10496
+ const entriesPath = path23.join(arcsPath, arcDir, "entries");
10497
+ if (!fs21.existsSync(entriesPath)) continue;
10498
+ const files = fs21.readdirSync(entriesPath).filter((f) => f.endsWith(".yaml"));
10499
+ for (const file of files) {
10500
+ try {
10501
+ const entry = yaml12.load(fs21.readFileSync(path23.join(entriesPath, file), "utf8"));
10502
+ if (filter.symbol && !(entry.symbols || []).includes(filter.symbol)) continue;
10503
+ if (filter.tag && !(entry.tags || []).includes(filter.tag)) continue;
10504
+ if (filter.type && entry.type !== filter.type) continue;
10505
+ if (filter.dateFrom && entry.date < filter.dateFrom) continue;
10506
+ if (filter.dateTo && entry.date > filter.dateTo) continue;
10507
+ results.push(entry);
10508
+ } catch {
10509
+ }
10510
+ }
10511
+ }
10512
+ results.sort((a, b) => b.date.localeCompare(a.date));
10513
+ return results.slice(0, limit);
10514
+ }
10515
+ async function rebuildAssessmentIndex(rootDir) {
10516
+ const arcsPath = path23.join(rootDir, ASSESSMENTS_DIR, ARCS_DIR);
10517
+ const assessmentsPath = path23.join(rootDir, ASSESSMENTS_DIR);
10518
+ let totalArcs = 0, totalEntries = 0, activeArcs = 0;
10519
+ const arcSummaries = [];
10520
+ if (fs21.existsSync(arcsPath)) {
10521
+ const arcDirs = fs21.readdirSync(arcsPath).filter((d) => {
10522
+ try {
10523
+ return fs21.statSync(path23.join(arcsPath, d)).isDirectory();
10524
+ } catch {
10525
+ return false;
10526
+ }
10527
+ });
10528
+ for (const arcDir of arcDirs) {
10529
+ const arcFile = path23.join(arcsPath, arcDir, "arc.yaml");
10530
+ if (!fs21.existsSync(arcFile)) continue;
10531
+ try {
10532
+ const arc = yaml12.load(fs21.readFileSync(arcFile, "utf8"));
10533
+ const entriesPath = path23.join(arcsPath, arcDir, "entries");
10534
+ const entryCount = fs21.existsSync(entriesPath) ? fs21.readdirSync(entriesPath).filter((f) => f.endsWith(".yaml")).length : 0;
10535
+ totalArcs++;
10536
+ totalEntries += entryCount;
10537
+ if (arc.status === "active") activeArcs++;
10538
+ arcSummaries.push({ id: arc.id, name: arc.name, status: arc.status, entries: entryCount });
10539
+ } catch {
10540
+ }
10541
+ }
10542
+ }
10543
+ const index = {
10544
+ version: "1.0",
10545
+ total_arcs: totalArcs,
10546
+ total_entries: totalEntries,
10547
+ active_arcs: activeArcs,
10548
+ last_updated: (/* @__PURE__ */ new Date()).toISOString(),
10549
+ arcs: arcSummaries
10550
+ };
10551
+ fs21.mkdirSync(assessmentsPath, { recursive: true });
10552
+ fs21.writeFileSync(path23.join(assessmentsPath, INDEX_FILE), yaml12.dump(index, { lineWidth: -1, noRefs: true }));
10553
+ return index;
10554
+ }
10555
+
10337
10556
  // ../paradigm-mcp/src/tools/assessment.ts
10557
+ import { execSync as execSync4 } from "child_process";
10558
+ import * as os2 from "os";
10559
+ function resolveAuthor() {
10560
+ const envAuthor = process.env.PARADIGM_AUTHOR;
10561
+ if (envAuthor) return sanitize2(envAuthor);
10562
+ try {
10563
+ const gitName = execSync4("git config user.name", { encoding: "utf-8", timeout: 3e3 }).trim();
10564
+ if (gitName) return sanitize2(gitName);
10565
+ } catch {
10566
+ }
10567
+ try {
10568
+ const username = os2.userInfo().username;
10569
+ if (username) return sanitize2(username);
10570
+ } catch {
10571
+ }
10572
+ return "unknown";
10573
+ }
10574
+ function sanitize2(name) {
10575
+ return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 20) || "unknown";
10576
+ }
10338
10577
  function getAssessmentToolsList() {
10339
10578
  return [
10340
10579
  {
10341
10580
  name: "paradigm_assessment_record",
10342
- description: "Add a reflection entry to an assessment arc. Creates the arc if it does not exist (provide arc_name). Returns entry ID. ~150 tokens.",
10581
+ description: "[DEPRECATED \u2014 use paradigm_lore_record with arc:* tags] Add a reflection entry. Forwards to lore with arc:{arc_id} and assessment:{type} tags. ~150 tokens.",
10343
10582
  inputSchema: {
10344
10583
  type: "object",
10345
10584
  properties: {
10346
- arc_id: { type: "string", description: 'Arc ID (e.g., "arc-telemetry"). Created automatically if new.' },
10347
- arc_name: { type: "string", description: "Human-readable arc name (required when creating a new arc)" },
10348
- arc_description: { type: "string", description: "Arc description (used when creating a new arc)" },
10585
+ arc_id: { type: "string", description: "Arc ID (becomes arc:{id} tag on the lore entry)" },
10586
+ arc_name: { type: "string", description: "Human-readable arc name (ignored \u2014 arcs are now just tags)" },
10587
+ arc_description: { type: "string", description: "Arc description (ignored \u2014 arcs are now just tags)" },
10349
10588
  title: { type: "string", description: "Entry title" },
10350
10589
  summary: { type: "string", description: "Short summary (1-2 sentences)" },
10351
10590
  body: { type: "string", description: "Full reflection \u2014 what happened, what was learned, what changed" },
@@ -10353,7 +10592,7 @@ function getAssessmentToolsList() {
10353
10592
  tags: { type: "array", items: { type: "string" } },
10354
10593
  type: { type: "string", enum: ["retro", "insight", "decision", "milestone"], description: "Entry type (default: retro)" },
10355
10594
  linked_lore: { type: "array", items: { type: "string" }, description: "Lore entry IDs" },
10356
- linked_tasks: { type: "array", items: { type: "string" }, description: "Task IDs completed as part of this" },
10595
+ linked_tasks: { type: "array", items: { type: "string" }, description: "Task IDs" },
10357
10596
  linked_commits: { type: "array", items: { type: "string" }, description: "Commit hashes" }
10358
10597
  },
10359
10598
  required: ["arc_id", "title", "summary"]
@@ -10362,7 +10601,7 @@ function getAssessmentToolsList() {
10362
10601
  },
10363
10602
  {
10364
10603
  name: "paradigm_assessment_list",
10365
- description: "List assessment arcs, or entries within a specific arc. Returns arc summaries or entry summaries. ~200 tokens.",
10604
+ description: '[DEPRECATED \u2014 use paradigm_lore_search with tag:"arc:{id}"] List assessment arcs or entries within a specific arc. ~200 tokens.',
10366
10605
  inputSchema: {
10367
10606
  type: "object",
10368
10607
  properties: {
@@ -10375,7 +10614,7 @@ function getAssessmentToolsList() {
10375
10614
  },
10376
10615
  {
10377
10616
  name: "paradigm_assessment_get",
10378
- description: "Get a specific assessment entry or arc detail. Pass an entry ID (A-*) or arc ID (arc-*). Returns full entry or arc with entry list. ~200 tokens.",
10617
+ description: "[DEPRECATED \u2014 use paradigm_lore_get] Get a specific assessment entry or arc detail. ~200 tokens.",
10379
10618
  inputSchema: {
10380
10619
  type: "object",
10381
10620
  properties: {
@@ -10387,7 +10626,7 @@ function getAssessmentToolsList() {
10387
10626
  },
10388
10627
  {
10389
10628
  name: "paradigm_assessment_search",
10390
- description: "Search across all assessment arcs by symbol, tag, date range, or type. Returns matching entries with arc context. ~200 tokens.",
10629
+ description: "[DEPRECATED \u2014 use paradigm_lore_search with tag/type filters] Search across assessment entries by symbol, tag, type, or date. ~200 tokens.",
10391
10630
  inputSchema: {
10392
10631
  type: "object",
10393
10632
  properties: {
@@ -10403,13 +10642,13 @@ function getAssessmentToolsList() {
10403
10642
  },
10404
10643
  {
10405
10644
  name: "paradigm_assessment_arc_create",
10406
- description: "Explicitly create an assessment arc (without adding an entry). Returns arc ID. ~100 tokens.",
10645
+ description: "[DEPRECATED \u2014 arcs are now tag prefixes] No-op. Arcs are just arc:* tags on lore entries. No explicit creation needed. ~100 tokens.",
10407
10646
  inputSchema: {
10408
10647
  type: "object",
10409
10648
  properties: {
10410
- id: { type: "string", description: 'Arc ID (e.g., "arc-telemetry"). Kebab-case, prefixed with "arc-".' },
10411
- name: { type: "string", description: "Human-readable arc name" },
10412
- description: { type: "string", description: "What this arc tracks" },
10649
+ id: { type: "string", description: "Arc ID (no longer needed \u2014 just use arc:{id} tag on lore entries)" },
10650
+ name: { type: "string", description: "Arc name (ignored)" },
10651
+ description: { type: "string", description: "Arc description (ignored)" },
10413
10652
  tags: { type: "array", items: { type: "string" } }
10414
10653
  },
10415
10654
  required: ["id", "name"]
@@ -10418,7 +10657,7 @@ function getAssessmentToolsList() {
10418
10657
  },
10419
10658
  {
10420
10659
  name: "paradigm_assessment_arc_close",
10421
- description: "Mark an assessment arc as complete or archived. Returns confirmation. ~100 tokens.",
10660
+ description: "[DEPRECATED \u2014 use paradigm_lore_search + paradigm_lore_update] Adds arc-closed tag to all entries in the arc. ~100 tokens.",
10422
10661
  inputSchema: {
10423
10662
  type: "object",
10424
10663
  properties: {
@@ -10434,27 +10673,38 @@ function getAssessmentToolsList() {
10434
10673
  async function handleAssessmentTool(name, args, ctx) {
10435
10674
  switch (name) {
10436
10675
  case "paradigm_assessment_record": {
10676
+ const arcId = args.arc_id;
10677
+ const entryType = args.type || "retro";
10678
+ const userTags = args.tags || [];
10679
+ const tags = [
10680
+ `arc:${arcId}`,
10681
+ `assessment:${entryType}`,
10682
+ ...userTags
10683
+ ];
10684
+ const entry = {
10685
+ id: "",
10686
+ type: entryType,
10687
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10688
+ author: resolveAuthor(),
10689
+ agent: { provider: "anthropic", model: "claude-opus-4-6" },
10690
+ title: args.title,
10691
+ summary: args.summary,
10692
+ body: args.body,
10693
+ symbols_touched: args.symbols || [],
10694
+ tags,
10695
+ linked_lore: args.linked_lore,
10696
+ linked_tasks: args.linked_tasks,
10697
+ linked_commits: args.linked_commits
10698
+ };
10437
10699
  try {
10438
- const id = await recordEntry(
10439
- ctx.rootDir,
10440
- {
10441
- arc_id: args.arc_id,
10442
- title: args.title,
10443
- summary: args.summary,
10444
- body: args.body,
10445
- symbols: args.symbols,
10446
- tags: args.tags,
10447
- type: args.type,
10448
- linked_lore: args.linked_lore,
10449
- linked_tasks: args.linked_tasks,
10450
- linked_commits: args.linked_commits
10451
- },
10452
- args.arc_name,
10453
- args.arc_description
10454
- );
10700
+ const id = await recordLoreEntry(ctx.rootDir, entry);
10455
10701
  return {
10456
10702
  handled: true,
10457
- text: JSON.stringify({ recorded: id, arc_id: args.arc_id }, null, 2)
10703
+ text: JSON.stringify({
10704
+ recorded: id,
10705
+ arc_id: arcId,
10706
+ deprecated: 'Use paradigm_lore_record with tags: ["arc:' + arcId + '"] instead'
10707
+ }, null, 2)
10458
10708
  };
10459
10709
  } catch (err2) {
10460
10710
  return {
@@ -10466,88 +10716,160 @@ async function handleAssessmentTool(name, args, ctx) {
10466
10716
  case "paradigm_assessment_list": {
10467
10717
  const arcId = args.arc_id;
10468
10718
  if (arcId) {
10469
- const entries = await loadEntries(ctx.rootDir, arcId);
10470
- const limited2 = entries.slice(0, args.limit || 20);
10471
- const arc = await loadArc(ctx.rootDir, arcId);
10472
- const arcName = arc ? arc.name : arcId;
10473
- const lines2 = [`${limited2.length} entries in "${arcName}" (${arcId}):`];
10474
- for (const e of limited2) {
10475
- lines2.push(` [${e.type}] ${e.id}: ${e.title} (${e.date.slice(0, 10)})`);
10476
- }
10477
- return { handled: true, text: lines2.join("\n") };
10478
- }
10479
- const status = args.status || "active";
10480
- const arcs = await loadArcs(ctx.rootDir, status);
10481
- const limited = arcs.slice(0, args.limit || 20);
10482
- const lines = [`${limited.length} ${status} arc(s):`];
10483
- for (const a of limited) {
10484
- const symbols = a.symbols.length > 0 ? ` [${a.symbols.slice(0, 3).join(", ")}]` : "";
10485
- lines.push(` ${a.id}: ${a.name} (${a.entry_count} entries)${symbols}`);
10719
+ const entries = await loadLoreEntries(ctx.rootDir, {
10720
+ tag: `arc:${arcId}`,
10721
+ limit: args.limit || 20
10722
+ });
10723
+ const lines = [`${entries.length} entries with arc:${arcId} tag:`];
10724
+ for (const e of entries) {
10725
+ lines.push(` [${e.type || "unknown"}] ${e.id}: ${e.title} (${e.timestamp.slice(0, 10)})`);
10726
+ }
10727
+ lines.push("", 'Deprecated: Use paradigm_lore_search with tag: "arc:' + arcId + '"');
10728
+ return { handled: true, text: lines.join("\n") };
10729
+ }
10730
+ try {
10731
+ const status = args.status || "active";
10732
+ const arcs = await loadArcs(ctx.rootDir, status);
10733
+ const limited = arcs.slice(0, args.limit || 20);
10734
+ const lines = [`${limited.length} ${status} arc(s):`];
10735
+ for (const a of limited) {
10736
+ const symbols = a.symbols.length > 0 ? ` [${a.symbols.slice(0, 3).join(", ")}]` : "";
10737
+ lines.push(` ${a.id}: ${a.name} (${a.entry_count} entries)${symbols}`);
10738
+ }
10739
+ lines.push("", 'Deprecated: Run "paradigm lore migrate-assessments" then use paradigm_lore_search');
10740
+ return { handled: true, text: lines.join("\n") };
10741
+ } catch {
10742
+ return { handled: true, text: "No assessment arcs found. Assessments are now unified with lore." };
10486
10743
  }
10487
- return { handled: true, text: lines.join("\n") };
10488
10744
  }
10489
10745
  case "paradigm_assessment_get": {
10490
10746
  const id = args.id;
10747
+ if (id.startsWith("L-")) {
10748
+ const entry = await loadLoreEntry(ctx.rootDir, id);
10749
+ if (entry) {
10750
+ return {
10751
+ handled: true,
10752
+ text: JSON.stringify({
10753
+ entry,
10754
+ deprecated: "Use paradigm_lore_get instead"
10755
+ }, null, 2)
10756
+ };
10757
+ }
10758
+ }
10491
10759
  if (id.startsWith("arc-")) {
10492
- const arc = await loadArc(ctx.rootDir, id);
10493
- if (!arc) {
10760
+ try {
10761
+ const arc = await loadArc(ctx.rootDir, id);
10762
+ if (!arc) {
10763
+ return { handled: true, text: JSON.stringify({ error: `Arc ${id} not found` }) };
10764
+ }
10765
+ const entries = await loadEntries(ctx.rootDir, id);
10766
+ return {
10767
+ handled: true,
10768
+ text: JSON.stringify({
10769
+ arc,
10770
+ entries: entries.map((e) => ({ id: e.id, type: e.type, title: e.title, date: e.date.slice(0, 10), summary: e.summary })),
10771
+ deprecated: 'Run "paradigm lore migrate-assessments" then use paradigm_lore_search with tag: "arc:' + id + '"'
10772
+ }, null, 2)
10773
+ };
10774
+ } catch {
10494
10775
  return { handled: true, text: JSON.stringify({ error: `Arc ${id} not found` }) };
10495
10776
  }
10496
- const entries = await loadEntries(ctx.rootDir, id);
10777
+ }
10778
+ try {
10779
+ const result = await loadEntry(ctx.rootDir, id);
10780
+ if (!result) {
10781
+ return { handled: true, text: JSON.stringify({ error: `Entry ${id} not found` }) };
10782
+ }
10497
10783
  return {
10498
10784
  handled: true,
10499
10785
  text: JSON.stringify({
10500
- arc,
10501
- entries: entries.map((e) => ({ id: e.id, type: e.type, title: e.title, date: e.date.slice(0, 10), summary: e.summary }))
10786
+ entry: result.entry,
10787
+ arc: { id: result.arc.id, name: result.arc.name, status: result.arc.status },
10788
+ deprecated: 'Run "paradigm lore migrate-assessments" then use paradigm_lore_get'
10502
10789
  }, null, 2)
10503
10790
  };
10504
- }
10505
- const result = await loadEntry(ctx.rootDir, id);
10506
- if (!result) {
10791
+ } catch {
10507
10792
  return { handled: true, text: JSON.stringify({ error: `Entry ${id} not found` }) };
10508
10793
  }
10509
- return {
10510
- handled: true,
10511
- text: JSON.stringify({ entry: result.entry, arc: { id: result.arc.id, name: result.arc.name, status: result.arc.status } }, null, 2)
10512
- };
10513
10794
  }
10514
10795
  case "paradigm_assessment_search": {
10515
- const entries = await searchEntries(ctx.rootDir, {
10516
- symbol: args.symbol,
10517
- tag: args.tag,
10518
- type: args.type,
10519
- dateFrom: args.dateFrom,
10520
- dateTo: args.dateTo,
10796
+ const filter = {
10521
10797
  limit: args.limit || 20
10522
- });
10523
- const lines = [`${entries.length} matching entries:`];
10524
- for (const e of entries) {
10525
- const symbols = (e.symbols || []).slice(0, 3).join(", ");
10526
- lines.push(` [${e.type}] ${e.id} (${e.arc_id}): ${e.title} \u2014 ${symbols}`);
10798
+ };
10799
+ if (args.symbol) filter.symbol = args.symbol;
10800
+ if (args.tag) filter.tag = args.tag;
10801
+ if (args.type) filter.tag = `assessment:${args.type}`;
10802
+ if (args.dateFrom) filter.dateFrom = args.dateFrom;
10803
+ if (args.dateTo) filter.dateTo = args.dateTo;
10804
+ const loreEntries = await loadLoreEntries(ctx.rootDir, filter);
10805
+ const arcEntries = loreEntries.filter((e) => e.tags?.some((t) => t.startsWith("arc:")));
10806
+ if (arcEntries.length > 0) {
10807
+ const lines = [`${arcEntries.length} matching lore entries (with arc tags):`];
10808
+ for (const e of arcEntries) {
10809
+ const arcTag = e.tags?.find((t) => t.startsWith("arc:")) || "";
10810
+ const symbols = (e.symbols_touched || []).slice(0, 3).join(", ");
10811
+ lines.push(` [${e.type || "unknown"}] ${e.id} (${arcTag}): ${e.title} \u2014 ${symbols}`);
10812
+ }
10813
+ lines.push("", "Deprecated: Use paradigm_lore_search with tag filter");
10814
+ return { handled: true, text: lines.join("\n") };
10527
10815
  }
10528
- return { handled: true, text: lines.join("\n") };
10529
- }
10530
- case "paradigm_assessment_arc_create": {
10531
10816
  try {
10532
- const arcId = await createArc(ctx.rootDir, {
10533
- id: args.id,
10534
- name: args.name,
10535
- description: args.description,
10536
- tags: args.tags
10817
+ const entries = await searchEntries(ctx.rootDir, {
10818
+ symbol: args.symbol,
10819
+ tag: args.tag,
10820
+ type: args.type,
10821
+ dateFrom: args.dateFrom,
10822
+ dateTo: args.dateTo,
10823
+ limit: args.limit || 20
10537
10824
  });
10538
- return { handled: true, text: JSON.stringify({ created: arcId }, null, 2) };
10539
- } catch (err2) {
10540
- return { handled: true, text: JSON.stringify({ error: err2.message }) };
10825
+ const lines = [`${entries.length} matching entries:`];
10826
+ for (const e of entries) {
10827
+ const symbols = (e.symbols || []).slice(0, 3).join(", ");
10828
+ lines.push(` [${e.type}] ${e.id} (${e.arc_id}): ${e.title} \u2014 ${symbols}`);
10829
+ }
10830
+ lines.push("", 'Deprecated: Run "paradigm lore migrate-assessments" then use paradigm_lore_search');
10831
+ return { handled: true, text: lines.join("\n") };
10832
+ } catch {
10833
+ return { handled: true, text: "0 matching entries." };
10541
10834
  }
10542
10835
  }
10836
+ case "paradigm_assessment_arc_create": {
10837
+ return {
10838
+ handled: true,
10839
+ text: JSON.stringify({
10840
+ message: "Arcs are now tag prefixes on lore entries. No explicit creation needed.",
10841
+ guidance: `To create entries in this arc, use paradigm_lore_record with tags: ["arc:${args.id}"]`,
10842
+ deprecated: true
10843
+ }, null, 2)
10844
+ };
10845
+ }
10543
10846
  case "paradigm_assessment_arc_close": {
10544
10847
  const arcId = args.arc_id;
10545
10848
  const status = args.status || "complete";
10546
- const ok2 = await closeArc(ctx.rootDir, arcId, status);
10547
- if (!ok2) {
10548
- return { handled: true, text: JSON.stringify({ error: `Arc ${arcId} not found` }) };
10849
+ const entries = await loadLoreEntries(ctx.rootDir, { tag: `arc:${arcId}` });
10850
+ let updated = 0;
10851
+ for (const entry of entries) {
10852
+ const currentTags = entry.tags || [];
10853
+ if (!currentTags.includes("arc-closed")) {
10854
+ await updateLoreEntry(ctx.rootDir, entry.id, {
10855
+ tags: [...currentTags, "arc-closed", `arc-status:${status}`]
10856
+ });
10857
+ updated++;
10858
+ }
10859
+ }
10860
+ try {
10861
+ await closeArc(ctx.rootDir, arcId, status);
10862
+ } catch {
10549
10863
  }
10550
- return { handled: true, text: JSON.stringify({ closed: arcId, status }, null, 2) };
10864
+ return {
10865
+ handled: true,
10866
+ text: JSON.stringify({
10867
+ closed: arcId,
10868
+ status,
10869
+ lore_entries_tagged: updated,
10870
+ deprecated: "Use paradigm_lore_search + paradigm_lore_update to manage arc lifecycle via tags"
10871
+ }, null, 2)
10872
+ };
10551
10873
  }
10552
10874
  default:
10553
10875
  return { handled: false, text: "" };
@@ -10564,8 +10886,8 @@ function generateRunId() {
10564
10886
  var TEMPLATE_REGEX = /\{\{([^}]+)\}\}/g;
10565
10887
  function interpolate(value, scope) {
10566
10888
  if (typeof value === "string") {
10567
- return value.replace(TEMPLATE_REGEX, (_match, path25) => {
10568
- const resolved = resolvePath(path25.trim(), scope);
10889
+ return value.replace(TEMPLATE_REGEX, (_match, path26) => {
10890
+ const resolved = resolvePath(path26.trim(), scope);
10569
10891
  return resolved !== void 0 ? String(resolved) : _match;
10570
10892
  });
10571
10893
  }
@@ -10598,8 +10920,8 @@ function resolvePath(dotPath, scope) {
10598
10920
  return void 0;
10599
10921
  }
10600
10922
  }
10601
- function deepGet(obj, path25) {
10602
- const parts = path25.split(/[.\[\]]+/).filter(Boolean);
10923
+ function deepGet(obj, path26) {
10924
+ const parts = path26.split(/[.\[\]]+/).filter(Boolean);
10603
10925
  let current = obj;
10604
10926
  for (const part of parts) {
10605
10927
  if (current == null || typeof current !== "object") return void 0;
@@ -10835,11 +11157,11 @@ async function runPersonaObject(rootDir, persona, options) {
10835
11157
  }
10836
11158
  async function runChain(rootDir, chainId, options) {
10837
11159
  const start = Date.now();
10838
- const fs21 = await import("fs");
10839
- const path25 = await import("path");
10840
- const yaml12 = await import("js-yaml");
10841
- const chainPath = path25.join(rootDir, ".paradigm", "personas", "chains", `${chainId}.yaml`);
10842
- if (!fs21.existsSync(chainPath)) {
11160
+ const fs22 = await import("fs");
11161
+ const path26 = await import("path");
11162
+ const yaml13 = await import("js-yaml");
11163
+ const chainPath = path26.join(rootDir, ".paradigm", "personas", "chains", `${chainId}.yaml`);
11164
+ if (!fs22.existsSync(chainPath)) {
10843
11165
  return {
10844
11166
  chain_id: chainId,
10845
11167
  status: "error",
@@ -10848,7 +11170,7 @@ async function runChain(rootDir, chainId, options) {
10848
11170
  duration_ms: Date.now() - start
10849
11171
  };
10850
11172
  }
10851
- const chain = yaml12.load(fs21.readFileSync(chainPath, "utf8"));
11173
+ const chain = yaml13.load(fs22.readFileSync(chainPath, "utf8"));
10852
11174
  let permutation;
10853
11175
  if (options.permutation && chain.permutations) {
10854
11176
  permutation = chain.permutations.find((p) => p.id === options.permutation);
@@ -10952,8 +11274,8 @@ function validateInterpolation(persona) {
10952
11274
  const serialized = JSON.stringify(step);
10953
11275
  const templates = serialized.match(TEMPLATE_REGEX) || [];
10954
11276
  for (const template of templates) {
10955
- const path25 = template.replace("{{", "").replace("}}", "").trim();
10956
- const [namespace, ...rest] = path25.split(".");
11277
+ const path26 = template.replace("{{", "").replace("}}", "").trim();
11278
+ const [namespace, ...rest] = path26.split(".");
10957
11279
  const key = rest.join(".");
10958
11280
  switch (namespace) {
10959
11281
  case "fixtures":
@@ -11966,8 +12288,8 @@ function summarizeStep(step) {
11966
12288
  }
11967
12289
 
11968
12290
  // ../paradigm-mcp/src/tools/fallback-grep.ts
11969
- import * as path23 from "path";
11970
- import { execSync as execSync4 } from "child_process";
12291
+ import * as path24 from "path";
12292
+ import { execSync as execSync5 } from "child_process";
11971
12293
  function grepForReferences(rootDir, symbol, options = {}) {
11972
12294
  const { maxResults = 20 } = options;
11973
12295
  const results = [];
@@ -11981,7 +12303,7 @@ function grepForReferences(rootDir, symbol, options = {}) {
11981
12303
  let output = "";
11982
12304
  for (const cmd of grepCommands) {
11983
12305
  try {
11984
- output = execSync4(cmd, { encoding: "utf8", maxBuffer: 1024 * 1024 });
12306
+ output = execSync5(cmd, { encoding: "utf8", maxBuffer: 1024 * 1024 });
11985
12307
  if (output.trim()) break;
11986
12308
  } catch {
11987
12309
  continue;
@@ -11995,7 +12317,7 @@ function grepForReferences(rootDir, symbol, options = {}) {
11995
12317
  const match = line.match(/^(.+?):(\d+):(.*)$/);
11996
12318
  if (match) {
11997
12319
  const [, filePath, lineNum, content] = match;
11998
- const relativePath = path23.relative(rootDir, filePath);
12320
+ const relativePath = path24.relative(rootDir, filePath);
11999
12321
  let context2 = "unknown";
12000
12322
  if (relativePath.includes(".purpose") || relativePath.includes("portal.yaml")) {
12001
12323
  context2 = "purpose";
@@ -12648,7 +12970,7 @@ function registerTools(server, getContext2, reloadContext2) {
12648
12970
  const symbols = getSymbolsByType(ctx.index, type);
12649
12971
  examples[type] = symbols.slice(0, 3).map((s) => s.symbol);
12650
12972
  }
12651
- const platform2 = os2.platform();
12973
+ const platform2 = os3.platform();
12652
12974
  const isWindows = platform2 === "win32";
12653
12975
  const shell = isWindows ? "PowerShell/CMD" : platform2 === "darwin" ? "zsh/bash" : "bash";
12654
12976
  let protocols;
@@ -12888,10 +13210,10 @@ Update command:
12888
13210
  trackToolCall(noWsText.length, name);
12889
13211
  return { content: [{ type: "text", text: noWsText }] };
12890
13212
  }
12891
- const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-UAYAEF7M.js");
13213
+ const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-CMZARW5K.js");
12892
13214
  const memberResults = [];
12893
13215
  for (const member of ctx.workspace.config.members) {
12894
- const memberAbsPath = path24.resolve(path24.dirname(ctx.workspace.workspacePath), member.path);
13216
+ const memberAbsPath = path25.resolve(path25.dirname(ctx.workspace.workspacePath), member.path);
12895
13217
  try {
12896
13218
  const result = await rebuildStaticFiles2(memberAbsPath);
12897
13219
  memberResults.push({