@a-company/paradigm 3.17.1 → 3.18.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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  deleteLoreEntry,
4
4
  loadLoreEntry
5
- } from "./chunk-6GWRQWQB.js";
5
+ } from "./chunk-YHRRJM6J.js";
6
6
  import "./chunk-ZXMDA7VB.js";
7
7
 
8
8
  // src/commands/lore/delete.ts
@@ -21,8 +21,8 @@ async function loreDeleteCommand(id, options) {
21
21
  console.log(chalk.cyan(`
22
22
  [dry-run] Would delete lore entry:`));
23
23
  console.log(chalk.white(` ${entry.id} - ${entry.title}`));
24
- console.log(chalk.gray(` Type: ${entry.type} | Author: ${entry.author.id} | ${entry.timestamp}`));
25
- console.log(chalk.gray(` Symbols: ${entry.symbols_touched.join(", ")}`));
24
+ console.log(chalk.gray(` Type: ${entry.type} | Author: ${entry.author} | ${entry.timestamp}`));
25
+ console.log(chalk.gray(` Symbols: ${(entry.symbols_touched || []).join(", ")}`));
26
26
  console.log(chalk.cyan(`
27
27
  [dry-run] No changes made.
28
28
  `));
@@ -32,8 +32,8 @@ async function loreDeleteCommand(id, options) {
32
32
  console.log(chalk.yellow(`
33
33
  Will delete lore entry:`));
34
34
  console.log(chalk.white(` ${entry.id} - ${entry.title}`));
35
- console.log(chalk.gray(` Type: ${entry.type} | Author: ${entry.author.id} | ${entry.timestamp}`));
36
- console.log(chalk.gray(` Symbols: ${entry.symbols_touched.join(", ")}`));
35
+ console.log(chalk.gray(` Type: ${entry.type} | Author: ${entry.author} | ${entry.timestamp}`));
36
+ console.log(chalk.gray(` Symbols: ${(entry.symbols_touched || []).join(", ")}`));
37
37
  console.log(chalk.gray(`
38
38
  Use --yes to confirm deletion.
39
39
  `));
@@ -6,6 +6,7 @@ import {
6
6
  DEFAULT_SERVER_CONFIG,
7
7
  FlowTracker,
8
8
  IncidentGrouper,
9
+ PARADIGM_SCHEMA,
9
10
  PatternImporter,
10
11
  PatternMatcher,
11
12
  PatternSuggester,
@@ -26,7 +27,7 @@ import {
26
27
  loadServerConfig,
27
28
  loadUniversalPatterns,
28
29
  writeConfig
29
- } from "./chunk-ZRPEI35Q.js";
30
+ } from "./chunk-BKMNLROM.js";
30
31
  export {
31
32
  ContextEnricher,
32
33
  DEFAULT_AUTH_CONFIG,
@@ -34,6 +35,7 @@ export {
34
35
  DEFAULT_SERVER_CONFIG,
35
36
  FlowTracker,
36
37
  IncidentGrouper,
38
+ PARADIGM_SCHEMA,
37
39
  PatternImporter,
38
40
  PatternMatcher,
39
41
  PatternSuggester,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  loadLoreEntry,
4
4
  updateLoreEntry
5
- } from "./chunk-6GWRQWQB.js";
5
+ } from "./chunk-YHRRJM6J.js";
6
6
  import "./chunk-ZXMDA7VB.js";
7
7
 
8
8
  // src/commands/lore/edit.ts
package/dist/index.js CHANGED
@@ -621,35 +621,35 @@ triageCmd.option("-l, --limit <number>", "Maximum incidents to show", "10").opti
621
621
  });
622
622
  var loreCmd = program.command("lore").description("Project lore - timeline of everything that happened to this project");
623
623
  loreCmd.command("list").alias("ls").description("List recent lore entries").option("--author <author>", "Filter by author").option("--type <type>", "Filter by type: agent-session, human-note, decision, review, incident, milestone").option("--symbol <symbol>", "Filter by symbol").option("--tags <tags>", "Filter by tags (comma-separated)").option("--from <date>", "Filter from date (ISO format, e.g., 2026-02-20)").option("--to <date>", "Filter to date (ISO format)").option("-l, --limit <number>", "Number of entries", "20").option("--json", "Output as JSON").action(async (options) => {
624
- const { loreListCommand } = await import("./list-Q4R7L7WJ.js");
624
+ const { loreListCommand } = await import("./list-RHYZPKG3.js");
625
625
  await loreListCommand(options);
626
626
  });
627
627
  loreCmd.command("show <id>").description("Show full detail for a lore entry").option("--json", "Output as JSON").action(async (id, options) => {
628
- const { loreShowCommand } = await import("./show-CJGHREFS.js");
628
+ const { loreShowCommand } = await import("./show-6CHTSR33.js");
629
629
  await loreShowCommand(id, options);
630
630
  });
631
- loreCmd.command("record").description("Record a new lore entry (human note, milestone, etc.)").option("--type <type>", "Entry type: human-note, decision, milestone", "human-note").option("--author <author>", "Author name").option("--title <title>", "Entry title").option("--summary <summary>", "Entry summary").option("--symbols <symbols>", "Comma-separated symbols").option("--tags <tags>", "Comma-separated tags").option("--files-modified <files>", "Comma-separated files modified").option("--files-created <files>", "Comma-separated files created").option("--commit <hash>", "Git commit hash").option("--learnings <items>", "Comma-separated learnings").option("--duration <minutes>", "Duration in minutes").action(async (options) => {
632
- const { loreRecordCommand } = await import("./record-YJ3D3462.js");
631
+ loreCmd.command("record").description("Record a new lore entry (human note, milestone, etc.)").option("--type <type>", "Entry type: human-note, decision, milestone", "human-note").option("--author <author>", "Author name").option("--title <title>", "Entry title").option("--summary <summary>", "Entry summary").option("--symbols <symbols>", "Comma-separated symbols").option("--tags <tags>", "Comma-separated tags").option("--files-modified <files>", "Comma-separated files modified").option("--files-created <files>", "Comma-separated files created").option("--commit <hash>", "Git commit hash").option("--learnings <items>", "Comma-separated learnings").option("--duration <minutes>", "Duration in minutes").option("--meta <json>", `Project-defined metadata as JSON (e.g., '{"sprint": 12}')`).action(async (options) => {
632
+ const { loreRecordCommand } = await import("./record-PGVYYZFU.js");
633
633
  await loreRecordCommand(options);
634
634
  });
635
635
  loreCmd.command("review <id>").description("Add a review to a lore entry").option("--reviewer <name>", "Reviewer name").option("--completeness <n>", "Completeness score (1-5)", "3").option("--quality <n>", "Quality score (1-5)", "3").option("--notes <text>", "Review notes").action(async (id, options) => {
636
- const { loreReviewCommand } = await import("./review-3OW3KVW7.js");
636
+ const { loreReviewCommand } = await import("./review-BRY5R45L.js");
637
637
  await loreReviewCommand(id, options);
638
638
  });
639
639
  loreCmd.command("edit <id>").description("Edit an existing lore entry").option("--title <title>", "New title").option("--summary <summary>", "New summary").option("--type <type>", "New type: agent-session, human-note, decision, review, incident, milestone").option("--symbols <symbols>", "Comma-separated symbols").option("--tags <tags>", "Comma-separated tags").option("--learnings <items>", "Comma-separated learnings").action(async (id, options) => {
640
- const { loreEditCommand } = await import("./edit-7FSQNAPE.js");
640
+ const { loreEditCommand } = await import("./edit-GJYLJYDU.js");
641
641
  await loreEditCommand(id, options);
642
642
  });
643
643
  loreCmd.command("delete <id>").description("Delete a lore entry").option("-y, --yes", "Skip confirmation").option("--dry-run", "Show what would be deleted without making changes").action(async (id, options) => {
644
- const { loreDeleteCommand } = await import("./delete-OINCSDQH.js");
644
+ const { loreDeleteCommand } = await import("./delete-2PX6DDAY.js");
645
645
  await loreDeleteCommand(id, options);
646
646
  });
647
647
  loreCmd.command("timeline").description("Show lore timeline grouped by date with hot symbols and authors").option("-l, --limit <number>", "Number of entries", "20").option("--json", "Output as JSON").action(async (options) => {
648
- const { loreTimelineCommand } = await import("./timeline-ELO5JTQO.js");
648
+ const { loreTimelineCommand } = await import("./timeline-HC527YXE.js");
649
649
  await loreTimelineCommand(options);
650
650
  });
651
651
  loreCmd.option("-p, --port <port>", "Port to run on", "3840").option("--no-open", "Don't open browser automatically").action(async (options) => {
652
- const { loreServeCommand } = await import("./serve-GCCMOIHR.js");
652
+ const { loreServeCommand } = await import("./serve-KBMKF4KG.js");
653
653
  await loreServeCommand(void 0, options);
654
654
  });
655
655
  var habitsCmd = program.command("habits").description("Behavioral habits - practice tracking and compliance");
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  loadLoreEntries
4
- } from "./chunk-6GWRQWQB.js";
4
+ } from "./chunk-YHRRJM6J.js";
5
5
  import "./chunk-ZXMDA7VB.js";
6
6
 
7
7
  // src/commands/lore/list.ts
@@ -42,11 +42,11 @@ async function loreListCommand(options) {
42
42
  const date = new Date(entry.timestamp);
43
43
  const dateStr = date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
44
44
  const timeStr = date.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" });
45
- const authorIcon = entry.author.type === "agent" ? "\u{1F916}" : "\u{1F464}";
45
+ const authorIcon = entry.agent ? "\u{1F916}" : "\u{1F464}";
46
46
  const verifyIcon = entry.verification?.status === "pass" ? chalk.green("\u2713") : entry.verification?.status === "fail" ? chalk.red("\u2717") : entry.verification?.status === "partial" ? chalk.yellow("\u26A0") : chalk.gray("\xB7");
47
47
  const reviewStr = entry.review ? chalk.yellow("\u2605".repeat(entry.review.quality) + "\u2606".repeat(5 - entry.review.quality)) : "";
48
48
  console.log(` ${chalk.gray(entry.id)} ${colorFn(entry.type.padEnd(14))} ${verifyIcon} ${chalk.white(entry.title)}`);
49
- console.log(` ${chalk.gray(dateStr + " " + timeStr)} ${authorIcon} ${chalk.gray(entry.author.id)} ${entry.symbols_touched.map((s) => chalk.cyan(s)).join(" ")} ${reviewStr}`);
49
+ console.log(` ${chalk.gray(dateStr + " " + timeStr)} ${authorIcon} ${chalk.gray(entry.author)} ${(entry.symbols_touched || []).map((s) => chalk.cyan(s)).join(" ")} ${reviewStr}`);
50
50
  console.log();
51
51
  }
52
52
  }
@@ -15,6 +15,36 @@ import * as path from "path";
15
15
  import * as yaml from "js-yaml";
16
16
  var LORE_DIR = ".paradigm/lore";
17
17
  var ENTRIES_DIR = "entries";
18
+ function isLoreFile(filename) {
19
+ return filename.endsWith(".yaml") || filename.endsWith(".lore");
20
+ }
21
+ function normalizeEntry(raw) {
22
+ const author = raw.author;
23
+ if (typeof author === "object" && author && !Array.isArray(author)) {
24
+ const old = author;
25
+ if (old.type === "agent") {
26
+ raw.author = "unknown";
27
+ const model = old.model || old.id || "unknown";
28
+ const lower = model.toLowerCase();
29
+ let provider = "unknown";
30
+ if (lower.includes("claude") || lower.includes("anthropic")) provider = "anthropic";
31
+ else if (lower.includes("gpt") || lower.includes("openai")) provider = "openai";
32
+ raw.agent = { provider, model };
33
+ } else {
34
+ raw.author = old.id || "unknown";
35
+ }
36
+ delete raw.assistedBy;
37
+ }
38
+ return raw;
39
+ }
40
+ function resolveEntryPath(projectDir, dateStr, entryId) {
41
+ const dirPath = path.join(projectDir, LORE_DIR, ENTRIES_DIR, dateStr);
42
+ const lorePath = path.join(dirPath, `${entryId}.lore`);
43
+ if (fs.existsSync(lorePath)) return lorePath;
44
+ const yamlPath = path.join(dirPath, `${entryId}.yaml`);
45
+ if (fs.existsSync(yamlPath)) return yamlPath;
46
+ return null;
47
+ }
18
48
  function loadAllEntries(projectDir) {
19
49
  const entriesPath = path.join(projectDir, LORE_DIR, ENTRIES_DIR);
20
50
  if (!fs.existsSync(entriesPath)) {
@@ -24,12 +54,12 @@ function loadAllEntries(projectDir) {
24
54
  const dateDirs = fs.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
25
55
  for (const dateDir of dateDirs) {
26
56
  const dirPath = path.join(entriesPath, dateDir);
27
- const files = fs.readdirSync(dirPath).filter((f) => f.endsWith(".yaml")).sort();
57
+ const files = fs.readdirSync(dirPath).filter(isLoreFile).sort();
28
58
  for (const file of files) {
29
59
  try {
30
60
  const content = fs.readFileSync(path.join(dirPath, file), "utf8");
31
- const entry = yaml.load(content);
32
- entries.push(entry);
61
+ const raw = yaml.load(content);
62
+ entries.push(normalizeEntry(raw));
33
63
  } catch {
34
64
  }
35
65
  }
@@ -40,16 +70,22 @@ function createLoreRouter(projectDir) {
40
70
  const router = Router();
41
71
  router.get("/", (req, res) => {
42
72
  let entries = loadAllEntries(projectDir);
43
- const { author, authorType, symbol, type, from, to, tags, hasReview, limit, offset } = req.query;
73
+ const { author, authorType, hasAgent, symbol, type, from, to, tags, hasReview, limit, offset } = req.query;
44
74
  if (author) {
45
- entries = entries.filter((e) => e.author.id === author);
75
+ entries = entries.filter((e) => e.author === author);
46
76
  }
47
- if (authorType) {
48
- entries = entries.filter((e) => e.author.type === authorType);
77
+ if (hasAgent !== void 0) {
78
+ entries = entries.filter(
79
+ (e) => hasAgent === "true" ? e.agent != null : e.agent == null
80
+ );
81
+ } else if (authorType) {
82
+ entries = entries.filter(
83
+ (e) => authorType === "agent" ? e.agent != null : e.agent == null
84
+ );
49
85
  }
50
86
  if (symbol) {
51
87
  entries = entries.filter(
52
- (e) => e.symbols_touched.includes(symbol) || e.symbols_created?.includes(symbol)
88
+ (e) => e.symbols_touched?.includes(symbol) || e.symbols_created?.includes(symbol)
53
89
  );
54
90
  }
55
91
  if (type) {
@@ -96,8 +132,10 @@ function createLoreRouter(projectDir) {
96
132
  const entries = loadAllEntries(projectDir);
97
133
  const symbolCounts = {};
98
134
  for (const entry of entries) {
99
- for (const sym of entry.symbols_touched) {
100
- symbolCounts[sym] = (symbolCounts[sym] || 0) + 1;
135
+ if (entry.symbols_touched) {
136
+ for (const sym of entry.symbols_touched) {
137
+ symbolCounts[sym] = (symbolCounts[sym] || 0) + 1;
138
+ }
101
139
  }
102
140
  if (entry.symbols_created) {
103
141
  for (const sym of entry.symbols_created) {
@@ -112,11 +150,12 @@ function createLoreRouter(projectDir) {
112
150
  const entries = loadAllEntries(projectDir);
113
151
  const authorMap = {};
114
152
  for (const entry of entries) {
115
- const aid = entry.author.id;
153
+ const aid = entry.author;
116
154
  if (!authorMap[aid]) {
117
- authorMap[aid] = { type: entry.author.type, count: 0, lastActive: entry.timestamp };
155
+ authorMap[aid] = { hasAgent: entry.agent != null, count: 0, lastActive: entry.timestamp };
118
156
  }
119
157
  authorMap[aid].count++;
158
+ if (entry.agent != null) authorMap[aid].hasAgent = true;
120
159
  if (entry.timestamp > authorMap[aid].lastActive) {
121
160
  authorMap[aid].lastActive = entry.timestamp;
122
161
  }
@@ -142,8 +181,8 @@ function createLoreRouter(projectDir) {
142
181
  return;
143
182
  }
144
183
  const dateStr = entry.timestamp.slice(0, 10);
145
- const entryPath = path.join(projectDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
146
- if (!fs.existsSync(entryPath)) {
184
+ const entryPath = resolveEntryPath(projectDir, dateStr, entryId);
185
+ if (!entryPath) {
147
186
  res.status(404).json({ error: "Entry file not found" });
148
187
  return;
149
188
  }
@@ -195,6 +234,28 @@ import * as os from "os";
195
234
  var LORE_DIR2 = ".paradigm/lore";
196
235
  var ENTRIES_DIR2 = "entries";
197
236
  var SESSION_GAP_MS = 4 * 60 * 60 * 1e3;
237
+ function isLoreFile2(filename) {
238
+ return filename.endsWith(".yaml") || filename.endsWith(".lore");
239
+ }
240
+ function normalizeEntry2(raw) {
241
+ const author = raw.author;
242
+ if (typeof author === "object" && author && !Array.isArray(author)) {
243
+ const old = author;
244
+ if (old.type === "agent") {
245
+ raw.author = "unknown";
246
+ const model = old.model || old.id || "unknown";
247
+ const lower = model.toLowerCase();
248
+ let provider = "unknown";
249
+ if (lower.includes("claude") || lower.includes("anthropic")) provider = "anthropic";
250
+ else if (lower.includes("gpt") || lower.includes("openai")) provider = "openai";
251
+ raw.agent = { provider, model };
252
+ } else {
253
+ raw.author = old.id || "unknown";
254
+ }
255
+ delete raw.assistedBy;
256
+ }
257
+ return raw;
258
+ }
198
259
  function loadAllEntries2(projectDir) {
199
260
  const entriesPath = path3.join(projectDir, LORE_DIR2, ENTRIES_DIR2);
200
261
  if (!fs3.existsSync(entriesPath)) {
@@ -204,12 +265,12 @@ function loadAllEntries2(projectDir) {
204
265
  const dateDirs = fs3.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
205
266
  for (const dateDir of dateDirs) {
206
267
  const dirPath = path3.join(entriesPath, dateDir);
207
- const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".yaml")).sort();
268
+ const files = fs3.readdirSync(dirPath).filter(isLoreFile2).sort();
208
269
  for (const file of files) {
209
270
  try {
210
271
  const content = fs3.readFileSync(path3.join(dirPath, file), "utf8");
211
- const entry = yaml3.load(content);
212
- entries.push(entry);
272
+ const raw = yaml3.load(content);
273
+ entries.push(normalizeEntry2(raw));
213
274
  } catch {
214
275
  }
215
276
  }
@@ -250,7 +311,7 @@ function deriveSessionsFromEntries(entries, breadcrumbs) {
250
311
  const prev = sorted[i - 1];
251
312
  const curr = sorted[i];
252
313
  const gap = new Date(curr.timestamp).getTime() - new Date(prev.timestamp).getTime();
253
- const sameAuthor = curr.author.id === prev.author.id;
314
+ const sameAuthor = curr.author === prev.author;
254
315
  if (gap <= SESSION_GAP_MS && sameAuthor) {
255
316
  currentGroup.push(curr);
256
317
  } else {
@@ -267,6 +328,7 @@ function deriveSessionsFromEntries(entries, breadcrumbs) {
267
328
  }
268
329
  function groupToSession(group) {
269
330
  const allSymbols = /* @__PURE__ */ new Set();
331
+ let hasAgent = false;
270
332
  for (const entry of group) {
271
333
  if (entry.symbols_touched) {
272
334
  for (const sym of entry.symbols_touched) allSymbols.add(sym);
@@ -274,14 +336,15 @@ function groupToSession(group) {
274
336
  if (entry.symbols_created) {
275
337
  for (const sym of entry.symbols_created) allSymbols.add(sym);
276
338
  }
339
+ if (entry.agent) hasAgent = true;
277
340
  }
278
341
  const startTime = group[0].timestamp;
279
342
  const endTime = group[group.length - 1].timestamp;
280
343
  const date = startTime.slice(0, 10);
281
344
  return {
282
- id: `session-${date}-${group[0].author.id}-${group[0].id.slice(0, 8)}`,
345
+ id: `session-${date}-${group[0].author}-${group[0].id.slice(0, 8)}`,
283
346
  date,
284
- author: { type: group[0].author.type, id: group[0].author.id },
347
+ author: { name: group[0].author, hasAgent },
285
348
  startTime,
286
349
  endTime,
287
350
  entryCount: group.length,
package/dist/mcp.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  StatsCalculator,
25
25
  TimelineBuilder,
26
26
  loadAllSeedPatterns
27
- } from "./chunk-ZRPEI35Q.js";
27
+ } from "./chunk-BKMNLROM.js";
28
28
  import {
29
29
  addStep,
30
30
  addToolBreadcrumb,
@@ -92,7 +92,7 @@ import {
92
92
  validatePersona,
93
93
  validateProtocol,
94
94
  validatePurposeFile
95
- } from "./chunk-D4VBBKGV.js";
95
+ } from "./chunk-TUW27EIC.js";
96
96
  import {
97
97
  getPluginUpdateNotice,
98
98
  schedulePluginUpdateCheck
@@ -2033,7 +2033,7 @@ function registerResources(server, getContext2) {
2033
2033
  }
2034
2034
 
2035
2035
  // ../paradigm-mcp/src/tools/index.ts
2036
- import * as os from "os";
2036
+ import * as os2 from "os";
2037
2037
  import * as path24 from "path";
2038
2038
  import {
2039
2039
  ListToolsRequestSchema,
@@ -8215,6 +8215,26 @@ function runPostflightCheck(filesModified, symbolsTouched, ctx) {
8215
8215
  }
8216
8216
 
8217
8217
  // ../paradigm-mcp/src/tools/lore.ts
8218
+ import { execSync as execSync2 } from "child_process";
8219
+ import * as os from "os";
8220
+ function resolveAuthorForMcp() {
8221
+ const envAuthor = process.env.PARADIGM_AUTHOR;
8222
+ if (envAuthor) return sanitize(envAuthor);
8223
+ try {
8224
+ const gitName = execSync2("git config user.name", { encoding: "utf-8", timeout: 3e3 }).trim();
8225
+ if (gitName) return sanitize(gitName);
8226
+ } catch {
8227
+ }
8228
+ try {
8229
+ const username = os.userInfo().username;
8230
+ if (username) return sanitize(username);
8231
+ } catch {
8232
+ }
8233
+ return "unknown";
8234
+ }
8235
+ function sanitize(name) {
8236
+ return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 20) || "unknown";
8237
+ }
8218
8238
  function getLoreToolsList() {
8219
8239
  return [
8220
8240
  {
@@ -8229,12 +8249,16 @@ function getLoreToolsList() {
8229
8249
  },
8230
8250
  author: {
8231
8251
  type: "string",
8232
- description: 'Filter by author ID (e.g., "ascend", "claude-opus-4")'
8252
+ description: 'Filter by author (human user name, e.g., "ascend")'
8253
+ },
8254
+ hasAgent: {
8255
+ type: "boolean",
8256
+ description: "Filter by AI assistance: true = AI-assisted entries, false = human-only"
8233
8257
  },
8234
8258
  authorType: {
8235
8259
  type: "string",
8236
8260
  enum: ["human", "agent"],
8237
- description: "Filter by author type"
8261
+ description: "(Deprecated, use hasAgent) Filter by old author type"
8238
8262
  },
8239
8263
  type: {
8240
8264
  type: "string",
@@ -8363,6 +8387,10 @@ function getLoreToolsList() {
8363
8387
  type: "array",
8364
8388
  items: { type: "string" },
8365
8389
  description: "Tags for categorization"
8390
+ },
8391
+ meta: {
8392
+ type: "object",
8393
+ description: 'Project-defined metadata (open-ended key-value pairs, e.g., { meeting_type: "design-review", sprint: 12 })'
8366
8394
  }
8367
8395
  },
8368
8396
  required: ["type", "title", "summary", "symbols_touched"]
@@ -8397,7 +8425,7 @@ function getLoreToolsList() {
8397
8425
  properties: {
8398
8426
  id: {
8399
8427
  type: "string",
8400
- description: 'Lore entry ID (e.g., "L-2026-02-23-001")'
8428
+ description: 'Lore entry ID (e.g., "L-2026-02-23-001" or "L-2026-03-02-ascend-143025-001")'
8401
8429
  }
8402
8430
  },
8403
8431
  required: ["id"]
@@ -8499,6 +8527,7 @@ async function handleLoreTool(name, args, ctx) {
8499
8527
  case "paradigm_lore_search": {
8500
8528
  const filter = {
8501
8529
  author: args.author,
8530
+ hasAgent: args.hasAgent,
8502
8531
  authorType: args.authorType,
8503
8532
  symbol: args.symbol,
8504
8533
  dateFrom: args.dateFrom,
@@ -8538,7 +8567,8 @@ async function handleLoreTool(name, args, ctx) {
8538
8567
  errors_encountered,
8539
8568
  learnings,
8540
8569
  verification,
8541
- tags
8570
+ tags,
8571
+ meta
8542
8572
  } = args;
8543
8573
  let habit_compliance;
8544
8574
  try {
@@ -8563,7 +8593,8 @@ async function handleLoreTool(name, args, ctx) {
8563
8593
  type,
8564
8594
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
8565
8595
  duration_minutes,
8566
- author: { type: "agent", id: "claude", model: "claude-opus-4-6" },
8596
+ author: resolveAuthorForMcp(),
8597
+ agent: { provider: "anthropic", model: "claude-opus-4-6" },
8567
8598
  title,
8568
8599
  summary,
8569
8600
  symbols_touched,
@@ -8578,6 +8609,7 @@ async function handleLoreTool(name, args, ctx) {
8578
8609
  learnings,
8579
8610
  verification,
8580
8611
  tags,
8612
+ meta: meta || void 0,
8581
8613
  habit_compliance
8582
8614
  };
8583
8615
  const id = await recordLoreEntry(ctx.rootDir, entry);
@@ -8618,11 +8650,12 @@ async function handleLoreTool(name, args, ctx) {
8618
8650
  const hotSymbols = Object.entries(symbolCounts).sort(([, a], [, b]) => b - a).slice(0, 10).map(([symbol, count]) => ({ symbol, count }));
8619
8651
  const authorActivity = {};
8620
8652
  for (const entry of entries) {
8621
- const aid = entry.author.id;
8653
+ const aid = entry.author;
8622
8654
  if (!authorActivity[aid]) {
8623
- authorActivity[aid] = { count: 0, lastActive: entry.timestamp, type: entry.author.type };
8655
+ authorActivity[aid] = { count: 0, lastActive: entry.timestamp, hasAgent: entry.agent != null };
8624
8656
  }
8625
8657
  authorActivity[aid].count++;
8658
+ if (entry.agent) authorActivity[aid].hasAgent = true;
8626
8659
  if (entry.timestamp > authorActivity[aid].lastActive) {
8627
8660
  authorActivity[aid].lastActive = entry.timestamp;
8628
8661
  }
@@ -8635,7 +8668,7 @@ async function handleLoreTool(name, args, ctx) {
8635
8668
  hotSymbols,
8636
8669
  authors: Object.entries(authorActivity).map(([id, info]) => ({
8637
8670
  id,
8638
- type: info.type,
8671
+ hasAgent: info.hasAgent,
8639
8672
  entries: info.count,
8640
8673
  lastActive: info.lastActive
8641
8674
  }))
@@ -8708,6 +8741,7 @@ function summarizeEntry(entry) {
8708
8741
  title: entry.title,
8709
8742
  summary: entry.summary,
8710
8743
  author: entry.author,
8744
+ agent: entry.agent,
8711
8745
  timestamp: entry.timestamp,
8712
8746
  duration_minutes: entry.duration_minutes,
8713
8747
  symbols_touched: entry.symbols_touched,
@@ -8723,7 +8757,7 @@ function summarizeEntry(entry) {
8723
8757
  // ../paradigm-mcp/src/tools/habits.ts
8724
8758
  import * as fs19 from "fs";
8725
8759
  import * as path21 from "path";
8726
- import { execSync as execSync2 } from "child_process";
8760
+ import { execSync as execSync3 } from "child_process";
8727
8761
  function getHabitsToolsList() {
8728
8762
  return [
8729
8763
  {
@@ -8927,7 +8961,7 @@ async function handleHabitsCheck(args, ctx) {
8927
8961
  ].some((k) => taskLower.includes(k));
8928
8962
  let gitClean;
8929
8963
  try {
8930
- const status = execSync2("git status --porcelain", {
8964
+ const status = execSync3("git status --porcelain", {
8931
8965
  cwd: ctx.rootDir,
8932
8966
  encoding: "utf8",
8933
8967
  timeout: 5e3
@@ -10980,7 +11014,7 @@ var PERSONA_SCHEMA = {
10980
11014
  var sentinelSchemaRegistered = false;
10981
11015
  async function emitPersonaEvents(result) {
10982
11016
  try {
10983
- const { SentinelStorage: SentinelStorage2 } = await import("./dist-YHDSIZQD.js");
11017
+ const { SentinelStorage: SentinelStorage2 } = await import("./dist-IKBGY7FQ.js");
10984
11018
  const storage2 = new SentinelStorage2();
10985
11019
  if (!sentinelSchemaRegistered) {
10986
11020
  try {
@@ -11933,7 +11967,7 @@ function summarizeStep(step) {
11933
11967
 
11934
11968
  // ../paradigm-mcp/src/tools/fallback-grep.ts
11935
11969
  import * as path23 from "path";
11936
- import { execSync as execSync3 } from "child_process";
11970
+ import { execSync as execSync4 } from "child_process";
11937
11971
  function grepForReferences(rootDir, symbol, options = {}) {
11938
11972
  const { maxResults = 20 } = options;
11939
11973
  const results = [];
@@ -11947,7 +11981,7 @@ function grepForReferences(rootDir, symbol, options = {}) {
11947
11981
  let output = "";
11948
11982
  for (const cmd of grepCommands) {
11949
11983
  try {
11950
- output = execSync3(cmd, { encoding: "utf8", maxBuffer: 1024 * 1024 });
11984
+ output = execSync4(cmd, { encoding: "utf8", maxBuffer: 1024 * 1024 });
11951
11985
  if (output.trim()) break;
11952
11986
  } catch {
11953
11987
  continue;
@@ -12614,7 +12648,7 @@ function registerTools(server, getContext2, reloadContext2) {
12614
12648
  const symbols = getSymbolsByType(ctx.index, type);
12615
12649
  examples[type] = symbols.slice(0, 3).map((s) => s.symbol);
12616
12650
  }
12617
- const platform2 = os.platform();
12651
+ const platform2 = os2.platform();
12618
12652
  const isWindows = platform2 === "win32";
12619
12653
  const shell = isWindows ? "PowerShell/CMD" : platform2 === "darwin" ? "zsh/bash" : "bash";
12620
12654
  let protocols;
@@ -12854,7 +12888,7 @@ Update command:
12854
12888
  trackToolCall(noWsText.length, name);
12855
12889
  return { content: [{ type: "text", text: noWsText }] };
12856
12890
  }
12857
- const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-T4N3NG73.js");
12891
+ const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-UAYAEF7M.js");
12858
12892
  const memberResults = [];
12859
12893
  for (const member of ctx.workspace.config.members) {
12860
12894
  const memberAbsPath = path24.resolve(path24.dirname(ctx.workspace.workspacePath), member.path);
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- recordLore
4
- } from "./chunk-6GWRQWQB.js";
3
+ recordLore,
4
+ resolveAuthor
5
+ } from "./chunk-YHRRJM6J.js";
5
6
  import "./chunk-ZXMDA7VB.js";
6
7
 
7
8
  // src/commands/lore/record.ts
@@ -14,10 +15,7 @@ async function loreRecordCommand(options) {
14
15
  type: options.type || "human-note",
15
16
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
16
17
  duration_minutes: options.duration ? parseInt(options.duration, 10) : void 0,
17
- author: {
18
- type: "human",
19
- id: options.author || "unknown"
20
- },
18
+ author: options.author || resolveAuthor(),
21
19
  title: options.title || "Untitled",
22
20
  summary: options.summary || "",
23
21
  symbols_touched: options.symbols ? options.symbols.split(",").map((s) => s.trim()) : [],
@@ -25,7 +23,9 @@ async function loreRecordCommand(options) {
25
23
  files_created: options.filesCreated ? options.filesCreated.split(",").map((f) => f.trim()) : void 0,
26
24
  commit: options.commit || void 0,
27
25
  learnings: options.learnings ? options.learnings.split(",").map((l) => l.trim()) : void 0,
28
- tags: options.tags ? options.tags.split(",").map((t) => t.trim()) : void 0
26
+ tags: options.tags ? options.tags.split(",").map((t) => t.trim()) : void 0,
27
+ meta: options.meta ? JSON.parse(options.meta) : void 0
28
+ // git_context is auto-captured by recordLore
29
29
  };
30
30
  await recordLore(rootDir, entry);
31
31
  console.log(chalk.green(`
@@ -3,7 +3,7 @@ import {
3
3
  getReindexToolsList,
4
4
  handleReindexTool,
5
5
  rebuildStaticFiles
6
- } from "./chunk-D4VBBKGV.js";
6
+ } from "./chunk-TUW27EIC.js";
7
7
  export {
8
8
  getReindexToolsList,
9
9
  handleReindexTool,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  addReview
4
- } from "./chunk-6GWRQWQB.js";
4
+ } from "./chunk-YHRRJM6J.js";
5
5
  import "./chunk-ZXMDA7VB.js";
6
6
 
7
7
  // src/commands/lore/review.ts
@@ -9,7 +9,7 @@ async function loreServeCommand(path, options) {
9
9
  const shouldOpen = options.open !== false;
10
10
  console.log(chalk.cyan("\nStarting Lore Timeline...\n"));
11
11
  try {
12
- const { startLoreServer } = await import("./lore-server-BLJWN7PY.js");
12
+ const { startLoreServer } = await import("./lore-server-XEW7EG62.js");
13
13
  console.log(chalk.gray(`Project: ${projectDir}`));
14
14
  console.log(chalk.gray(`Port: ${port}`));
15
15
  console.log();