@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/chunk-3DYYXGDC.js +403 -0
- package/dist/{chunk-YHRRJM6J.js → chunk-BRILIG7Z.js} +53 -34
- package/dist/{chunk-TUW27EIC.js → chunk-EZ6XW6FB.js} +141 -500
- package/dist/{delete-2PX6DDAY.js → delete-YTASL4SM.js} +1 -1
- package/dist/{edit-GJYLJYDU.js → edit-S7NZD7H7.js} +1 -1
- package/dist/index.js +18 -10
- package/dist/{list-RHYZPKG3.js → list-CAL7KS7B.js} +1 -1
- package/dist/lore-loader-S5BXMH27.js +21 -0
- package/dist/{lore-server-XEW7EG62.js → lore-server-2NYDLGCJ.js} +25 -1
- package/dist/mcp.js +458 -136
- package/dist/migrate-assessments-FPR6C35Z.js +97 -0
- package/dist/{record-PGVYYZFU.js → record-UGN75GTB.js} +5 -2
- package/dist/{reindex-UAYAEF7M.js → reindex-CMZARW5K.js} +2 -1
- package/dist/retag-URLJLMSK.js +62 -0
- package/dist/{review-BRY5R45L.js → review-725ZKA7U.js} +1 -1
- package/dist/{serve-KBMKF4KG.js → serve-GUJ3L3IG.js} +1 -1
- package/dist/{show-6CHTSR33.js → show-GEVVQWWG.js} +37 -3
- package/dist/{timeline-HC527YXE.js → timeline-B6TMGWRU.js} +1 -1
- package/dist/university-content/courses/para-501.json +30 -30
- package/dist/university-content/plsat/v3.0.json +26 -26
- package/package.json +1 -1
- package/dist/assessment-loader-C5EOUM47.js +0 -23
- package/dist/chunk-DSXS42FY.js +0 -283
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
normalizeLoreEntry,
|
|
4
|
+
recordLore
|
|
5
|
+
} from "./chunk-BRILIG7Z.js";
|
|
6
|
+
import "./chunk-ZXMDA7VB.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/lore/migrate-assessments.ts
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import * as fs from "fs";
|
|
11
|
+
import * as path from "path";
|
|
12
|
+
import * as yaml from "js-yaml";
|
|
13
|
+
var ASSESSMENTS_DIR = ".paradigm/assessments";
|
|
14
|
+
async function loreMigrateAssessmentsCommand(options) {
|
|
15
|
+
const rootDir = process.cwd();
|
|
16
|
+
const arcsDir = path.join(rootDir, ASSESSMENTS_DIR, "arcs");
|
|
17
|
+
const dryRun = !!options.dryRun;
|
|
18
|
+
if (!fs.existsSync(arcsDir)) {
|
|
19
|
+
console.log(chalk.yellow("\n No assessments found at .paradigm/assessments/arcs/\n"));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const arcDirs = fs.readdirSync(arcsDir).filter((d) => {
|
|
23
|
+
const stat = fs.statSync(path.join(arcsDir, d));
|
|
24
|
+
return stat.isDirectory();
|
|
25
|
+
});
|
|
26
|
+
let migrated = 0;
|
|
27
|
+
let skipped = 0;
|
|
28
|
+
const arcsProcessed = [];
|
|
29
|
+
for (const arcDir of arcDirs) {
|
|
30
|
+
const entriesDir = path.join(arcsDir, arcDir, "entries");
|
|
31
|
+
if (!fs.existsSync(entriesDir)) continue;
|
|
32
|
+
const entryFiles = fs.readdirSync(entriesDir).filter((f) => f.endsWith(".yaml") && !f.endsWith(".migrated"));
|
|
33
|
+
for (const file of entryFiles) {
|
|
34
|
+
const filePath = path.join(entriesDir, file);
|
|
35
|
+
try {
|
|
36
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
37
|
+
const assessment = yaml.load(content);
|
|
38
|
+
const tags = [
|
|
39
|
+
`arc:${assessment.arc_id}`,
|
|
40
|
+
`assessment:${assessment.type}`,
|
|
41
|
+
...assessment.tags || [],
|
|
42
|
+
"migrated-from-assessment"
|
|
43
|
+
];
|
|
44
|
+
const rawEntry = {
|
|
45
|
+
id: "",
|
|
46
|
+
// Will be generated
|
|
47
|
+
type: assessment.type,
|
|
48
|
+
timestamp: assessment.date,
|
|
49
|
+
author: assessment.author,
|
|
50
|
+
// Will be normalized
|
|
51
|
+
title: assessment.title,
|
|
52
|
+
summary: assessment.summary,
|
|
53
|
+
body: assessment.body,
|
|
54
|
+
symbols_touched: assessment.symbols || [],
|
|
55
|
+
tags,
|
|
56
|
+
linked_lore: assessment.linked_lore,
|
|
57
|
+
linked_tasks: assessment.linked_tasks,
|
|
58
|
+
linked_commits: assessment.linked_commits
|
|
59
|
+
};
|
|
60
|
+
const normalized = normalizeLoreEntry(rawEntry);
|
|
61
|
+
const entry = {
|
|
62
|
+
...normalized,
|
|
63
|
+
id: ""
|
|
64
|
+
// Let recordLore generate a new ID
|
|
65
|
+
};
|
|
66
|
+
if (dryRun) {
|
|
67
|
+
console.log(chalk.gray(` [dry-run] Would migrate: ${assessment.id} \u2192 lore (arc:${assessment.arc_id})`));
|
|
68
|
+
} else {
|
|
69
|
+
await recordLore(rootDir, entry);
|
|
70
|
+
fs.renameSync(filePath, filePath.replace(".yaml", ".migrated"));
|
|
71
|
+
console.log(chalk.green(` Migrated: ${assessment.id} \u2192 ${entry.id} (arc:${assessment.arc_id})`));
|
|
72
|
+
}
|
|
73
|
+
migrated++;
|
|
74
|
+
if (!arcsProcessed.includes(assessment.arc_id)) {
|
|
75
|
+
arcsProcessed.push(assessment.arc_id);
|
|
76
|
+
}
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.error(chalk.red(` Failed to migrate ${file}: ${err}`));
|
|
79
|
+
skipped++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
console.log();
|
|
84
|
+
if (dryRun) {
|
|
85
|
+
console.log(chalk.yellow(` Dry run complete: ${migrated} entries would be migrated from ${arcsProcessed.length} arcs`));
|
|
86
|
+
} else {
|
|
87
|
+
console.log(chalk.green(` Migration complete: ${migrated} entries migrated from ${arcsProcessed.length} arcs`));
|
|
88
|
+
}
|
|
89
|
+
if (skipped > 0) {
|
|
90
|
+
console.log(chalk.yellow(` ${skipped} entries skipped due to errors`));
|
|
91
|
+
}
|
|
92
|
+
console.log(chalk.gray(` Arcs preserved as tags: ${arcsProcessed.map((a) => `arc:${a}`).join(", ")}`));
|
|
93
|
+
console.log();
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
loreMigrateAssessmentsCommand
|
|
97
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
recordLore,
|
|
4
4
|
resolveAuthor
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BRILIG7Z.js";
|
|
6
6
|
import "./chunk-ZXMDA7VB.js";
|
|
7
7
|
|
|
8
8
|
// src/commands/lore/record.ts
|
|
@@ -24,7 +24,10 @@ async function loreRecordCommand(options) {
|
|
|
24
24
|
commit: options.commit || void 0,
|
|
25
25
|
learnings: options.learnings ? options.learnings.split(",").map((l) => l.trim()) : void 0,
|
|
26
26
|
tags: options.tags ? options.tags.split(",").map((t) => t.trim()) : void 0,
|
|
27
|
-
meta: options.meta ? JSON.parse(options.meta) : void 0
|
|
27
|
+
meta: options.meta ? JSON.parse(options.meta) : void 0,
|
|
28
|
+
body: options.body || void 0,
|
|
29
|
+
linked_lore: options.linkLore ? options.linkLore.split(",").map((l) => l.trim()) : void 0,
|
|
30
|
+
linked_commits: options.linkCommits ? options.linkCommits.split(",").map((c) => c.trim()) : void 0
|
|
28
31
|
// git_context is auto-captured by recordLore
|
|
29
32
|
};
|
|
30
33
|
await recordLore(rootDir, entry);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadLoreEntries,
|
|
4
|
+
updateLoreEntry
|
|
5
|
+
} from "./chunk-BRILIG7Z.js";
|
|
6
|
+
import "./chunk-ZXMDA7VB.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/lore/retag.ts
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
async function loreRetagCommand(options) {
|
|
11
|
+
const rootDir = process.cwd();
|
|
12
|
+
const addTag = options.add;
|
|
13
|
+
const removeTag = options.remove;
|
|
14
|
+
if (!addTag && !removeTag) {
|
|
15
|
+
console.error(chalk.red("\n Must specify --add <tag> or --remove <tag>\n"));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const filter = {};
|
|
19
|
+
if (options.type) filter.type = options.type;
|
|
20
|
+
if (options.symbol) filter.symbol = options.symbol;
|
|
21
|
+
if (options.author) filter.author = options.author;
|
|
22
|
+
if (options.from) filter.dateFrom = options.from;
|
|
23
|
+
if (options.to) filter.dateTo = options.to;
|
|
24
|
+
if (options.tags) filter.tags = options.tags.split(",").map((t) => t.trim());
|
|
25
|
+
const entries = await loadLoreEntries(rootDir, filter);
|
|
26
|
+
if (entries.length === 0) {
|
|
27
|
+
console.log(chalk.yellow("\n No matching entries found\n"));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const dryRun = !!options.dryRun;
|
|
31
|
+
let updated = 0;
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
const currentTags = entry.tags || [];
|
|
34
|
+
let newTags;
|
|
35
|
+
if (addTag) {
|
|
36
|
+
if (currentTags.includes(addTag)) continue;
|
|
37
|
+
newTags = [...currentTags, addTag];
|
|
38
|
+
} else {
|
|
39
|
+
if (!currentTags.includes(removeTag)) continue;
|
|
40
|
+
newTags = currentTags.filter((t) => t !== removeTag);
|
|
41
|
+
}
|
|
42
|
+
if (dryRun) {
|
|
43
|
+
const action = addTag ? chalk.green(`+${addTag}`) : chalk.red(`-${removeTag}`);
|
|
44
|
+
console.log(chalk.gray(` [dry-run] ${entry.id}: ${action}`));
|
|
45
|
+
} else {
|
|
46
|
+
await updateLoreEntry(rootDir, entry.id, { tags: newTags });
|
|
47
|
+
const action = addTag ? chalk.green(`+${addTag}`) : chalk.red(`-${removeTag}`);
|
|
48
|
+
console.log(` ${entry.id}: ${action}`);
|
|
49
|
+
}
|
|
50
|
+
updated++;
|
|
51
|
+
}
|
|
52
|
+
console.log();
|
|
53
|
+
if (dryRun) {
|
|
54
|
+
console.log(chalk.yellow(` Dry run: ${updated} entries would be updated`));
|
|
55
|
+
} else {
|
|
56
|
+
console.log(chalk.green(` Updated ${updated} entries`));
|
|
57
|
+
}
|
|
58
|
+
console.log();
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
loreRetagCommand
|
|
62
|
+
};
|
|
@@ -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-
|
|
12
|
+
const { startLoreServer } = await import("./lore-server-2NYDLGCJ.js");
|
|
13
13
|
console.log(chalk.gray(`Project: ${projectDir}`));
|
|
14
14
|
console.log(chalk.gray(`Port: ${port}`));
|
|
15
15
|
console.log();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadLoreEntry
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BRILIG7Z.js";
|
|
5
5
|
import "./chunk-ZXMDA7VB.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/lore/show.ts
|
|
@@ -27,10 +27,16 @@ Entry not found: ${id}
|
|
|
27
27
|
"incident": chalk.hex("#f87171"),
|
|
28
28
|
"milestone": chalk.hex("#60a5fa")
|
|
29
29
|
};
|
|
30
|
-
const
|
|
30
|
+
const typeColors = {
|
|
31
|
+
...typeColor,
|
|
32
|
+
"retro": chalk.hex("#fb923c"),
|
|
33
|
+
"insight": chalk.hex("#a78bfa")
|
|
34
|
+
};
|
|
35
|
+
const entryType = entry.type || "agent-session";
|
|
36
|
+
const colorFn = typeColors[entryType] || chalk.white;
|
|
31
37
|
console.log();
|
|
32
38
|
console.log(chalk.white.bold(` ${entry.title}`));
|
|
33
|
-
console.log(chalk.gray(` ${entry.id} \xB7 ${colorFn(
|
|
39
|
+
console.log(chalk.gray(` ${entry.id} \xB7 ${colorFn(entryType)} \xB7 ${entry.timestamp}`));
|
|
34
40
|
console.log();
|
|
35
41
|
console.log(` \u{1F464} ${chalk.white(entry.author)}`);
|
|
36
42
|
if (entry.agent) {
|
|
@@ -43,6 +49,34 @@ Entry not found: ${id}
|
|
|
43
49
|
console.log(chalk.gray(" Summary:"));
|
|
44
50
|
console.log(` ${entry.summary}`);
|
|
45
51
|
console.log();
|
|
52
|
+
if (entry.body) {
|
|
53
|
+
console.log(chalk.gray(" Body:"));
|
|
54
|
+
for (const line of entry.body.split("\n")) {
|
|
55
|
+
console.log(` ${line}`);
|
|
56
|
+
}
|
|
57
|
+
console.log();
|
|
58
|
+
}
|
|
59
|
+
if (entry.linked_lore && entry.linked_lore.length > 0) {
|
|
60
|
+
console.log(chalk.gray(" Linked lore:"));
|
|
61
|
+
for (const id2 of entry.linked_lore) {
|
|
62
|
+
console.log(` ${chalk.cyan(id2)}`);
|
|
63
|
+
}
|
|
64
|
+
console.log();
|
|
65
|
+
}
|
|
66
|
+
if (entry.linked_tasks && entry.linked_tasks.length > 0) {
|
|
67
|
+
console.log(chalk.gray(" Linked tasks:"));
|
|
68
|
+
for (const id2 of entry.linked_tasks) {
|
|
69
|
+
console.log(` ${chalk.yellow(id2)}`);
|
|
70
|
+
}
|
|
71
|
+
console.log();
|
|
72
|
+
}
|
|
73
|
+
if (entry.linked_commits && entry.linked_commits.length > 0) {
|
|
74
|
+
console.log(chalk.gray(" Linked commits:"));
|
|
75
|
+
for (const sha of entry.linked_commits) {
|
|
76
|
+
console.log(` ${chalk.gray(sha)}`);
|
|
77
|
+
}
|
|
78
|
+
console.log();
|
|
79
|
+
}
|
|
46
80
|
if (entry.symbols_touched?.length > 0) {
|
|
47
81
|
console.log(chalk.gray(" Symbols touched:"));
|
|
48
82
|
console.log(` ${entry.symbols_touched.map((s) => chalk.cyan(s)).join(" ")}`);
|
|
@@ -737,56 +737,56 @@
|
|
|
737
737
|
},
|
|
738
738
|
{
|
|
739
739
|
"id": "assessment-loops",
|
|
740
|
-
"title": "
|
|
741
|
-
"content": "## The
|
|
740
|
+
"title": "Lore as Unified Project Memory",
|
|
741
|
+
"content": "## Lore: The Single Source of Project Memory\n\nParadigm uses lore as its unified project memory system. Every piece of project knowledge — session records, retrospectives, insights, decisions, milestones — lives in lore entries, differentiated by `type` and classified by tags.\n\nThe model is simple: **one system, tags drive classification.**\n\n| Entry Type | When to Use |\n|---|---|\n| `agent-session` | Automated record of an AI-assisted work session |\n| `human-note` | Manual note from a human developer |\n| `decision` | Strategic or architectural decision with rationale |\n| `review` | Quality review of a previous entry |\n| `incident` | Production issue or bug report |\n| `milestone` | Significant project achievement |\n| `retro` | Retrospective — looking back at completed work |\n| `insight` | A realization or pattern discovered across sessions |\n\nLore entries are stored as YAML files in `.paradigm/lore/entries/{date}/` with the `.lore` extension. Each entry has a unique ID: `L-{date}-{author}-{HHMMSS}-{NNN}`.\n\n## Tags Drive Classification\n\nTags are the primary classification mechanism in lore. Any string can be a tag, but certain prefixes carry special meaning:\n\n| Tag Prefix | Meaning | Example |\n|---|---|---|\n| `arc:` | Groups entries into a thematic arc | `arc:auth-hardening`, `arc:v2-migration` |\n| `assessment:` | Marks the reflection type | `assessment:retro`, `assessment:insight` |\n| `arc-closed` | Arc is no longer active | Added when an arc is complete |\n| `arc-status:` | Arc status metadata | `arc-status:complete`, `arc-status:archived` |\n\nArcs are simply tag prefixes — no separate storage or management needed. To create an arc, just start tagging lore entries with `arc:my-arc-name`. To close an arc, add `arc-closed` and `arc-status:complete` tags to its entries.\n\n## The Body Field\n\nFor entries that need more than a 2-3 sentence summary, lore entries support a `body` field for long-form content. This is where retrospective narratives, detailed decision rationale, and multi-paragraph reflections live:\n\n```yaml\nid: L-2026-03-02-ascend-164500-001\ntype: retro\ntitle: \"JWT refresh token rotation — what we learned\"\nsummary: Completed refresh token rotation with httpOnly cookie storage.\nbody: |\n After three sessions implementing refresh token rotation,\n the key insight is that storing refresh tokens in httpOnly\n cookies eliminates an entire class of XSS vulnerabilities.\nsymbols_touched: [\"#refresh-token-handler\", \"^authenticated\"]\nlinked_lore: [L-2026-02-10-003, L-2026-02-12-001]\nlinked_commits: [a1b2c3d, e4f5g6h]\ntags: [arc:auth-hardening, assessment:retro, security, auth, jwt]\n```\n\n## Cross-Referencing\n\nLore entries can link to other project artifacts:\n\n- **`linked_lore`** — References to other lore entry IDs, creating a web of related records\n- **`linked_tasks`** — References to paradigm task IDs\n- **`linked_commits`** — Git commit SHAs related to this entry\n\nThese links create traceability. A retrospective entry can point to the three session records that produced it and the five commits that implemented it.\n\n## Working with Lore\n\n**Recording:** Use `paradigm_lore_record` with `type`, `title`, `summary`, and `symbols_touched`. Add `body` for long-form content, `tags` with `arc:*` prefixes for arc grouping, and `linked_lore`/`linked_commits` for cross-references.\n\n**Searching:** Use `paradigm_lore_search` with filters:\n- `tag: \"arc:auth-hardening\"` — Find all entries in an arc\n- `type: \"retro\"` — Find all retrospectives\n- `hasBody: true` — Find entries with detailed content\n- `symbol: \"#payment-service\"` — Find entries touching a symbol\n\n## The Reflection Loop\n\nLore supports a natural reflection cycle:\n\n1. **Session records** — Automatically captured during work sessions (type: `agent-session`)\n2. **Reflection entries** — Manually recorded at natural pause points (type: `retro`, `insight`, `decision`, `milestone`)\n3. **Arc grouping** — Related reflections tagged with `arc:*` for thematic organization\n4. **Cross-referencing** — Reflection entries link back to the sessions that produced them\n\nWhen a task is marked complete via `paradigm_task_done`, the system suggests recording a lore entry as a natural reflection point.\n\n## When to Record Reflective Entries\n\n- **After completing a multi-session feature** — What did we learn? (`retro` with `arc:feature-name`)\n- **When a pattern emerges** — \"Every time we touch auth, we find token edge cases\" (`insight`)\n- **When making a strategic choice** — \"Switching from REST to GraphQL\" (`decision`)\n- **When reaching a milestone** — \"v2.0 shipped to production\" (`milestone`)\n\nThe general rule: if the knowledge would be valuable in 3 months, record it as a reflective lore entry with appropriate tags.\n\n## Migration from Assessments\n\nProjects that used the older separate assessment system can migrate with `paradigm lore migrate-assessments`. This converts assessment entries to lore entries with `arc:{arc_id}` and `assessment:{type}` tags, preserving all data.",
|
|
742
742
|
"keyConcepts": [
|
|
743
|
-
"
|
|
744
|
-
"
|
|
745
|
-
"
|
|
746
|
-
"
|
|
747
|
-
"
|
|
748
|
-
"
|
|
749
|
-
"Task completion nudges
|
|
743
|
+
"Lore is the unified project memory — one system, tags drive classification",
|
|
744
|
+
"Eight entry types: agent-session, human-note, decision, review, incident, milestone, retro, insight",
|
|
745
|
+
"Arc tags (arc:*) group related entries by theme — no separate arc management needed",
|
|
746
|
+
"The body field supports long-form content for detailed reflections",
|
|
747
|
+
"Cross-referencing via linked_lore, linked_tasks, and linked_commits creates traceability",
|
|
748
|
+
"paradigm_lore_search with tag filter finds entries across arcs",
|
|
749
|
+
"Task completion nudges lore recording as a natural reflection point"
|
|
750
750
|
],
|
|
751
751
|
"quiz": [
|
|
752
752
|
{
|
|
753
753
|
"id": "q1",
|
|
754
|
-
"question": "You have completed a three-session effort to add rate limiting.
|
|
754
|
+
"question": "You have completed a three-session effort to add rate limiting. You want to record a retrospective grouped with other rate-limiting work. What is the correct approach?",
|
|
755
755
|
"choices": {
|
|
756
|
-
"A": "`
|
|
757
|
-
"B": "`
|
|
758
|
-
"C": "`
|
|
759
|
-
"D": "
|
|
760
|
-
"E": "`
|
|
756
|
+
"A": "Call `paradigm_lore_record` with `type: \"retro\"`, a body with your reflection, and `tags: [\"arc:rate-limiting\"]`",
|
|
757
|
+
"B": "Call `paradigm_assessment_record` with `arc_id: \"arc-rate-limiting\"` and `type: \"retro\"`",
|
|
758
|
+
"C": "Call `paradigm_lore_record` with `type: \"milestone\"` — completing features is always a milestone",
|
|
759
|
+
"D": "Create a separate `.paradigm/assessments/` directory and write the entry manually",
|
|
760
|
+
"E": "Call `paradigm_lore_record` with `type: \"agent-session\"` — all lore is session-level"
|
|
761
761
|
},
|
|
762
|
-
"correct": "
|
|
763
|
-
"explanation": "
|
|
762
|
+
"correct": "A",
|
|
763
|
+
"explanation": "Reflective entries are recorded via `paradigm_lore_record` with the appropriate type and arc tag. A retro with `tags: [\"arc:rate-limiting\"]` groups it with other entries in that arc. The body field holds the detailed reflection. The assessment tools (B) are deprecated wrappers. Milestones (C) mark significant project events, not feature completions. Agent-session (E) is for automated session records, not deliberate reflections."
|
|
764
764
|
},
|
|
765
765
|
{
|
|
766
766
|
"id": "q2",
|
|
767
|
-
"question": "
|
|
767
|
+
"question": "A lore entry has `linked_lore: [L-2026-02-10-003, L-2026-02-12-001]` and `linked_commits: [a1b2c3d]`. What does this cross-referencing enable?",
|
|
768
768
|
"choices": {
|
|
769
|
-
"A": "It automatically updates the
|
|
770
|
-
"B": "It creates traceability — readers can drill from the synthesized insight down to the specific sessions
|
|
769
|
+
"A": "It automatically updates the linked entries with backlinks",
|
|
770
|
+
"B": "It creates traceability — readers can drill from the synthesized insight down to the specific sessions and code changes",
|
|
771
771
|
"C": "It prevents the referenced lore entries from being deleted",
|
|
772
772
|
"D": "It triggers Sentinel to check those commits for incidents",
|
|
773
|
-
"E": "It merges the
|
|
773
|
+
"E": "It merges the linked entries into a single combined entry"
|
|
774
774
|
},
|
|
775
775
|
"correct": "B",
|
|
776
|
-
"explanation": "
|
|
776
|
+
"explanation": "Cross-references create a traceability chain. A reader encountering an insight entry can follow `linked_lore` to see the full session context, and `linked_commits` to see the exact code changes. This is the core value of linking — each entry adds interpretation to what it references, with links to drill down for evidence."
|
|
777
777
|
},
|
|
778
778
|
{
|
|
779
779
|
"id": "q3",
|
|
780
|
-
"question": "You want to find every retrospective that mentions `#payment-service
|
|
780
|
+
"question": "You want to find every retrospective in the `arc:auth-hardening` arc that mentions `#payment-service`. Which approach is correct?",
|
|
781
781
|
"choices": {
|
|
782
|
-
"A": "`
|
|
783
|
-
"B": "`paradigm_assessment_search` with `symbol:
|
|
784
|
-
"C": "`
|
|
785
|
-
"D": "`
|
|
786
|
-
"E": "
|
|
782
|
+
"A": "Call `paradigm_lore_search` with `tag: \"arc:auth-hardening\"`, `type: \"retro\"`, and `symbol: \"#payment-service\"`",
|
|
783
|
+
"B": "Call `paradigm_assessment_search` with `symbol: \"#payment-service\"` — it searches the old assessment system",
|
|
784
|
+
"C": "Call `paradigm_lore_search` with `tags: [\"arc:auth-hardening\", \"retro\"]`",
|
|
785
|
+
"D": "Call `paradigm_search` with `query: \"payment retro auth\"` — general search covers lore",
|
|
786
|
+
"E": "Read every file in `.paradigm/lore/entries/` and filter manually"
|
|
787
787
|
},
|
|
788
|
-
"correct": "
|
|
789
|
-
"explanation": "`
|
|
788
|
+
"correct": "A",
|
|
789
|
+
"explanation": "`paradigm_lore_search` supports combining filters: `tag` for arc prefix matching, `type` for entry type, and `symbol` for symbol references. These filters combine (AND logic), so you get only retro entries in the auth-hardening arc that touch the payment service. The assessment tools (B) are deprecated. Using `tags` array (C) uses OR logic, not AND. General search (D) searches the symbol index, not lore content."
|
|
790
790
|
}
|
|
791
791
|
]
|
|
792
792
|
}
|
|
@@ -2224,17 +2224,17 @@
|
|
|
2224
2224
|
"variants": [
|
|
2225
2225
|
{
|
|
2226
2226
|
"id": "plsat-091",
|
|
2227
|
-
"scenario": "An agent finishes a debugging session and wants to record the root cause and resolution as a lasting insight
|
|
2228
|
-
"question": "
|
|
2227
|
+
"scenario": "An agent finishes a debugging session and wants to record the root cause and resolution as a lasting insight, grouped under the `arc:auth-hardening` arc. The agent calls `paradigm_lore_record` with `type: \"insight\"`, `tags: [\"arc:auth-hardening\", \"assessment:insight\"]`, a summary, and a body with the detailed analysis. The author is `ascend` and the timestamp is `2026-04-02T16:30:00Z`.",
|
|
2228
|
+
"question": "Where is the entry stored, and how does the arc grouping work?",
|
|
2229
2229
|
"choices": {
|
|
2230
|
-
"A": "
|
|
2231
|
-
"B": "
|
|
2232
|
-
"C": "
|
|
2233
|
-
"D": "
|
|
2234
|
-
"E": "
|
|
2230
|
+
"A": "Stored in `.paradigm/assessments/arcs/arc-auth-hardening/entries/` \u2014 arcs have their own storage directories.",
|
|
2231
|
+
"B": "Stored in `.paradigm/lore/entries/2026-04-02/` as a `.lore` file \u2014 arcs are just tag prefixes, not separate storage.",
|
|
2232
|
+
"C": "Stored in `.paradigm/lore/arcs/auth-hardening/` \u2014 arc entries get their own subdirectory.",
|
|
2233
|
+
"D": "Stored in `.paradigm/lore/entries/` root directory \u2014 no date partitioning for arc entries.",
|
|
2234
|
+
"E": "Stored in both `.paradigm/lore/` and `.paradigm/assessments/` \u2014 the system maintains backward compatibility."
|
|
2235
2235
|
},
|
|
2236
2236
|
"correct": "B",
|
|
2237
|
-
"explanation": "
|
|
2237
|
+
"explanation": "All lore entries are stored in `.paradigm/lore/entries/{date}/` as `.lore` files, regardless of their tags. Arcs are simply tag prefixes (e.g., `arc:auth-hardening`) \u2014 they require no separate directory structure or management. To find all entries in an arc, use `paradigm_lore_search` with `tag: \"arc:auth-hardening\"`. This unified storage eliminates the complexity of a separate assessment system while preserving full arc-based organization through tags."
|
|
2238
2238
|
}
|
|
2239
2239
|
]
|
|
2240
2240
|
},
|
|
@@ -2245,17 +2245,17 @@
|
|
|
2245
2245
|
"variants": [
|
|
2246
2246
|
{
|
|
2247
2247
|
"id": "plsat-092",
|
|
2248
|
-
"scenario": "A developer
|
|
2249
|
-
"question": "What happens when
|
|
2248
|
+
"scenario": "A developer wants to record retrospectives about a failed deployment. They have no prior entries tagged with `arc:platform-stability`. The agent calls `paradigm_lore_record` with `type: \"retro\"`, `tags: [\"arc:platform-stability\", \"assessment:retro\"]`, a title, summary, and body describing the failure and lessons learned.",
|
|
2249
|
+
"question": "What happens when you use a new arc tag that no prior entries have?",
|
|
2250
2250
|
"choices": {
|
|
2251
|
-
"A": "The call fails
|
|
2252
|
-
"B": "The entry is recorded as an
|
|
2253
|
-
"C": "The
|
|
2254
|
-
"D": "The
|
|
2255
|
-
"E": "The
|
|
2251
|
+
"A": "The call fails \u2014 arcs must be explicitly created before tagging entries.",
|
|
2252
|
+
"B": "The entry is recorded normally \u2014 arcs are just tag prefixes, no creation step needed. The arc exists as soon as an entry has the tag.",
|
|
2253
|
+
"C": "The system auto-creates a `.paradigm/lore/arcs/platform-stability/` directory to track the arc.",
|
|
2254
|
+
"D": "The entry is recorded but flagged as orphaned until an arc is formally registered.",
|
|
2255
|
+
"E": "The tag is rejected because it does not match an existing arc in the arc registry."
|
|
2256
2256
|
},
|
|
2257
|
-
"correct": "
|
|
2258
|
-
"explanation": "
|
|
2257
|
+
"correct": "B",
|
|
2258
|
+
"explanation": "Arcs in the unified lore system are simply tag prefixes \u2014 no explicit creation needed. The first entry tagged with `arc:platform-stability` effectively creates that arc. To find all entries in this arc later, use `paradigm_lore_search` with `tag: \"arc:platform-stability\"`. To close the arc, add `arc-closed` and `arc-status:complete` tags to its entries. This tag-based approach eliminates the overhead of managing separate arc directories and YAML files."
|
|
2259
2259
|
}
|
|
2260
2260
|
]
|
|
2261
2261
|
},
|
|
@@ -2266,17 +2266,17 @@
|
|
|
2266
2266
|
"variants": [
|
|
2267
2267
|
{
|
|
2268
2268
|
"id": "plsat-093",
|
|
2269
|
-
"scenario": "Your project has been running for six months. The codebase has 200+ commits
|
|
2270
|
-
"question": "Which statement BEST describes Paradigm's
|
|
2269
|
+
"scenario": "Your project has been running for six months. The codebase has 200+ commits in git and 57 lore entries: 45 are `agent-session` type (automatic session records), 8 have `arc:*` tags (retrospectives and insights grouped into thematic arcs), and 4 are `decision` type (architectural decisions). A new team member asks how lore's different entry types and tags work together.",
|
|
2270
|
+
"question": "Which statement BEST describes Paradigm's unified lore model?",
|
|
2271
2271
|
"choices": {
|
|
2272
|
-
"A": "
|
|
2273
|
-
"B": "Lore
|
|
2274
|
-
"C": "
|
|
2275
|
-
"D": "
|
|
2276
|
-
"E": "
|
|
2272
|
+
"A": "Lore entries are all the same \u2014 tags are purely cosmetic and do not affect searching or organization.",
|
|
2273
|
+
"B": "Lore is the single project memory system. Entry types classify the nature of knowledge (session, retro, insight, decision), while tags like `arc:*` group related entries into themes \u2014 both are filterable via `paradigm_lore_search`.",
|
|
2274
|
+
"C": "Session entries and reflection entries are stored in separate directories, with tags used only for cross-referencing between them.",
|
|
2275
|
+
"D": "The `arc:*` tags are managed by a separate arc subsystem that must be initialized before use.",
|
|
2276
|
+
"E": "Entry types are deprecated \u2014 tags alone drive all classification in the new model."
|
|
2277
2277
|
},
|
|
2278
|
-
"correct": "
|
|
2279
|
-
"explanation": "Paradigm's
|
|
2278
|
+
"correct": "B",
|
|
2279
|
+
"explanation": "Paradigm's unified lore model uses one system with two classification axes: entry `type` classifies the nature of the knowledge (agent-session for automated records, retro for retrospectives, insight for patterns, decision for choices, etc.), while tags provide flexible grouping (arc:* for thematic arcs, assessment:* for reflection type, plus arbitrary project tags). Both are searchable via `paradigm_lore_search` \u2014 you can filter by type, tag prefix, symbol, author, and date range. All entries live in the same `.paradigm/lore/entries/` directory structure regardless of type or tags."
|
|
2280
2280
|
}
|
|
2281
2281
|
]
|
|
2282
2282
|
},
|
package/package.json
CHANGED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
closeArc,
|
|
4
|
-
createArc,
|
|
5
|
-
loadArc,
|
|
6
|
-
loadArcs,
|
|
7
|
-
loadEntries,
|
|
8
|
-
loadEntry,
|
|
9
|
-
rebuildAssessmentIndex,
|
|
10
|
-
recordEntry,
|
|
11
|
-
searchEntries
|
|
12
|
-
} from "./chunk-DSXS42FY.js";
|
|
13
|
-
export {
|
|
14
|
-
closeArc,
|
|
15
|
-
createArc,
|
|
16
|
-
loadArc,
|
|
17
|
-
loadArcs,
|
|
18
|
-
loadEntries,
|
|
19
|
-
loadEntry,
|
|
20
|
-
rebuildAssessmentIndex,
|
|
21
|
-
recordEntry,
|
|
22
|
-
searchEntries
|
|
23
|
-
};
|