@a-company/paradigm 2.0.13 → 3.0.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/{auto-IU7VN55K.js → auto-6MOGYQ4G.js} +34 -0
- package/dist/chunk-27OSFWHG.js +199 -0
- package/dist/{chunk-753RICFF.js → chunk-2NMUSZFA.js} +1 -1
- package/dist/{chunk-2M6OSOIG.js → chunk-4WR7X3FE.js} +46 -0
- package/dist/{chunk-YDNKXH4Z.js → chunk-A5BKW7QV.js} +33 -0
- package/dist/{chunk-THFVK5AE.js → chunk-CH6VCTXQ.js} +1 -1
- package/dist/{chunk-5GOA7WYD.js → chunk-MOZPTZ77.js} +1 -1
- package/dist/{chunk-ELLR7WP6.js → chunk-S65LENNL.js} +4 -4
- package/dist/{dist-7MPIRMTZ-IOQOREMZ.js → dist-2F7NO4H4-KSL6SJIO.js} +156 -4182
- package/dist/{doctor-6Y6L6HEB.js → doctor-QMPFQONP.js} +2 -2
- package/dist/{hooks-MBWE4ILT.js → hooks-7TQIRXXS.js} +1 -1
- package/dist/index.js +56 -35
- package/dist/list-QMUE7DPK.js +53 -0
- package/dist/lore-server-3TAIUZ3Y.js +292 -0
- package/dist/mcp.js +856 -114
- package/dist/{promote-Z52ZJTJU.js → promote-E6NBZ3BK.js} +1 -0
- package/dist/record-5CTCDFUO.js +32 -0
- package/dist/review-QEDNQAIO.js +33 -0
- package/dist/{sentinel-LCFD56OJ.js → sentinel-J64XJVTU.js} +1 -1
- package/dist/serve-WCIRW244.js +36 -0
- package/dist/server-SKGY7GFZ.js +269 -0
- package/dist/server-VUYAY7TP.js +6135 -0
- package/dist/{shift-HKIAP4ZN.js → shift-BJKPOYEF.js} +11 -5
- package/dist/show-S653P3TO.js +127 -0
- package/dist/{summary-H6J6N6PJ.js → summary-ZIEIBCAF.js} +1 -1
- package/dist/{sync-BEOCW7TZ.js → sync-PF3MJ3E4.js} +2 -2
- package/dist/{triage-ETVXXFMV.js → triage-RM5KNG5V.js} +30 -31
- package/dist/{university-R2WDQLSI.js → university-IXTJCROL.js} +1 -1
- package/dist/{upgrade-5B3YGGC6.js → upgrade-X4PVS7UV.js} +1 -1
- package/dist/{watch-6IIWPWDN.js → watch-QYGAIYZ3.js} +1 -1
- package/lore-ui/dist/assets/index-DcT8TINz.js +56 -0
- package/lore-ui/dist/assets/index-DyJhpQ5w.css +1 -0
- package/lore-ui/dist/index.html +13 -0
- package/package.json +5 -2
- package/dist/chunk-ILOWBJRC.js +0 -12
- package/dist/chunk-MQWH7PFI.js +0 -13366
- package/dist/server-F5ITNK6T.js +0 -9846
- package/dist/server-T6WIFYRQ.js +0 -16076
|
@@ -450,6 +450,40 @@ Skipped ${skipped.length} existing file(s). Use --force to overwrite.`));
|
|
|
450
450
|
fs.writeFileSync(g.path, g.content);
|
|
451
451
|
}
|
|
452
452
|
spinner.succeed(chalk.green(`Generated ${generated.length} .purpose file(s)`));
|
|
453
|
+
if (options.init) {
|
|
454
|
+
const portalPath = path.join(rootDir, "portal.yaml");
|
|
455
|
+
const portalExists = fs.existsSync(portalPath);
|
|
456
|
+
if (portalExists && !options.force) {
|
|
457
|
+
console.log(chalk.gray("\nportal.yaml already exists. Use --force to overwrite."));
|
|
458
|
+
} else {
|
|
459
|
+
const portalGates = {};
|
|
460
|
+
const portalRoutes = {};
|
|
461
|
+
for (const gate of gates) {
|
|
462
|
+
portalGates[`^${gate.id}`] = {
|
|
463
|
+
description: gate.description,
|
|
464
|
+
check: `// TODO: implement ${gate.id} check`,
|
|
465
|
+
prizes: []
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
for (const route of routes) {
|
|
469
|
+
if (route.description.startsWith("GET ") || route.description.startsWith("POST ") || route.description.startsWith("PUT ") || route.description.startsWith("PATCH ") || route.description.startsWith("DELETE ")) {
|
|
470
|
+
const routeKey = route.description;
|
|
471
|
+
const gateRefs = gates.length > 0 ? gates.map((g) => `^${g.id}`) : ["# TODO: add gates"];
|
|
472
|
+
portalRoutes[routeKey] = gateRefs;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
if (Object.keys(portalGates).length > 0 || Object.keys(portalRoutes).length > 0) {
|
|
476
|
+
const portalData = { version: "1.0" };
|
|
477
|
+
if (Object.keys(portalGates).length > 0) portalData.gates = portalGates;
|
|
478
|
+
if (Object.keys(portalRoutes).length > 0) portalData.routes = portalRoutes;
|
|
479
|
+
const portalContent = yaml.dump(portalData, { lineWidth: -1, noRefs: true });
|
|
480
|
+
fs.writeFileSync(portalPath, portalContent);
|
|
481
|
+
spinner.succeed(chalk.green(`Generated portal.yaml with ${Object.keys(portalGates).length} gates and ${Object.keys(portalRoutes).length} routes`));
|
|
482
|
+
} else {
|
|
483
|
+
console.log(chalk.gray("\nNo gates or routes detected for portal.yaml."));
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
453
487
|
console.log(chalk.gray("\nNext steps:"));
|
|
454
488
|
console.log(chalk.gray(" 1. Review generated files and adjust descriptions"));
|
|
455
489
|
console.log(chalk.gray(" 2. Run `paradigm lint` to validate"));
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/core/lore/storage.ts
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import * as yaml from "js-yaml";
|
|
7
|
+
|
|
8
|
+
// src/core/lore/filter.ts
|
|
9
|
+
function applyLoreFilter(entries, filter) {
|
|
10
|
+
let result = entries;
|
|
11
|
+
if (filter.author) {
|
|
12
|
+
result = result.filter((e) => e.author.id === filter.author);
|
|
13
|
+
}
|
|
14
|
+
if (filter.authorType) {
|
|
15
|
+
result = result.filter((e) => e.author.type === filter.authorType);
|
|
16
|
+
}
|
|
17
|
+
if (filter.symbol) {
|
|
18
|
+
result = result.filter(
|
|
19
|
+
(e) => e.symbols_touched.includes(filter.symbol) || e.symbols_created?.includes(filter.symbol)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
if (filter.dateFrom) {
|
|
23
|
+
const from = new Date(filter.dateFrom).getTime();
|
|
24
|
+
result = result.filter((e) => new Date(e.timestamp).getTime() >= from);
|
|
25
|
+
}
|
|
26
|
+
if (filter.dateTo) {
|
|
27
|
+
const to = new Date(filter.dateTo).getTime();
|
|
28
|
+
result = result.filter((e) => new Date(e.timestamp).getTime() <= to);
|
|
29
|
+
}
|
|
30
|
+
if (filter.type) {
|
|
31
|
+
result = result.filter((e) => e.type === filter.type);
|
|
32
|
+
}
|
|
33
|
+
if (filter.tags && filter.tags.length > 0) {
|
|
34
|
+
result = result.filter(
|
|
35
|
+
(e) => filter.tags.some((tag) => e.tags?.includes(tag))
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
if (filter.hasReview !== void 0) {
|
|
39
|
+
result = result.filter(
|
|
40
|
+
(e) => filter.hasReview ? e.review != null : e.review == null
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (filter.minCompleteness !== void 0) {
|
|
44
|
+
result = result.filter(
|
|
45
|
+
(e) => e.review != null && e.review.completeness >= filter.minCompleteness
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
result.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
49
|
+
if (filter.offset) {
|
|
50
|
+
result = result.slice(filter.offset);
|
|
51
|
+
}
|
|
52
|
+
if (filter.limit) {
|
|
53
|
+
result = result.slice(0, filter.limit);
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/core/lore/storage.ts
|
|
59
|
+
var LORE_DIR = ".paradigm/lore";
|
|
60
|
+
var ENTRIES_DIR = "entries";
|
|
61
|
+
var TIMELINE_FILE = "timeline.yaml";
|
|
62
|
+
async function recordLore(rootDir, entry) {
|
|
63
|
+
const lorePath = path.join(rootDir, LORE_DIR);
|
|
64
|
+
const dateStr = entry.timestamp.slice(0, 10);
|
|
65
|
+
const datePath = path.join(lorePath, ENTRIES_DIR, dateStr);
|
|
66
|
+
if (!fs.existsSync(datePath)) {
|
|
67
|
+
fs.mkdirSync(datePath, { recursive: true });
|
|
68
|
+
}
|
|
69
|
+
if (!entry.id) {
|
|
70
|
+
entry.id = generateLoreId(rootDir, dateStr);
|
|
71
|
+
}
|
|
72
|
+
const entryPath = path.join(datePath, `${entry.id}.yaml`);
|
|
73
|
+
fs.writeFileSync(entryPath, yaml.dump(entry, { lineWidth: -1, noRefs: true }));
|
|
74
|
+
await rebuildTimeline(rootDir);
|
|
75
|
+
}
|
|
76
|
+
async function loadLoreEntries(rootDir, filter) {
|
|
77
|
+
const entriesPath = path.join(rootDir, LORE_DIR, ENTRIES_DIR);
|
|
78
|
+
if (!fs.existsSync(entriesPath)) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
const entries = [];
|
|
82
|
+
const dateDirs = fs.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
|
|
83
|
+
for (const dateDir of dateDirs) {
|
|
84
|
+
if (filter?.dateFrom && dateDir < filter.dateFrom.slice(0, 10)) continue;
|
|
85
|
+
if (filter?.dateTo && dateDir > filter.dateTo.slice(0, 10)) continue;
|
|
86
|
+
const dirPath = path.join(entriesPath, dateDir);
|
|
87
|
+
const files = fs.readdirSync(dirPath).filter((f) => f.endsWith(".yaml")).sort();
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
try {
|
|
90
|
+
const content = fs.readFileSync(path.join(dirPath, file), "utf8");
|
|
91
|
+
const entry = yaml.load(content);
|
|
92
|
+
entries.push(entry);
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return filter ? applyLoreFilter(entries, filter) : entries;
|
|
98
|
+
}
|
|
99
|
+
async function rebuildTimeline(rootDir) {
|
|
100
|
+
const lorePath = path.join(rootDir, LORE_DIR);
|
|
101
|
+
const entriesPath = path.join(lorePath, ENTRIES_DIR);
|
|
102
|
+
if (!fs.existsSync(entriesPath)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const authors = /* @__PURE__ */ new Set();
|
|
106
|
+
let entryCount = 0;
|
|
107
|
+
let lastUpdated = "";
|
|
108
|
+
const dateDirs = fs.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d));
|
|
109
|
+
for (const dateDir of dateDirs) {
|
|
110
|
+
const dirPath = path.join(entriesPath, dateDir);
|
|
111
|
+
const files = fs.readdirSync(dirPath).filter((f) => f.endsWith(".yaml"));
|
|
112
|
+
for (const file of files) {
|
|
113
|
+
try {
|
|
114
|
+
const content = fs.readFileSync(path.join(dirPath, file), "utf8");
|
|
115
|
+
const entry = yaml.load(content);
|
|
116
|
+
authors.add(entry.author.id);
|
|
117
|
+
entryCount++;
|
|
118
|
+
if (!lastUpdated || entry.timestamp > lastUpdated) {
|
|
119
|
+
lastUpdated = entry.timestamp;
|
|
120
|
+
}
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
let project = "unknown";
|
|
126
|
+
const configPath = path.join(rootDir, ".paradigm", "config.yaml");
|
|
127
|
+
if (fs.existsSync(configPath)) {
|
|
128
|
+
try {
|
|
129
|
+
const config = yaml.load(fs.readFileSync(configPath, "utf8"));
|
|
130
|
+
project = config.project || config.name || "unknown";
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const timeline = {
|
|
135
|
+
version: "1.0",
|
|
136
|
+
project,
|
|
137
|
+
entries: entryCount,
|
|
138
|
+
last_updated: lastUpdated || (/* @__PURE__ */ new Date()).toISOString(),
|
|
139
|
+
authors: Array.from(authors)
|
|
140
|
+
};
|
|
141
|
+
if (!fs.existsSync(lorePath)) {
|
|
142
|
+
fs.mkdirSync(lorePath, { recursive: true });
|
|
143
|
+
}
|
|
144
|
+
fs.writeFileSync(
|
|
145
|
+
path.join(lorePath, TIMELINE_FILE),
|
|
146
|
+
yaml.dump(timeline, { lineWidth: -1, noRefs: true })
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
async function addReview(rootDir, entryId, review) {
|
|
150
|
+
const entries = await loadLoreEntries(rootDir);
|
|
151
|
+
const entry = entries.find((e) => e.id === entryId);
|
|
152
|
+
if (!entry) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const dateStr = entry.timestamp.slice(0, 10);
|
|
156
|
+
const entryPath = path.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
|
|
157
|
+
if (!fs.existsSync(entryPath)) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
entry.review = review;
|
|
161
|
+
fs.writeFileSync(entryPath, yaml.dump(entry, { lineWidth: -1, noRefs: true }));
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
async function loadLoreEntry(rootDir, entryId) {
|
|
165
|
+
const dateMatch = entryId.match(/^L-(\d{4}-\d{2}-\d{2})-/);
|
|
166
|
+
if (dateMatch) {
|
|
167
|
+
const dateStr = dateMatch[1];
|
|
168
|
+
const entryPath = path.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
|
|
169
|
+
if (fs.existsSync(entryPath)) {
|
|
170
|
+
try {
|
|
171
|
+
const content = fs.readFileSync(entryPath, "utf8");
|
|
172
|
+
return yaml.load(content);
|
|
173
|
+
} catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const entries = await loadLoreEntries(rootDir);
|
|
179
|
+
return entries.find((e) => e.id === entryId) || null;
|
|
180
|
+
}
|
|
181
|
+
function generateLoreId(rootDir, dateStr) {
|
|
182
|
+
const datePath = path.join(rootDir, LORE_DIR, ENTRIES_DIR, dateStr);
|
|
183
|
+
if (!fs.existsSync(datePath)) {
|
|
184
|
+
return `L-${dateStr}-001`;
|
|
185
|
+
}
|
|
186
|
+
const existing = fs.readdirSync(datePath).filter((f) => f.startsWith("L-") && f.endsWith(".yaml")).map((f) => {
|
|
187
|
+
const match = f.match(/L-\d{4}-\d{2}-\d{2}-(\d+)\.yaml/);
|
|
188
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
189
|
+
});
|
|
190
|
+
const next = existing.length > 0 ? Math.max(...existing) + 1 : 1;
|
|
191
|
+
return `L-${dateStr}-${String(next).padStart(3, "0")}`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export {
|
|
195
|
+
recordLore,
|
|
196
|
+
loadLoreEntries,
|
|
197
|
+
addReview,
|
|
198
|
+
loadLoreEntry
|
|
199
|
+
};
|
|
@@ -113,6 +113,7 @@ var CLAUDE_CODE_STOP_HOOK = `#!/bin/sh
|
|
|
113
113
|
# 4. Aspect anchor files that no longer exist
|
|
114
114
|
# 5. Per-directory .purpose freshness (tracked via .pending-review)
|
|
115
115
|
# 6. Aspect coverage advisory
|
|
116
|
+
# 7. Lore entry expected for significant sessions (3+ source files)
|
|
116
117
|
|
|
117
118
|
# Read JSON from stdin (hook input)
|
|
118
119
|
INPUT=$(cat)
|
|
@@ -334,6 +335,27 @@ if [ "$HAS_ASPECTS" = true ] && [ "$SOURCE_COUNT" -gt 0 ]; then
|
|
|
334
335
|
fi
|
|
335
336
|
fi
|
|
336
337
|
|
|
338
|
+
# --- Check 7: Lore entry expected for significant sessions ---
|
|
339
|
+
if [ "$SOURCE_COUNT" -ge 3 ] && [ -d ".paradigm/lore" ]; then
|
|
340
|
+
LORE_RECORDED=false
|
|
341
|
+
for file in $MODIFIED; do
|
|
342
|
+
case "$file" in
|
|
343
|
+
.paradigm/lore/entries/*.yaml|.paradigm/lore/entries/*/*.yaml)
|
|
344
|
+
LORE_RECORDED=true
|
|
345
|
+
break
|
|
346
|
+
;;
|
|
347
|
+
esac
|
|
348
|
+
done
|
|
349
|
+
|
|
350
|
+
if [ "$LORE_RECORDED" = false ]; then
|
|
351
|
+
VIOLATIONS="$VIOLATIONS
|
|
352
|
+
- You modified $SOURCE_COUNT source files but recorded no lore entry.
|
|
353
|
+
Record your session: paradigm_lore_record (MCP) or paradigm lore record (CLI).
|
|
354
|
+
Include: type, title, summary, and symbols_touched."
|
|
355
|
+
VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
|
|
356
|
+
fi
|
|
357
|
+
fi
|
|
358
|
+
|
|
337
359
|
# --- Final verdict ---
|
|
338
360
|
if [ "$VIOLATION_COUNT" -gt 0 ]; then
|
|
339
361
|
echo "" >&2
|
|
@@ -350,6 +372,7 @@ if [ "$VIOLATION_COUNT" -gt 0 ]; then
|
|
|
350
372
|
echo " 2. paradigm_purpose_add_aspect \u2014 register cross-cutting concerns (with anchors)" >&2
|
|
351
373
|
echo " 3. paradigm_portal_add_route \u2014 register new endpoints with gates" >&2
|
|
352
374
|
echo " 4. paradigm_reindex \u2014 rebuild indexes after updates" >&2
|
|
375
|
+
echo " 5. paradigm_lore_record \u2014 record session lore entry" >&2
|
|
353
376
|
exit 2
|
|
354
377
|
fi
|
|
355
378
|
|
|
@@ -525,6 +548,7 @@ var CURSOR_STOP_HOOK = `#!/bin/sh
|
|
|
525
548
|
# 4. Aspect anchor files that no longer exist
|
|
526
549
|
# 5. Per-directory .purpose freshness (tracked via .pending-review)
|
|
527
550
|
# 6. Aspect coverage advisory
|
|
551
|
+
# 7. Lore entry expected for significant sessions (3+ source files)
|
|
528
552
|
|
|
529
553
|
# Read JSON from stdin (hook input)
|
|
530
554
|
INPUT=$(cat)
|
|
@@ -746,6 +770,27 @@ if [ "$HAS_ASPECTS" = true ] && [ "$SOURCE_COUNT" -gt 0 ]; then
|
|
|
746
770
|
fi
|
|
747
771
|
fi
|
|
748
772
|
|
|
773
|
+
# --- Check 7: Lore entry expected for significant sessions ---
|
|
774
|
+
if [ "$SOURCE_COUNT" -ge 3 ] && [ -d ".paradigm/lore" ]; then
|
|
775
|
+
LORE_RECORDED=false
|
|
776
|
+
for file in $MODIFIED; do
|
|
777
|
+
case "$file" in
|
|
778
|
+
.paradigm/lore/entries/*.yaml|.paradigm/lore/entries/*/*.yaml)
|
|
779
|
+
LORE_RECORDED=true
|
|
780
|
+
break
|
|
781
|
+
;;
|
|
782
|
+
esac
|
|
783
|
+
done
|
|
784
|
+
|
|
785
|
+
if [ "$LORE_RECORDED" = false ]; then
|
|
786
|
+
VIOLATIONS="$VIOLATIONS
|
|
787
|
+
- You modified $SOURCE_COUNT source files but recorded no lore entry.
|
|
788
|
+
Record your session: paradigm_lore_record (MCP) or paradigm lore record (CLI).
|
|
789
|
+
Include: type, title, summary, and symbols_touched."
|
|
790
|
+
VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
|
|
791
|
+
fi
|
|
792
|
+
fi
|
|
793
|
+
|
|
749
794
|
# --- Final verdict ---
|
|
750
795
|
if [ "$VIOLATION_COUNT" -gt 0 ]; then
|
|
751
796
|
echo "" >&2
|
|
@@ -762,6 +807,7 @@ if [ "$VIOLATION_COUNT" -gt 0 ]; then
|
|
|
762
807
|
echo " 2. paradigm_purpose_add_aspect \u2014 register cross-cutting concerns (with anchors)" >&2
|
|
763
808
|
echo " 3. paradigm_portal_add_route \u2014 register new endpoints with gates" >&2
|
|
764
809
|
echo " 4. paradigm_reindex \u2014 rebuild indexes after updates" >&2
|
|
810
|
+
echo " 5. paradigm_lore_record \u2014 record session lore entry" >&2
|
|
765
811
|
exit 2
|
|
766
812
|
fi
|
|
767
813
|
|
|
@@ -1514,6 +1514,7 @@ var ClaudeAdapter = class {
|
|
|
1514
1514
|
sections.push(".paradigm/docs/ \u2192 Commands, patterns, troubleshooting");
|
|
1515
1515
|
sections.push(".cursorrules \u2192 IDE instructions (if using Cursor)");
|
|
1516
1516
|
sections.push("portal.yaml \u2192 Security/auth definitions");
|
|
1517
|
+
sections.push(".paradigm/lore/ \u2192 Project timeline and history");
|
|
1517
1518
|
sections.push("```");
|
|
1518
1519
|
sections.push("");
|
|
1519
1520
|
sections.push(generateTerminalGuidance());
|
|
@@ -1620,6 +1621,35 @@ var ClaudeAdapter = class {
|
|
|
1620
1621
|
sections.push("3. Check `portal.yaml` for existing auth gates");
|
|
1621
1622
|
sections.push("4. Check `.paradigm/docs/patterns.md` for coding patterns");
|
|
1622
1623
|
sections.push("");
|
|
1624
|
+
sections.push("## Lore (Project Timeline)");
|
|
1625
|
+
sections.push("");
|
|
1626
|
+
sections.push("Lore records what happened, why, and what was learned \u2014 forming a queryable project history.");
|
|
1627
|
+
sections.push("");
|
|
1628
|
+
sections.push("### MCP Tools");
|
|
1629
|
+
sections.push("");
|
|
1630
|
+
sections.push("| Tool | Purpose |");
|
|
1631
|
+
sections.push("|------|---------|");
|
|
1632
|
+
sections.push("| `paradigm_lore_search` | Search and filter lore entries by author, symbol, date, type |");
|
|
1633
|
+
sections.push("| `paradigm_lore_record` | Record a new lore entry (session, decision, milestone, etc.) |");
|
|
1634
|
+
sections.push("| `paradigm_lore_timeline` | Get project timeline summary with entry count and authors |");
|
|
1635
|
+
sections.push("");
|
|
1636
|
+
sections.push("### CLI Commands");
|
|
1637
|
+
sections.push("");
|
|
1638
|
+
sections.push("| Command | Description |");
|
|
1639
|
+
sections.push("|---------|-------------|");
|
|
1640
|
+
sections.push("| `paradigm lore` | List recent lore entries |");
|
|
1641
|
+
sections.push("| `paradigm lore record` | Interactively record a new entry |");
|
|
1642
|
+
sections.push("| `paradigm lore show <id>` | Show full details of an entry |");
|
|
1643
|
+
sections.push("| `paradigm lore review <id>` | Add human review to an entry |");
|
|
1644
|
+
sections.push("| `paradigm lore timeline` | Show project timeline summary |");
|
|
1645
|
+
sections.push("");
|
|
1646
|
+
sections.push("### When to Record Lore");
|
|
1647
|
+
sections.push("");
|
|
1648
|
+
sections.push("- After completing a feature or significant session");
|
|
1649
|
+
sections.push("- When making architectural decisions");
|
|
1650
|
+
sections.push("- After resolving incidents or bugs");
|
|
1651
|
+
sections.push("- At project milestones");
|
|
1652
|
+
sections.push("");
|
|
1623
1653
|
sections.push(generateNavigationSection(config));
|
|
1624
1654
|
sections.push("## Context Monitoring Protocol");
|
|
1625
1655
|
sections.push("");
|
|
@@ -1651,6 +1681,8 @@ var ClaudeAdapter = class {
|
|
|
1651
1681
|
sections.push("| **Getting test data** | `paradigm_test_fixtures` for fixtures |");
|
|
1652
1682
|
sections.push('| **Building a feature (3+ files)** | `paradigm_orchestrate_inline` mode="plan" |');
|
|
1653
1683
|
sections.push('| **Task involves security + code** | `paradigm_orchestrate_inline` mode="plan" |');
|
|
1684
|
+
sections.push("| **Recording work done** | `paradigm_lore_record` to capture session history |");
|
|
1685
|
+
sections.push("| **Checking project history** | `paradigm_lore_timeline` for timeline overview |");
|
|
1654
1686
|
sections.push("| **Finishing work session** | `paradigm_reindex` to rebuild static index |");
|
|
1655
1687
|
sections.push("");
|
|
1656
1688
|
sections.push("**Benefits**: ~100 tokens per query vs ~2000 for reading files. Always fresh data from live index.");
|
|
@@ -1861,6 +1893,7 @@ var ClaudeAdapter = class {
|
|
|
1861
1893
|
sections.push("| Add multi-step flow | Document as `$flow` in `.purpose` |");
|
|
1862
1894
|
sections.push("| Rename/delete symbol | Update all `.purpose` references |");
|
|
1863
1895
|
sections.push("| Learn antipattern | Add to `.paradigm/wisdom/antipatterns.yaml` |");
|
|
1896
|
+
sections.push("| Complete feature/session | Record lore entry via `paradigm_lore_record` |");
|
|
1864
1897
|
sections.push("");
|
|
1865
1898
|
sections.push("**CRITICAL: Authorization requires portal.yaml**");
|
|
1866
1899
|
sections.push("");
|
|
@@ -2121,7 +2121,7 @@ var require_sql_wasm = __commonJS({
|
|
|
2121
2121
|
}
|
|
2122
2122
|
});
|
|
2123
2123
|
|
|
2124
|
-
// ../sentinel/dist/chunk-
|
|
2124
|
+
// ../sentinel/dist/chunk-WNZBSJR7.js
|
|
2125
2125
|
var import_sql = __toESM(require_sql_wasm(), 1);
|
|
2126
2126
|
|
|
2127
2127
|
// ../sentinel/node_modules/uuid/dist/esm-node/rng.js
|
|
@@ -2171,7 +2171,7 @@ function v4(options, buf, offset) {
|
|
|
2171
2171
|
}
|
|
2172
2172
|
var v4_default = v4;
|
|
2173
2173
|
|
|
2174
|
-
// ../sentinel/dist/chunk-
|
|
2174
|
+
// ../sentinel/dist/chunk-WNZBSJR7.js
|
|
2175
2175
|
import * as path from "path";
|
|
2176
2176
|
import * as fs from "fs";
|
|
2177
2177
|
var SCHEMA_VERSION = 1;
|
|
@@ -2191,8 +2191,8 @@ var SentinelStorage = class {
|
|
|
2191
2191
|
this.dbPath = dbPath || this.getDefaultDbPath();
|
|
2192
2192
|
}
|
|
2193
2193
|
getDefaultDbPath() {
|
|
2194
|
-
const
|
|
2195
|
-
return path.join(
|
|
2194
|
+
const dataDir = process.env.SENTINEL_DATA_DIR || process.env.PARADIGM_DATA_DIR || path.join(process.cwd(), ".paradigm", "sentinel");
|
|
2195
|
+
return path.join(dataDir, "sentinel.db");
|
|
2196
2196
|
}
|
|
2197
2197
|
createSchema() {
|
|
2198
2198
|
if (!this.db) return;
|