@a-company/paradigm 3.17.2 → 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.
Files changed (27) hide show
  1. package/dist/chunk-3DYYXGDC.js +403 -0
  2. package/dist/{chunk-ZRPEI35Q.js → chunk-BKMNLROM.js} +533 -5
  3. package/dist/{chunk-IWDLTLZH.js → chunk-BRILIG7Z.js} +155 -32
  4. package/dist/{chunk-D4VBBKGV.js → chunk-EZ6XW6FB.js} +150 -409
  5. package/dist/{delete-KBKPTIMU.js → delete-YTASL4SM.js} +3 -3
  6. package/dist/{dist-YHDSIZQD.js → dist-IKBGY7FQ.js} +3 -1
  7. package/dist/{edit-Y6SKWVHI.js → edit-S7NZD7H7.js} +1 -1
  8. package/dist/index.js +18 -10
  9. package/dist/{list-SLAH7X7N.js → list-CAL7KS7B.js} +3 -3
  10. package/dist/lore-loader-S5BXMH27.js +21 -0
  11. package/dist/{lore-server-WFU4H5DI.js → lore-server-2NYDLGCJ.js} +102 -17
  12. package/dist/mcp.js +503 -147
  13. package/dist/migrate-assessments-FPR6C35Z.js +97 -0
  14. package/dist/{record-PLZ2OQAN.js → record-UGN75GTB.js} +10 -7
  15. package/dist/{reindex-T4N3NG73.js → reindex-CMZARW5K.js} +2 -1
  16. package/dist/retag-URLJLMSK.js +62 -0
  17. package/dist/{review-Z4Z37PD5.js → review-725ZKA7U.js} +1 -1
  18. package/dist/{serve-BU43NO7D.js → serve-GUJ3L3IG.js} +1 -1
  19. package/dist/{show-WGDIK56Q.js → show-GEVVQWWG.js} +54 -5
  20. package/dist/{timeline-X3CZM7MW.js → timeline-B6TMGWRU.js} +9 -8
  21. package/dist/university-content/courses/para-501.json +30 -30
  22. package/dist/university-content/plsat/v3.0.json +26 -26
  23. package/lore-ui/dist/assets/{index-CB4RregB.js → index-CDr7Tr1E.js} +10 -10
  24. package/lore-ui/dist/index.html +1 -1
  25. package/package.json +1 -1
  26. package/dist/assessment-loader-C5EOUM47.js +0 -23
  27. package/dist/chunk-DSXS42FY.js +0 -283
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  deleteLoreEntry,
4
4
  loadLoreEntry
5
- } from "./chunk-IWDLTLZH.js";
5
+ } from "./chunk-BRILIG7Z.js";
6
6
  import "./chunk-ZXMDA7VB.js";
7
7
 
8
8
  // src/commands/lore/delete.ts
@@ -21,7 +21,7 @@ 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}`));
24
+ console.log(chalk.gray(` Type: ${entry.type} | Author: ${entry.author} | ${entry.timestamp}`));
25
25
  console.log(chalk.gray(` Symbols: ${(entry.symbols_touched || []).join(", ")}`));
26
26
  console.log(chalk.cyan(`
27
27
  [dry-run] No changes made.
@@ -32,7 +32,7 @@ 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}`));
35
+ console.log(chalk.gray(` Type: ${entry.type} | Author: ${entry.author} | ${entry.timestamp}`));
36
36
  console.log(chalk.gray(` Symbols: ${(entry.symbols_touched || []).join(", ")}`));
37
37
  console.log(chalk.gray(`
38
38
  Use --yes to confirm deletion.
@@ -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-IWDLTLZH.js";
5
+ } from "./chunk-BRILIG7Z.js";
6
6
  import "./chunk-ZXMDA7VB.js";
7
7
 
8
8
  // src/commands/lore/edit.ts
package/dist/index.js CHANGED
@@ -620,36 +620,44 @@ triageCmd.option("-l, --limit <number>", "Maximum incidents to show", "10").opti
620
620
  await triageListCommand(options);
621
621
  });
622
622
  var loreCmd = program.command("lore").description("Project lore - timeline of everything that happened to this project");
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-SLAH7X7N.js");
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, retro, insight").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-CAL7KS7B.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-WGDIK56Q.js");
628
+ const { loreShowCommand } = await import("./show-GEVVQWWG.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-PLZ2OQAN.js");
631
+ loreCmd.command("record").description("Record a new lore entry (human note, milestone, etc.)").option("--type <type>", "Entry type: human-note, decision, milestone, retro, insight", "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}')`).option("--body <text>", "Long-form content (detailed notes, rationale, etc.)").option("--link-lore <ids>", "Comma-separated lore entry IDs to link").option("--link-commits <shas>", "Comma-separated git commit SHAs to link").action(async (options) => {
632
+ const { loreRecordCommand } = await import("./record-UGN75GTB.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-Z4Z37PD5.js");
636
+ const { loreReviewCommand } = await import("./review-725ZKA7U.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-Y6SKWVHI.js");
640
+ const { loreEditCommand } = await import("./edit-S7NZD7H7.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-KBKPTIMU.js");
644
+ const { loreDeleteCommand } = await import("./delete-YTASL4SM.js");
645
645
  await loreDeleteCommand(id, options);
646
646
  });
647
+ loreCmd.command("migrate-assessments").description("Migrate assessment entries to lore with arc: tags").option("--dry-run", "Show what would be migrated without making changes").action(async (options) => {
648
+ const { loreMigrateAssessmentsCommand } = await import("./migrate-assessments-FPR6C35Z.js");
649
+ await loreMigrateAssessmentsCommand(options);
650
+ });
651
+ loreCmd.command("retag").description("Add or remove tags from matching lore entries").option("--add <tag>", "Tag to add").option("--remove <tag>", "Tag to remove").option("--type <type>", "Filter by entry type").option("--symbol <symbol>", "Filter by symbol").option("--author <author>", "Filter by author").option("--from <date>", "Filter from date").option("--to <date>", "Filter to date").option("--tags <tags>", "Filter by existing tags (comma-separated)").option("--dry-run", "Show what would change without making changes").action(async (options) => {
652
+ const { loreRetagCommand } = await import("./retag-URLJLMSK.js");
653
+ await loreRetagCommand(options);
654
+ });
647
655
  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-X3CZM7MW.js");
656
+ const { loreTimelineCommand } = await import("./timeline-B6TMGWRU.js");
649
657
  await loreTimelineCommand(options);
650
658
  });
651
659
  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-BU43NO7D.js");
660
+ const { loreServeCommand } = await import("./serve-GUJ3L3IG.js");
653
661
  await loreServeCommand(void 0, options);
654
662
  });
655
663
  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-IWDLTLZH.js";
4
+ } from "./chunk-BRILIG7Z.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
  }
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ addLoreReview,
4
+ deleteLoreEntry,
5
+ loadLoreEntries,
6
+ loadLoreEntry,
7
+ loadLoreTimeline,
8
+ rebuildTimeline,
9
+ recordLoreEntry,
10
+ updateLoreEntry
11
+ } from "./chunk-3DYYXGDC.js";
12
+ export {
13
+ addLoreReview,
14
+ deleteLoreEntry,
15
+ loadLoreEntries,
16
+ loadLoreEntry,
17
+ loadLoreTimeline,
18
+ rebuildTimeline,
19
+ recordLoreEntry,
20
+ updateLoreEntry
21
+ };
@@ -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,12 +70,18 @@ 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, tag, from, to, tags, hasReview, hasBody, 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(
@@ -55,6 +91,17 @@ function createLoreRouter(projectDir) {
55
91
  if (type) {
56
92
  entries = entries.filter((e) => e.type === type);
57
93
  }
94
+ if (tag) {
95
+ const prefix = tag;
96
+ entries = entries.filter(
97
+ (e) => e.tags?.some((t) => t === prefix || t.startsWith(prefix + ":") || prefix.includes(":") && t === prefix)
98
+ );
99
+ }
100
+ if (hasBody === "true") {
101
+ entries = entries.filter((e) => e.body != null && e.body.length > 0);
102
+ } else if (hasBody === "false") {
103
+ entries = entries.filter((e) => !e.body || e.body.length === 0);
104
+ }
58
105
  if (from) {
59
106
  const fromDate = new Date(from).getTime();
60
107
  entries = entries.filter((e) => new Date(e.timestamp).getTime() >= fromDate);
@@ -110,15 +157,29 @@ function createLoreRouter(projectDir) {
110
157
  const symbols = Object.entries(symbolCounts).map(([symbol, count]) => ({ symbol, count })).sort((a, b) => b.count - a.count);
111
158
  res.json({ symbols });
112
159
  });
160
+ router.get("/tags", (_req, res) => {
161
+ const entries = loadAllEntries(projectDir);
162
+ const tagCounts = {};
163
+ for (const entry of entries) {
164
+ if (entry.tags) {
165
+ for (const tag of entry.tags) {
166
+ tagCounts[tag] = (tagCounts[tag] || 0) + 1;
167
+ }
168
+ }
169
+ }
170
+ const tags = Object.entries(tagCounts).map(([tag, count]) => ({ tag, count })).sort((a, b) => b.count - a.count);
171
+ res.json({ tags });
172
+ });
113
173
  router.get("/authors", (_req, res) => {
114
174
  const entries = loadAllEntries(projectDir);
115
175
  const authorMap = {};
116
176
  for (const entry of entries) {
117
- const aid = entry.author.id;
177
+ const aid = entry.author;
118
178
  if (!authorMap[aid]) {
119
- authorMap[aid] = { type: entry.author.type, count: 0, lastActive: entry.timestamp };
179
+ authorMap[aid] = { hasAgent: entry.agent != null, count: 0, lastActive: entry.timestamp };
120
180
  }
121
181
  authorMap[aid].count++;
182
+ if (entry.agent != null) authorMap[aid].hasAgent = true;
122
183
  if (entry.timestamp > authorMap[aid].lastActive) {
123
184
  authorMap[aid].lastActive = entry.timestamp;
124
185
  }
@@ -144,8 +205,8 @@ function createLoreRouter(projectDir) {
144
205
  return;
145
206
  }
146
207
  const dateStr = entry.timestamp.slice(0, 10);
147
- const entryPath = path.join(projectDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
148
- if (!fs.existsSync(entryPath)) {
208
+ const entryPath = resolveEntryPath(projectDir, dateStr, entryId);
209
+ if (!entryPath) {
149
210
  res.status(404).json({ error: "Entry file not found" });
150
211
  return;
151
212
  }
@@ -197,6 +258,28 @@ import * as os from "os";
197
258
  var LORE_DIR2 = ".paradigm/lore";
198
259
  var ENTRIES_DIR2 = "entries";
199
260
  var SESSION_GAP_MS = 4 * 60 * 60 * 1e3;
261
+ function isLoreFile2(filename) {
262
+ return filename.endsWith(".yaml") || filename.endsWith(".lore");
263
+ }
264
+ function normalizeEntry2(raw) {
265
+ const author = raw.author;
266
+ if (typeof author === "object" && author && !Array.isArray(author)) {
267
+ const old = author;
268
+ if (old.type === "agent") {
269
+ raw.author = "unknown";
270
+ const model = old.model || old.id || "unknown";
271
+ const lower = model.toLowerCase();
272
+ let provider = "unknown";
273
+ if (lower.includes("claude") || lower.includes("anthropic")) provider = "anthropic";
274
+ else if (lower.includes("gpt") || lower.includes("openai")) provider = "openai";
275
+ raw.agent = { provider, model };
276
+ } else {
277
+ raw.author = old.id || "unknown";
278
+ }
279
+ delete raw.assistedBy;
280
+ }
281
+ return raw;
282
+ }
200
283
  function loadAllEntries2(projectDir) {
201
284
  const entriesPath = path3.join(projectDir, LORE_DIR2, ENTRIES_DIR2);
202
285
  if (!fs3.existsSync(entriesPath)) {
@@ -206,12 +289,12 @@ function loadAllEntries2(projectDir) {
206
289
  const dateDirs = fs3.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
207
290
  for (const dateDir of dateDirs) {
208
291
  const dirPath = path3.join(entriesPath, dateDir);
209
- const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".yaml")).sort();
292
+ const files = fs3.readdirSync(dirPath).filter(isLoreFile2).sort();
210
293
  for (const file of files) {
211
294
  try {
212
295
  const content = fs3.readFileSync(path3.join(dirPath, file), "utf8");
213
- const entry = yaml3.load(content);
214
- entries.push(entry);
296
+ const raw = yaml3.load(content);
297
+ entries.push(normalizeEntry2(raw));
215
298
  } catch {
216
299
  }
217
300
  }
@@ -252,7 +335,7 @@ function deriveSessionsFromEntries(entries, breadcrumbs) {
252
335
  const prev = sorted[i - 1];
253
336
  const curr = sorted[i];
254
337
  const gap = new Date(curr.timestamp).getTime() - new Date(prev.timestamp).getTime();
255
- const sameAuthor = curr.author.id === prev.author.id;
338
+ const sameAuthor = curr.author === prev.author;
256
339
  if (gap <= SESSION_GAP_MS && sameAuthor) {
257
340
  currentGroup.push(curr);
258
341
  } else {
@@ -269,6 +352,7 @@ function deriveSessionsFromEntries(entries, breadcrumbs) {
269
352
  }
270
353
  function groupToSession(group) {
271
354
  const allSymbols = /* @__PURE__ */ new Set();
355
+ let hasAgent = false;
272
356
  for (const entry of group) {
273
357
  if (entry.symbols_touched) {
274
358
  for (const sym of entry.symbols_touched) allSymbols.add(sym);
@@ -276,14 +360,15 @@ function groupToSession(group) {
276
360
  if (entry.symbols_created) {
277
361
  for (const sym of entry.symbols_created) allSymbols.add(sym);
278
362
  }
363
+ if (entry.agent) hasAgent = true;
279
364
  }
280
365
  const startTime = group[0].timestamp;
281
366
  const endTime = group[group.length - 1].timestamp;
282
367
  const date = startTime.slice(0, 10);
283
368
  return {
284
- id: `session-${date}-${group[0].author.id}-${group[0].id.slice(0, 8)}`,
369
+ id: `session-${date}-${group[0].author}-${group[0].id.slice(0, 8)}`,
285
370
  date,
286
- author: { type: group[0].author.type, id: group[0].author.id },
371
+ author: { name: group[0].author, hasAgent },
287
372
  startTime,
288
373
  endTime,
289
374
  entryCount: group.length,