agentsmesh 0.22.0 → 0.23.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lessons/bullet-hash.ts","../src/lessons/bullet-parser.ts","../src/lessons/index-schema.ts","../src/lessons/matcher.ts","../src/lessons/ledger.ts","../src/lessons/scoring.ts","../src/lessons/paths.ts","../src/lessons/store.ts","../src/lessons/init.ts"],"names":["z","parseYaml","yamlStringify","readFileSync","existsSync","relative","mkdirSync","dirname","writeFileSync","join"],"mappings":"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","file":"lessons.js","sourcesContent":["import { createHash } from 'node:crypto';\n\nfunction normalize(bullet: string): string {\n return bullet\n .split('\\n')\n .map((line) => line.replace(/\\s+$/, ''))\n .join('\\n')\n .trim()\n .replace(/^[-*]\\s+/, '');\n}\n\nexport function hashBullet(bullet: string): string {\n return createHash('sha256').update(normalize(bullet)).digest('hex').slice(0, 16);\n}\n","export interface ParsedBullet {\n text: string;\n lineNumber: number;\n}\n\nexport function parseBullets(markdown: string): ParsedBullet[] {\n const bullets: ParsedBullet[] = [];\n let current: ParsedBullet | null = null;\n let lineNumber = 0;\n\n for (const line of markdown.split('\\n')) {\n lineNumber += 1;\n if (/^[-*]\\s+/.test(line)) {\n if (current !== null) bullets.push(current);\n current = { text: line, lineNumber };\n } else if (current !== null) {\n if (line.length === 0) {\n bullets.push(current);\n current = null;\n } else if (/^\\s+\\S/.test(line)) {\n current.text += `\\n${line}`;\n } else {\n bullets.push(current);\n current = null;\n }\n }\n }\n if (current !== null) bullets.push(current);\n return bullets;\n}\n","import { z } from 'zod';\n\nconst TriggersSchema = z\n .object({\n file_globs: z.array(z.string()),\n command_patterns: z.array(z.string()),\n keywords: z.array(z.string()),\n })\n .refine((t) => t.file_globs.length + t.command_patterns.length + t.keywords.length > 0, {\n message: 'cluster must declare at least one trigger of any type',\n });\n\nconst ClusterSchema = z.object({\n topic: z.string().regex(/^[a-z0-9-]+$/, 'topic must be kebab-case'),\n /**\n * Project-relative path (forward slashes) to the cluster's markdown body.\n * Conventionally `.agentsmesh/lessons/topics/<topic>.md`, but any project\n * path is accepted — universal across every agent target.\n */\n file: z.string().regex(/\\.md$/, 'file must be a .md path'),\n summary: z.string().min(1),\n triggers: TriggersSchema,\n});\n\nexport const LessonsIndexSchema = z.object({\n version: z.literal(1),\n /**\n * Zero clusters is valid — supports `agentsmesh init --lessons` scaffolding a\n * fresh project. Topics accumulate via `distill:apply` as failures are\n * captured.\n */\n clusters: z.array(ClusterSchema),\n});\n\nexport type LessonsIndex = z.infer<typeof LessonsIndexSchema>;\nexport type LessonsCluster = z.infer<typeof ClusterSchema>;\n\nexport function parseIndex(raw: unknown): LessonsIndex {\n return LessonsIndexSchema.parse(raw);\n}\n","import picomatch from 'picomatch';\nimport type { LessonsCluster } from './index-schema.js';\n\nexport type ToolEvent =\n | { kind: 'edit' | 'write'; filePath: string }\n | { kind: 'bash'; command: string }\n | { kind: 'task'; text: string };\n\nfunction fileMatch(globs: readonly string[], path: string): boolean {\n return globs.some((g) => picomatch(g, { dot: true })(path));\n}\n\nfunction cmdMatch(patterns: readonly string[], cmd: string): boolean {\n return patterns.some((p) => {\n try {\n return new RegExp(p).test(cmd);\n } catch {\n return false;\n }\n });\n}\n\nfunction kwMatch(keywords: readonly string[], text: string): boolean {\n const lower = text.toLowerCase();\n return keywords.some((k) => lower.includes(k.toLowerCase()));\n}\n\nexport function matchTriggers(\n clusters: readonly LessonsCluster[],\n event: ToolEvent,\n): LessonsCluster[] {\n return clusters.filter((c) => {\n const t = c.triggers;\n switch (event.kind) {\n case 'edit':\n case 'write':\n return fileMatch(t.file_globs, event.filePath);\n case 'bash':\n return cmdMatch(t.command_patterns, event.command);\n case 'task':\n return kwMatch(t.keywords, event.text);\n }\n });\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { parse as parseYaml, stringify as yamlStringify } from 'yaml';\nimport { z } from 'zod';\n\nconst LedgerSchema = z.object({\n version: z.literal(1),\n assignments: z.record(z.string(), z.string()),\n});\n\nexport type Ledger = z.infer<typeof LedgerSchema>;\n\nexport function loadLedger(path: string): Ledger {\n if (!existsSync(path)) return { version: 1, assignments: {} };\n return LedgerSchema.parse(parseYaml(readFileSync(path, 'utf8')));\n}\n\nexport function saveLedger(path: string, ledger: Ledger): void {\n writeFileSync(path, yamlStringify(ledger), 'utf8');\n}\n","import type { LessonsCluster } from './index-schema.js';\n\nexport interface ScoredCluster {\n cluster: LessonsCluster;\n score: number;\n}\n\nexport function scoreBullet(bullet: string, clusters: readonly LessonsCluster[]): ScoredCluster[] {\n const lower = bullet.toLowerCase();\n return clusters\n .map((cluster): ScoredCluster => {\n const t = cluster.triggers;\n const kwHits = t.keywords.filter((k) => lower.includes(k.toLowerCase())).length;\n const pathHits = t.file_globs.filter((g) => {\n const stem = g\n .replace(/[*{}[\\]?!]/g, '')\n .replace(/\\/+/g, '/')\n .trim();\n return stem.length > 2 && lower.includes(stem.toLowerCase());\n }).length;\n const cmdHits = t.command_patterns.filter((p) => {\n try {\n return new RegExp(p, 'i').test(bullet);\n } catch {\n return false;\n }\n }).length;\n return { cluster, score: kwHits * 2 + pathHits + cmdHits };\n })\n .filter((s) => s.score > 0)\n .sort((a, b) => b.score - a.score);\n}\n","import { join, relative, sep } from 'node:path';\n\n/**\n * Default on-disk locations for the lessons subsystem.\n *\n * All artifacts live under `<projectRoot>/.agentsmesh/lessons/`, so the lessons\n * subsystem is a self-contained canonical feature — `agentsmesh init --lessons`\n * scaffolds this directory and the procedural rule, and removal is a single\n * directory delete.\n *\n * Path values are absolute; `*Rel` helpers return forward-slash project-relative\n * paths suitable for embedding in markdown rules consumed by any agent target.\n */\nexport interface LessonsPaths {\n /** Directory containing every lessons artifact. */\n readonly base: string;\n /** Append-only journal — point of capture for new lessons. */\n readonly journal: string;\n /** Trigger index — maps file_globs / command_patterns / keywords to topic files. */\n readonly index: string;\n /** Distill ledger — bullet hash → assigned topic (or \"skip\"). */\n readonly ledger: string;\n /** Distill proposal file — generated by `distill`, consumed by `distill:apply`. */\n readonly proposal: string;\n /** Directory holding one markdown file per topic cluster. */\n readonly topicsDir: string;\n}\n\nconst BASE_REL = '.agentsmesh/lessons';\n\nexport function lessonsPaths(projectRoot: string): LessonsPaths {\n const base = join(projectRoot, BASE_REL);\n return {\n base,\n journal: join(base, 'journal.md'),\n index: join(base, 'index.yaml'),\n ledger: join(base, 'distill-ledger.yaml'),\n proposal: join(base, 'distill-proposal.md'),\n topicsDir: join(base, 'topics'),\n };\n}\n\n/**\n * Project-relative path for a given absolute path, normalized to forward\n * slashes for cross-platform consistency in markdown rule files.\n */\nexport function toRelPath(projectRoot: string, absolute: string): string {\n return relative(projectRoot, absolute).split(sep).join('/');\n}\n\n/**\n * Empty-journal contents used by init scaffolding. The journal grows from here\n * as failures get recorded.\n */\nexport const LESSONS_JOURNAL_TEMPLATE = '# Lessons Learned\\n\\n';\n\n/**\n * Empty index used by init scaffolding. Schema allows zero clusters; topics\n * accumulate via `distill:apply` as failures are captured.\n */\nexport const LESSONS_INDEX_TEMPLATE = 'version: 1\\nclusters: []\\n';\n\n/**\n * Procedural rule paragraph that must live in the project's root rule\n * (`.agentsmesh/rules/_root.md`) for both recall and capture to be enforced.\n *\n * Universal across every agent target: only requires the ability to read\n * project files. No `Skill` tool, no description-match, no per-target\n * projection.\n */\nexport const LESSONS_PROCEDURAL_RULE = `## Lessons (MUST do — non-negotiable)\n\nTwo rituals. Universal across every agent harness — described in tool-agnostic action verbs (\"read a file\", \"edit a file\", \"run a shell command\"); use whatever read / write-patch / shell-exec tool your harness exposes. Skipping either ritual is a process violation; the same paid-for failure recurs next session.\n\n**Recall — BEFORE editing any file or running any shell command:**\n\n1. Read \\`.agentsmesh/lessons/index.yaml\\`.\n2. For every cluster whose triggers match — \\`file_globs\\` against the target file path, \\`command_patterns\\` (regex) against the shell command, or \\`keywords\\` (case-insensitive substring) against the active task description — read its \\`file\\` (e.g. \\`.agentsmesh/lessons/topics/<topic>.md\\`).\n3. Apply the loaded rules to the action.\n4. Then — and only then — perform the edit or run the command.\n\nRejected excuses: *\"the edit is small\"* → apply it. *\"I read this earlier in the session\"* → context may have compacted; re-read. *\"no trigger fires\"* → proceed; you've done your part.\n\n**Capture — IMMEDIATELY after any failure** (test, CI, lint, code review, user correction, regression you spotted yourself, OR any mistake by anyone in the loop):\n\n1. Append one bullet to \\`.agentsmesh/lessons/journal.md\\` in this exact shape:\n \\`- **<short heading>**: <what went wrong>. <root cause>. <imperative rule that prevents recurrence>.\\`\n2. Read \\`.agentsmesh/lessons/index.yaml\\` and identify which topic the lesson belongs to (use the \\`summary:\\` fields).\n3. If the lesson teaches a NEW rule: edit that topic's \\`## Rules\\` section to add it, citing \\`(Evidence: L<journal-line>)\\`. If it only reinforces an existing rule, the journal entry alone suffices.\n\nRejected excuses: *\"it wasn't really a failure\"* → if you fixed something, it was. *\"I'll capture it later\"* → no; do it now while context is fresh. *\"no topic fits\"* → still record in journal; an unrouted bullet is recoverable, a forgotten one is not.\n\n**These two rituals are load-bearing. Treat them with the same discipline as TDD.**`;\n","import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { parseIndex, type LessonsCluster, type LessonsIndex } from './index-schema.js';\nimport { matchTriggers, type ToolEvent } from './matcher.js';\nimport { lessonsPaths } from './paths.js';\n\nexport interface TriggeredLesson {\n readonly cluster: LessonsCluster;\n readonly relativePath: string;\n readonly filePath: string;\n readonly content: string;\n}\n\nexport interface LessonCaptureInput {\n readonly heading: string;\n readonly whatWentWrong: string;\n readonly rootCause: string;\n readonly rule: string;\n}\n\nexport interface AppendLessonResult {\n readonly journalPath: string;\n readonly bullet: string;\n readonly lineNumber: number;\n}\n\nexport function loadLessonsIndex(projectRoot: string): LessonsIndex {\n const raw = readFileSync(lessonsPaths(projectRoot).index, 'utf8');\n return parseIndex(parseYaml(raw) as unknown);\n}\n\nexport function readTriggeredLessons(projectRoot: string, event: ToolEvent): TriggeredLesson[] {\n const index = loadLessonsIndex(projectRoot);\n const contentByPath = new Map<string, string>();\n\n return matchTriggers(index.clusters, normalizeToolEvent(projectRoot, event)).map(\n (cluster): TriggeredLesson => {\n const filePath = resolveProjectFile(projectRoot, cluster.file);\n let content = contentByPath.get(cluster.file);\n if (content === undefined) {\n content = readFileSync(filePath, 'utf8');\n contentByPath.set(cluster.file, content);\n }\n\n return {\n cluster,\n relativePath: cluster.file,\n filePath,\n content,\n };\n },\n );\n}\n\nexport function formatLessonBullet(input: LessonCaptureInput): string {\n const heading = compact(input.heading);\n if (heading.length === 0) throw new Error('Lesson heading must not be empty.');\n\n return [\n `- **${heading}**:`,\n sentence(input.whatWentWrong),\n sentence(input.rootCause),\n sentence(input.rule),\n ].join(' ');\n}\n\nexport function appendLessonToJournal(\n projectRoot: string,\n input: LessonCaptureInput,\n): AppendLessonResult {\n const journalPath = lessonsPaths(projectRoot).journal;\n const bullet = formatLessonBullet(input);\n const current = existsSync(journalPath) ? readFileSync(journalPath, 'utf8') : '';\n const prefix = current.length === 0 || current.endsWith('\\n') ? '' : '\\n';\n const lineNumber = nextLineNumber(current);\n\n mkdirSync(dirname(journalPath), { recursive: true });\n appendFileSync(journalPath, `${prefix}${bullet}\\n`, 'utf8');\n\n return { journalPath, bullet, lineNumber };\n}\n\nfunction resolveProjectFile(projectRoot: string, relPath: string): string {\n if (isAbsolute(relPath) || /^[A-Za-z]:[\\\\/]/.test(relPath)) {\n throw new Error(`Lessons file must be project-relative: ${relPath}`);\n }\n\n const root = resolve(projectRoot);\n const filePath = resolve(root, relPath);\n const backToRoot = relative(root, filePath);\n if (backToRoot === '' || backToRoot.startsWith('..') || isAbsolute(backToRoot)) {\n throw new Error(`Lessons file escapes the project root: ${relPath}`);\n }\n\n return filePath;\n}\n\nfunction normalizeToolEvent(projectRoot: string, event: ToolEvent): ToolEvent {\n if (event.kind !== 'edit' && event.kind !== 'write') return event;\n return { ...event, filePath: normalizeEventPath(projectRoot, event.filePath) };\n}\n\nfunction normalizeEventPath(projectRoot: string, filePath: string): string {\n const normalized = filePath.replaceAll('\\\\', '/');\n const root = resolve(projectRoot).replaceAll('\\\\', '/');\n if (normalized === root) return '.';\n if (normalized.startsWith(`${root}/`)) return normalized.slice(root.length + 1);\n return normalized.replace(/^\\.\\//, '');\n}\n\nfunction compact(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n}\n\nfunction sentence(value: string): string {\n const compacted = compact(value);\n if (compacted.length === 0) throw new Error('Lesson sentence must not be empty.');\n return /[.!?]$/.test(compacted) ? compacted : `${compacted}.`;\n}\n\nfunction nextLineNumber(current: string): number {\n if (current.length === 0) return 1;\n const lineCount = current.split('\\n').length;\n return current.endsWith('\\n') ? lineCount : lineCount + 1;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport {\n LESSONS_INDEX_TEMPLATE,\n LESSONS_JOURNAL_TEMPLATE,\n LESSONS_PROCEDURAL_RULE,\n lessonsPaths,\n} from './paths.js';\n\nexport interface ScaffoldLessonsResult {\n readonly created: string[];\n readonly skipped: string[];\n readonly rootRuleUpdated: boolean;\n}\n\n/**\n * Idempotent scaffolder for the lessons subsystem. Intended for a future\n * `agentsmesh init --lessons` flag (project mode); safe to call repeatedly.\n *\n * Creates `.agentsmesh/lessons/` with an empty journal, an empty index, and a\n * `topics/` directory. Appends the procedural rule to\n * `.agentsmesh/rules/_root.md` if not already present.\n *\n * Never overwrites existing files. The ledger and proposal are not created —\n * they are auto-managed by the distill tool on first run.\n */\nexport function scaffoldLessons(projectRoot: string): ScaffoldLessonsResult {\n const paths = lessonsPaths(projectRoot);\n const created: string[] = [];\n const skipped: string[] = [];\n\n mkdirSync(paths.topicsDir, { recursive: true });\n\n for (const [path, template] of [\n [paths.journal, LESSONS_JOURNAL_TEMPLATE],\n [paths.index, LESSONS_INDEX_TEMPLATE],\n ] as const) {\n if (existsSync(path)) {\n skipped.push(path);\n } else {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, template, 'utf8');\n created.push(path);\n }\n }\n\n const rootRuleUpdated = appendProceduralRule(projectRoot);\n return { created, skipped, rootRuleUpdated };\n}\n\nfunction appendProceduralRule(projectRoot: string): boolean {\n const rootRule = join(projectRoot, '.agentsmesh/rules/_root.md');\n if (!existsSync(rootRule)) {\n mkdirSync(dirname(rootRule), { recursive: true });\n const seeded = `---\\nroot: true\\ndescription: \"\"\\n---\\n\\n# Operational Guidelines\\n\\n${LESSONS_PROCEDURAL_RULE}\\n`;\n writeFileSync(rootRule, seeded, 'utf8');\n return true;\n }\n const current = readFileSync(rootRule, 'utf8');\n // Match any '## Lessons (…)' heading — the parenthetical wording may evolve\n // (mandatory / MUST do / etc.) but the H2 itself is the stable idempotency\n // anchor for this paragraph.\n if (/^## Lessons \\(/m.test(current)) return false;\n const next = current.endsWith('\\n') ? current : `${current}\\n`;\n writeFileSync(rootRule, `${next}\\n${LESSONS_PROCEDURAL_RULE}\\n`, 'utf8');\n return true;\n}\n"]}
1
+ {"version":3,"sources":["../src/lessons/graph-schema.ts","../src/lessons/add-helpers.ts","../src/lessons/add-errors.ts","../src/lessons/ranking-text.ts","../src/lessons/keyword-signal.ts","../src/lessons/validate-liveness.ts","../src/lessons/capture-guardrails.ts","../src/lessons/graph-store.ts","../src/lessons/import-legacy-parse.ts","../src/lessons/import-legacy-merge.ts","../src/lessons/paths.ts","../src/lessons/import-legacy.ts","../src/lessons/auto-migrate.ts","../src/core/errors.ts","../src/utils/filesystem/process-lock.ts","../src/lessons/lessons-lock.ts","../src/lessons/validate-checks.ts","../src/lessons/regex-linear/nfa-compile.ts","../src/lessons/regex-linear/nfa.ts","../src/lessons/regex-linear/ast.ts","../src/lessons/regex-linear/parse-helpers.ts","../src/lessons/regex-linear/parse.ts","../src/lessons/regex-linear/index.ts","../src/lessons/regex-safety.ts","../src/lessons/validate-quality.ts","../src/lessons/validate.ts","../src/lessons/mutate.ts","../src/lessons/trigger-effectiveness.ts","../src/lessons/add.ts","../src/lessons/ranking-signals.ts","../src/lessons/prune.ts","../src/lessons/auto-prune.ts","../src/lessons/jsonl-log.ts","../src/lessons/telemetry.ts","../src/lessons/capture-telemetry.ts","../src/lessons/normalize-query-file.ts","../src/lessons/project-files.ts","../src/lessons/keyword-match.ts","../src/lessons/query.ts","../src/lessons/ranking.ts","../src/lessons/recall-config.ts","../src/lessons/seen-cache.ts","../src/lessons/recall.ts","../src/lessons/merge.ts","../src/lessons/strip-markers.ts","../src/lessons/recall-hook-scaffold.ts","../src/utils/filesystem/fs-text-encoding.ts","../src/utils/filesystem/fs.ts","../src/utils/filesystem/gitignore.ts","../src/targets/projection/managed-blocks.ts","../src/targets/projection/lessons-paragraph.ts","../src/utils/text/markdown.ts","../src/lessons/skill.ts","../src/lessons/init.ts"],"names":["spec","basename","z","makeTriggerId","TRIGGER_PREFIX","createHash","existsSync","join","readFileSync","parseYaml","todayIso","dirname","rmSync","resolve","mkdir","hex","normalizeRule","activeTriggerIds","mkdirSync","writeFileSync","renameSync","relative","picomatch","union","changedIds","readFile","lstat","unlink","writeFile","rename","rm","yamlStringify"],"mappings":"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","file":"lessons.js","sourcesContent":["import { z } from 'zod';\n\n/** Schema version this build reads/writes. A graph stamped higher is from a newer CLI. */\nexport const CURRENT_GRAPH_VERSION = 1;\n\n/**\n * Upper bound on a lesson rule's length, in characters. A rule is one imperative\n * sentence; this is generous headroom. Enforced as a BLOCK at capture (a longer\n * rule is a capture defect) and as a defensive TRUNCATION at hook emission, so a\n * cloned-repo graph with a megabyte-scale rule cannot flood an agent's context.\n * It is deliberately NOT a schema `.max()`: that would mark such a graph\n * \"corrupt\" and disable ALL recall — a worse outcome than truncating one rule.\n */\nexport const MAX_RULE_LENGTH = 2000;\n\nconst IdSchema = z.string().regex(/^[a-z0-9-]+$/, 'id must be kebab-case');\nconst DateSchema = z\n .string()\n .regex(\n /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?Z?)?$/,\n 'createdAt must be ISO-8601 date or datetime',\n );\n\nconst TopicSchema = z\n .object({\n summary: z.string().min(1, 'topic summary must not be empty'),\n })\n .strict();\n\nconst TriggerKindSchema = z.enum(['file_glob', 'command_pattern', 'keyword']);\n\nconst TriggerSchema = z\n .object({\n kind: TriggerKindSchema,\n pattern: z.string().min(1, 'trigger pattern must not be empty'),\n })\n .strict();\n\nconst LessonStatusSchema = z.enum(['active', 'deprecated', 'superseded']);\n\nconst LessonSchema = z\n .object({\n rule: z.string().min(1, 'lesson rule must not be empty'),\n rationale: z.string().min(1).optional(),\n topics: z.array(IdSchema).min(1, 'lesson must reference at least one topic'),\n triggers: z.array(IdSchema),\n evidence: z.array(z.string().min(1)),\n status: LessonStatusSchema,\n supersededBy: IdSchema.optional(),\n createdAt: DateSchema,\n })\n .strict();\n\nexport const LessonsGraphSchema = z\n .object({\n version: z.literal(CURRENT_GRAPH_VERSION),\n lessons: z.record(IdSchema, LessonSchema),\n topics: z.record(IdSchema, TopicSchema),\n triggers: z.record(IdSchema, TriggerSchema),\n })\n .strict();\n\nexport type LessonsGraph = z.infer<typeof LessonsGraphSchema>;\nexport type Lesson = z.infer<typeof LessonSchema>;\nexport type Topic = z.infer<typeof TopicSchema>;\nexport type Trigger = z.infer<typeof TriggerSchema>;\nexport type TriggerKind = z.infer<typeof TriggerKindSchema>;\nexport type LessonStatus = z.infer<typeof LessonStatusSchema>;\n\nexport function parseGraph(raw: unknown): LessonsGraph {\n return LessonsGraphSchema.parse(raw);\n}\n","import { createHash } from 'node:crypto';\nimport type { AddLessonTriggers } from './add.js';\nimport type { LessonsGraph, Trigger, TriggerKind } from './graph-schema.js';\n\nexport function normalizeRule(rule: string): string {\n return rule.trim().replace(/\\s+/g, ' ').toLowerCase();\n}\n\nexport function union(base: readonly string[], extra: readonly string[]): string[] {\n const out = [...base];\n for (const item of extra) if (!out.includes(item)) out.push(item);\n return out;\n}\n\ninterface TriggerSpec {\n readonly kind: TriggerKind;\n readonly pattern: string;\n}\n\n/** Resolve/create trigger nodes for the requested patterns; returns referenced + newly-created ids. */\nexport function mergeTriggers(\n graph: LessonsGraph,\n spec: AddLessonTriggers,\n): { triggerIds: string[]; newTriggerIds: string[] } {\n const requested: TriggerSpec[] = [\n // Normalize `\\` → `/` so a Windows-shaped glob matches: recall relativizes\n // every `--file` to forward slashes (normalizeRecallFile), so a backslash\n // pattern stored raw would silently never fire. Normalizing here also lets\n // a backslash pattern dedupe against the forward-slash node it equals.\n ...(spec.files ?? []).map(\n (p): TriggerSpec => ({ kind: 'file_glob', pattern: p.replaceAll('\\\\', '/') }),\n ),\n ...(spec.commands ?? []).map((p): TriggerSpec => ({ kind: 'command_pattern', pattern: p })),\n ...(spec.keywords ?? []).map((p): TriggerSpec => ({ kind: 'keyword', pattern: p })),\n ];\n\n const reverseLookup = new Map<string, string>();\n for (const [id, trigger] of Object.entries(graph.triggers)) {\n reverseLookup.set(triggerKey(trigger), id);\n }\n\n const triggerIds: string[] = [];\n const newTriggerIds: string[] = [];\n for (const spec of requested) {\n const key = triggerKey(spec);\n const existing = reverseLookup.get(key);\n if (existing !== undefined) {\n if (!triggerIds.includes(existing)) triggerIds.push(existing);\n continue;\n }\n const id = makeTriggerId(spec);\n graph.triggers[id] = { kind: spec.kind, pattern: spec.pattern };\n reverseLookup.set(key, id);\n triggerIds.push(id);\n newTriggerIds.push(id);\n }\n return { triggerIds, newTriggerIds };\n}\n\nfunction triggerKey(t: TriggerSpec | Trigger): string {\n return `${t.kind}|${t.pattern}`;\n}\n\nconst TRIGGER_PREFIX: Record<TriggerKind, string> = {\n file_glob: 'glob',\n command_pattern: 'cmd',\n keyword: 'kw',\n};\n\nfunction makeTriggerId(spec: TriggerSpec): string {\n const hash = createHash('sha1').update(triggerKey(spec)).digest('hex').slice(0, 8);\n return `t-${TRIGGER_PREFIX[spec.kind]}-${hash}`;\n}\n\nexport function makeLessonId(graph: LessonsGraph, topic: string, ruleKey: string): string {\n const slug = ruleToSlug(ruleKey);\n const base =\n slug.length > 0\n ? `${topic}-${slug}`\n : `${topic}-${createHash('sha1').update(ruleKey).digest('hex').slice(0, 8)}`;\n let candidate = base;\n let i = 2;\n while (graph.lessons[candidate] !== undefined) {\n candidate = `${base}-${i}`;\n i += 1;\n }\n return candidate;\n}\n\nfunction ruleToSlug(rule: string): string {\n const words = rule\n .replace(/[^a-z0-9 ]+/g, ' ')\n .split(/\\s+/)\n .filter((w) => w.length > 0)\n .slice(0, 5);\n return words.join('-').slice(0, 40).replace(/-+$/, '');\n}\n\nexport function todayIso(): string {\n const now = new Date();\n const y = now.getUTCFullYear();\n const m = String(now.getUTCMonth() + 1).padStart(2, '0');\n const d = String(now.getUTCDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n}\n","import type { IneffectiveTrigger } from './trigger-effectiveness.js';\n\n/**\n * Capture rejection errors thrown by {@link addLessonInto}. Kept in their own\n * module so `add.ts` stays focused on the mutation logic; re-exported from\n * `add.js` so every existing importer keeps its `from './add.js'` path.\n */\n\nexport class UnknownTopicError extends Error {\n readonly code = 'UNKNOWN_TOPIC';\n constructor(public readonly topic: string) {\n super(`Unknown topic: ${topic}. Pass allowNewTopic + topicSummary to create it.`);\n this.name = 'UnknownTopicError';\n }\n}\n\n/**\n * Thrown when a capture's rule text exceeds {@link MAX_RULE_LENGTH}. A rule is\n * one imperative sentence; a far longer one is a malformed capture (a pasted log,\n * a whole diff) that would bloat every recall that surfaces it.\n */\nexport class RuleTooLongError extends Error {\n readonly code = 'OVERSIZED_RULE';\n constructor(\n public readonly length: number,\n public readonly max: number,\n ) {\n super(\n `Lesson rule is ${length} characters (max ${max}). A rule should be one imperative ` +\n 'sentence — trim it to the essential instruction, or split it into separate lessons.',\n );\n this.name = 'RuleTooLongError';\n }\n}\n\n/** Thrown when a capture would leave a lesson with no trigger (unrecallable). */\nexport class NoTriggerError extends Error {\n readonly code = 'NO_TRIGGER';\n constructor() {\n super(\n 'A lesson needs at least one trigger to be recallable. Pass --trigger-file <glob> ' +\n '(preferred), --trigger-cmd <regex>, or --trigger-kw <text>.',\n );\n this.name = 'NoTriggerError';\n }\n}\n\n/**\n * Thrown when a capture would leave a lesson whose every trigger is dead on the\n * mandatory `--file`/`--cmd` recall path (a stopword-only keyword, an invalid or\n * ReDoS-shaped command regex). The lesson would be captured then silently never\n * recalled — so capture is rejected with the dead triggers named and a fix.\n */\nexport class UnrecallableLessonError extends Error {\n readonly code = 'UNRECALLABLE_LESSON';\n constructor(public readonly deadTriggers: readonly IneffectiveTrigger[]) {\n super(\n 'This capture would create a lesson with no effective trigger — every trigger is dead ' +\n 'on the mandatory --file/--cmd recall path, so the lesson could never be recalled there:\\n' +\n deadTriggers.map((t) => ` • ${t.kind} \"${t.pattern}\" — ${t.reason}`).join('\\n') +\n '\\nFix: add a precise --trigger-file <glob> (preferred) or a valid --trigger-cmd <regex>; ' +\n 'for a keyword, drop the stopwords (e.g. \"state art\" not \"state of the art\").',\n );\n this.name = 'UnrecallableLessonError';\n }\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport type { LessonsQuery } from './query.js';\n\n/**\n * Text/BM25 helpers for {@link rankLessons}. Split out of ranking.ts to keep\n * each file within the repository 200-line limit; this module owns tokenization\n * and the BM25 corpus, ranking.ts owns fusion and capping.\n */\n\nconst K1 = 1.5;\nconst B = 0.75;\nconst STOP = new Set([\n 'the',\n 'a',\n 'an',\n 'to',\n 'of',\n 'in',\n 'and',\n 'or',\n 'for',\n 'is',\n 'on',\n 'at',\n 'with',\n 'be',\n 'as',\n 'it',\n 'that',\n 'this',\n 'its',\n 'must',\n]);\n\nexport function tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length >= 2 && !STOP.has(t));\n}\n\nexport function queryTerms(query: LessonsQuery): string[] {\n const parts: string[] = [];\n if (query.keyword !== undefined) parts.push(query.keyword);\n if (query.file !== undefined) parts.push(query.file);\n if (query.command !== undefined) parts.push(query.command);\n return tokenize(parts.join(' '));\n}\n\nexport interface Corpus {\n readonly idf: Map<string, number>;\n readonly avgdl: number;\n}\n\nexport function buildCorpus(graph: LessonsGraph): Corpus {\n const docs: number[] = [];\n const df = new Map<string, number>();\n let total = 0;\n let n = 0;\n for (const lesson of Object.values(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n const toks = tokenize(lesson.rule);\n n += 1;\n total += toks.length;\n docs.push(toks.length);\n for (const t of new Set(toks)) df.set(t, (df.get(t) ?? 0) + 1);\n }\n // rankLessons short-circuits on empty matches, so the corpus always has >= 1\n // active lesson when we get here; N is therefore >= 1.\n const N = Math.max(n, 1);\n const idf = new Map<string, number>();\n for (const [t, f] of df) idf.set(t, Math.log(1 + (N - f + 0.5) / (f + 0.5)));\n return { idf, avgdl: total / N || 1 };\n}\n\nexport function bm25(terms: readonly string[], ruleText: string, corpus: Corpus): number {\n const toks = tokenize(ruleText);\n const dl = toks.length || 1;\n const tf = new Map<string, number>();\n for (const t of toks) tf.set(t, (tf.get(t) ?? 0) + 1);\n let score = 0;\n for (const t of new Set(terms)) {\n const f = tf.get(t) ?? 0;\n if (f === 0) continue;\n // f > 0 ⇒ the term is in this active lesson's rule ⇒ it is in the corpus idf.\n const idf = corpus.idf.get(t)!;\n score += (idf * (f * (K1 + 1))) / (f + K1 * (1 - B + (B * dl) / corpus.avgdl));\n }\n return score;\n}\n","import { tokenize } from './ranking-text.js';\n\n/**\n * Keyword-trigger \"signal\" guard shared by capture guardrails and `validate`.\n *\n * A keyword trigger fires ONLY when its full pattern is a substring of an\n * explicit `--keyword`, OR its tokens appear as a CONTIGUOUS run in the\n * `--file`/`--cmd` tokens (see keyword-match.ts). The needle that must match is\n * exactly {@link tokenize}(pattern), so the more tokens a pattern carries the\n * less likely either path matches — a long descriptive pattern (a sentence of\n * keywords) is effectively dead: it is never a substring of a realistic\n * `--keyword` and never appears contiguously in a file path. Authors should use\n * a short distinctive phrase instead.\n */\n\n/** Soft cap on keyword-trigger token count; past this, recall rarely matches. */\nexport const MAX_RECOMMENDED_KEYWORD_TOKENS = 5;\n\n/** True when a keyword pattern carries more matchable tokens than recall can realistically hit. */\nexport function isLowSignalKeyword(pattern: string): boolean {\n return tokenize(pattern).length > MAX_RECOMMENDED_KEYWORD_TOKENS;\n}\n\n/** Lowercase alphanumeric tokens, order-preserving, UNFILTERED — mirrors the recall haystack. */\nfunction splitRawTokens(pattern: string): string[] {\n return pattern\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 0);\n}\n\n/**\n * True when the pattern's stopword-FILTERED needle differs from its raw token\n * run — i.e. the multi-word phrase contains a stopword/short token. The recall\n * haystack keeps stopwords, so such a needle can never appear as a contiguous\n * run in text containing the literal phrase (\"state of the art\" → needle\n * `[state, art]` never matches `[state, of, the, art]`): the trigger is\n * structurally unmatchable on the `--file`/`--cmd` path.\n */\nexport function keywordNeedleLosesTokens(pattern: string): boolean {\n const raw = splitRawTokens(pattern);\n if (raw.length < 2) return false; // single-word patterns can't have a gap\n return tokenize(pattern).length !== raw.length;\n}\n","import picomatch from 'picomatch';\nimport type { LessonsGraph } from './graph-schema.js';\nimport type { ValidationFinding } from './validate.js';\n\n/**\n * Trigger-LIVENESS checks: a trigger referenced by an active lesson that can\n * never fire makes the lesson unreachable, silently, as the codebase moves\n * underneath it. These are distinct from breadth — the system deliberately\n * optimizes for precision, so neither check ever asks to WIDEN a narrow trigger;\n * `collectDeadFileGlobs` flags a glob that matches *nothing*, and\n * `collectRunnerAnchoredPatterns` flags a scope-MATCH gap (anchored to one\n * runner), not a scope-too-narrow one.\n */\n\nfunction activeTriggerIds(graph: LessonsGraph): Set<string> {\n const ids = new Set<string>();\n for (const lesson of Object.values(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n for (const t of lesson.triggers) ids.add(t);\n }\n return ids;\n}\n\n/**\n * The set of `file_glob` triggers (referenced by an active lesson) that match NO\n * path in the working tree — dead, in the liveness sense. Shared by `validate`\n * (which warns) and `prune` (which can GC them when doing so won't strand a\n * lesson). `knownPaths` is project-relative, forward-slash.\n */\nexport function deadFileGlobIds(\n graph: LessonsGraph,\n knownPaths: ReadonlySet<string>,\n): Set<string> {\n const active = activeTriggerIds(graph);\n const paths = [...knownPaths];\n const dead = new Set<string>();\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'file_glob') continue;\n if (!active.has(triggerId)) continue;\n const isMatch = picomatch(trigger.pattern, { dot: true });\n if (!paths.some((p) => isMatch(p))) dead.add(triggerId);\n }\n return dead;\n}\n\n/**\n * A `file_glob` (referenced by an active lesson) that matches NO path in the\n * working tree is dead — the lesson is unreachable via that trigger, almost\n * always because a refactor renamed the path it pointed at. Liveness, not\n * breadth: a narrow glob that still matches one file is fine; only a glob that\n * matches zero is reported. Caller supplies `knownPaths` (project-relative,\n * forward-slash); when it can't be determined the check is skipped entirely\n * (see {@link validateLessonsGraph}), so we never flag every glob dead.\n */\nexport function collectDeadFileGlobs(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n knownPaths: ReadonlySet<string>,\n): void {\n for (const triggerId of deadFileGlobIds(graph, knownPaths)) {\n findings.push({\n level: 'warning',\n code: 'DEAD_FILE_GLOB',\n message: `file_glob trigger \"${triggerId}\" (${graph.triggers[triggerId]?.pattern ?? ''}) matches no file in the working tree — the lesson is unreachable via this trigger (a rename likely moved the path). Re-point it at the current path, or detach it with \\`lessons untrigger\\`, or run \\`lessons prune --apply\\`.`,\n triggerId,\n });\n }\n}\n\n/** Anchored to a single package-runner at the start of the pattern. */\nconst RUNNER_ANCHOR = /^\\^(pnpm|npm|npx|yarn|bun)\\b/;\n\n/**\n * A `command_pattern` anchored to ONE runner (e.g. `^pnpm test`, `^npx vitest`)\n * will not fire for the same task run another way — an agent that types\n * `npx vitest` gets nothing from a `^pnpm` lesson, and `npx` is the shape agents\n * actually use. Scope-MATCH, not breadth: the fix is to drop the `^<runner>`\n * anchor and key on the task verb, not to widen what the lesson covers.\n */\nexport function collectRunnerAnchoredPatterns(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n): void {\n const active = activeTriggerIds(graph);\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'command_pattern') continue;\n if (!active.has(triggerId)) continue;\n if (!RUNNER_ANCHOR.test(trigger.pattern)) continue;\n findings.push({\n level: 'warning',\n code: 'RUNNER_ANCHORED_PATTERN',\n message: `command_pattern trigger \"${triggerId}\" (${trigger.pattern}) is anchored to one runner — it won't fire for the same task via another runner (e.g. \\`npx\\` vs \\`pnpm\\`). Drop the \\`^<runner>\\` anchor and key on the task (e.g. \\`\\\\bvitest\\\\b\\`).`,\n triggerId,\n });\n }\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport {\n isLowSignalKeyword,\n keywordNeedleLosesTokens,\n MAX_RECOMMENDED_KEYWORD_TOKENS,\n} from './keyword-signal.js';\nimport { tokenize } from './ranking-text.js';\nimport { deadFileGlobIds } from './validate-liveness.js';\n\n/**\n * Capture guardrails — mostly WARNINGS, steering authors toward a few specific\n * triggers. Over-triggering (too many triggers per lesson, broad globs,\n * keyword-only triggers that fire less reliably on the mandatory `--file`/`--cmd`\n * path, long/stopworded keyword patterns) is the single biggest threat to recall\n * precision, and a paraphrase silently accumulates a near-duplicate; these are\n * surfaced without blocking, because an over-broad lesson is better than a lost\n * one.\n *\n * The ONE blocking case lives elsewhere (`addLessonInto` → `UnrecallableLessonError`):\n * a capture whose EVERY trigger is dead on the mandatory recall path is rejected,\n * because that lesson is captured then silently never recalled. These guardrails\n * are the warn-only complement to that single hard block.\n */\n\nexport type GuardrailCode =\n | 'OVERSIZED_LESSON_TRIGGERS'\n | 'BROAD_GLOB_TRIGGER'\n | 'KEYWORD_ONLY_LESSON'\n | 'LOW_SIGNAL_KEYWORD'\n | 'STOPWORD_KEYWORD'\n | 'DEAD_GLOB'\n | 'NEAR_DUPLICATE_LESSON';\n\n/** Token-Jaccard similarity at/above which a new lesson is flagged a near-duplicate. */\nexport const NEAR_DUPLICATE_THRESHOLD = 0.6;\n\nexport interface GuardrailWarning {\n readonly code: GuardrailCode;\n readonly message: string;\n}\n\n/** Soft cap: past this many triggers a lesson fires on too much and dilutes recall. */\nexport const MAX_RECOMMENDED_TRIGGERS = 8;\n\n/**\n * A glob is \"broad\" when it matches large swaths of the tree: a bare star or\n * double-star, or any pattern that contains a double-star segment AND whose\n * basename is itself a wildcard (starts with a star — e.g. a globstar followed\n * by a star-extension). A double-star with a concrete basename (a globstar\n * followed by `index.ts`) or a single-directory wildcard is specific enough and\n * is not flagged.\n */\nfunction isBroadGlob(pattern: string): boolean {\n const p = pattern.trim();\n if (p === '*' || p === '**') return true;\n if (!p.includes('**')) return false;\n const basename = p.slice(p.lastIndexOf('/') + 1);\n return basename.startsWith('*');\n}\n\n/**\n * Inspect a freshly captured/updated lesson and return any guardrail warnings.\n * Operates on the post-mutation graph so it reflects the merged trigger set of\n * an upserted lesson, not just the triggers from this one `add` call.\n *\n * `knownPaths` (project-relative, forward-slash) enables the DEAD_GLOB liveness\n * warning. The pure write-barrier path passes nothing (no tree walk on the hot\n * mutate path); only the capture entry point supplies it, so a dead glob is\n * flagged at the best moment to fix it — right after capture.\n */\nexport function inspectCapturedLesson(\n graph: LessonsGraph,\n lessonId: string,\n knownPaths?: ReadonlySet<string>,\n): GuardrailWarning[] {\n const lesson = graph.lessons[lessonId];\n if (lesson === undefined) return [];\n const warnings: GuardrailWarning[] = [];\n\n if (lesson.triggers.length > MAX_RECOMMENDED_TRIGGERS) {\n warnings.push({\n code: 'OVERSIZED_LESSON_TRIGGERS',\n message: `Lesson \"${lessonId}\" has ${lesson.triggers.length} triggers (recommended ≤ ${MAX_RECOMMENDED_TRIGGERS}); broad trigger sets fire on too many edits and dilute recall — prefer a few specific triggers.`,\n });\n }\n\n const triggers = lesson.triggers\n .map((id) => graph.triggers[id])\n .filter((t): t is NonNullable<typeof t> => t !== undefined);\n\n const broad = triggers\n .filter((t) => t.kind === 'file_glob' && isBroadGlob(t.pattern))\n .map((t) => t.pattern);\n if (broad.length > 0) {\n warnings.push({\n code: 'BROAD_GLOB_TRIGGER',\n message: `Lesson \"${lessonId}\" has broad file glob(s) (${broad.join(', ')}) that match large swaths of the tree; prefer a path specific to the lesson.`,\n });\n }\n\n if (triggers.length > 0 && triggers.every((t) => t.kind === 'keyword')) {\n warnings.push({\n code: 'KEYWORD_ONLY_LESSON',\n message: `Lesson \"${lessonId}\" has only keyword triggers; mandatory --file/--cmd recall surfaces these only when the keyword appears as a path/command token, so it fires less reliably — add a file_glob or command_pattern trigger for precise recall.`,\n });\n }\n\n const lowSignal = triggers\n .filter((t) => t.kind === 'keyword' && isLowSignalKeyword(t.pattern))\n .map((t) => t.pattern);\n if (lowSignal.length > 0) {\n warnings.push({\n code: 'LOW_SIGNAL_KEYWORD',\n message: `Lesson \"${lessonId}\" has long keyword trigger(s) (${lowSignal.join(', ')}); recall matches a keyword only as a substring of --keyword or a contiguous token-run in the file/command, so a pattern past ${MAX_RECOMMENDED_KEYWORD_TOKENS} tokens rarely fires — use a short distinctive phrase.`,\n });\n }\n\n const stopworded = triggers\n .filter((t) => t.kind === 'keyword' && keywordNeedleLosesTokens(t.pattern))\n .map((t) => t.pattern);\n if (stopworded.length > 0) {\n warnings.push({\n code: 'STOPWORD_KEYWORD',\n message: `Lesson \"${lessonId}\" has keyword trigger(s) containing stopwords/short words (${stopworded.join(', ')}); recall filters them from the pattern but NOT from the file/command text, so the phrase can never match contiguously on the --file/--cmd path — drop the stopwords (e.g. \"state art\" instead of \"state of the art\").`,\n });\n }\n\n if (knownPaths !== undefined) {\n const dead = deadFileGlobIds(graph, knownPaths);\n const deadHere = lesson.triggers\n .filter((id) => dead.has(id))\n .map((id) => graph.triggers[id]?.pattern)\n .filter((p): p is string => p !== undefined);\n if (deadHere.length > 0) {\n warnings.push({\n code: 'DEAD_GLOB',\n message: `Lesson \"${lessonId}\" has file_glob trigger(s) (${deadHere.join(', ')}) that match no file in the working tree — likely a rename. Re-point them at the current path, or the lesson is unreachable via those globs.`,\n });\n }\n }\n\n return warnings;\n}\n\n/**\n * Suggest updating an existing active lesson when a NEW lesson paraphrases it.\n * Dedup is exact-normalized-text only, so a reordered/reworded rule slips through\n * and both recall. This scans active lessons (skipping `lessonId` itself), scores\n * rule similarity with token Jaccard over {@link tokenize} (robust to word\n * reordering, no corpus needed), and returns one warning for the top match at or\n * above {@link NEAR_DUPLICATE_THRESHOLD}. Called only on the new-lesson branch —\n * an upsert IS the match, and exact matches already upserted before reaching here.\n */\nexport function nearDuplicateWarning(\n graph: LessonsGraph,\n lessonId: string,\n): GuardrailWarning | null {\n const subject = graph.lessons[lessonId];\n if (subject === undefined) return null;\n const subjectTokens = new Set(tokenize(subject.rule));\n if (subjectTokens.size === 0) return null;\n\n let best: { id: string; score: number } | null = null;\n for (const [id, other] of Object.entries(graph.lessons)) {\n if (id === lessonId || other.status !== 'active') continue;\n const otherTokens = new Set(tokenize(other.rule));\n if (otherTokens.size === 0) continue;\n const score = jaccard(subjectTokens, otherTokens);\n if (score >= NEAR_DUPLICATE_THRESHOLD && (best === null || score > best.score)) {\n best = { id, score };\n }\n }\n if (best === null) return null;\n return {\n code: 'NEAR_DUPLICATE_LESSON',\n message: `Lesson \"${lessonId}\" closely resembles active lesson \"${best.id}\" (~${Math.round(best.score * 100)}% token overlap); consider updating \"${best.id}\" instead of adding a paraphrase (recall would surface both).`,\n };\n}\n\nfunction jaccard(a: ReadonlySet<string>, b: ReadonlySet<string>): number {\n let intersection = 0;\n for (const t of a) if (b.has(t)) intersection += 1;\n return intersection / (a.size + b.size - intersection);\n}\n","import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { CURRENT_GRAPH_VERSION, parseGraph, type LessonsGraph } from './graph-schema.js';\n\nconst GRAPH_REL_PATH = '.agentsmesh/lessons/lessons.json';\n\nexport function graphFilePath(projectRoot: string): string {\n return resolve(projectRoot, GRAPH_REL_PATH);\n}\n\nexport function loadLessonsGraph(projectRoot: string): LessonsGraph {\n const raw = readFileSync(graphFilePath(projectRoot), 'utf8');\n return parseGraph(JSON.parse(raw));\n}\n\nexport function tryLoadLessonsGraph(projectRoot: string): LessonsGraph | null {\n if (!existsSync(graphFilePath(projectRoot))) return null;\n return loadLessonsGraph(projectRoot);\n}\n\n/** Outcome of a non-throwing graph load — distinguishes absent from corrupt. */\nexport type ResilientGraphLoad =\n | { status: 'absent'; graph: null }\n | { status: 'ok'; graph: LessonsGraph }\n | { status: 'newer-version'; graph: null; version: number }\n | { status: 'corrupt'; graph: null; error: Error };\n\n/**\n * Load the canonical graph WITHOUT throwing. Recall is a blocking requirement\n * before every edit and command, so a corrupt graph (a bad merge conflict in\n * the git-tracked JSON, a truncated file, or schema drift) must degrade to\n * \"no lessons\" rather than crash the agent's whole workflow with a stack trace.\n * Callers surface the `corrupt` outcome as a user-facing warning; the throwing\n * {@link loadLessonsGraph} stays the contract for paths that WANT to fail loud\n * (lint, validate).\n *\n * A graph stamped with a numeric `version` greater than this build's\n * {@link CURRENT_GRAPH_VERSION} is reported as `newer-version` (not `corrupt`):\n * the file is fine, the CLI is simply behind, so callers can show an upgrade\n * hint instead of a misleading \"corrupt\" warning.\n */\nexport function loadLessonsGraphResilient(projectRoot: string): ResilientGraphLoad {\n const path = graphFilePath(projectRoot);\n if (!existsSync(path)) return { status: 'absent', graph: null };\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n const version = (parsed as { version?: unknown } | null)?.version;\n if (typeof version === 'number' && version > CURRENT_GRAPH_VERSION) {\n return { status: 'newer-version', graph: null, version };\n }\n return { status: 'ok', graph: parseGraph(parsed) };\n } catch (error) {\n return {\n status: 'corrupt',\n graph: null,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n\nexport function saveLessonsGraph(projectRoot: string, graph: LessonsGraph): void {\n const path = graphFilePath(projectRoot);\n mkdirSync(dirname(path), { recursive: true });\n // Atomic write: a crash mid-write must never truncate the canonical graph.\n // Write to a sibling temp file, then rename over the target (atomic on the\n // same filesystem). The lessons lock serializes writers, so the pid-scoped\n // temp name cannot collide in practice.\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, serializeGraph(graph), 'utf8');\n renameSync(tmp, path);\n}\n\n/**\n * Deterministic serialization: every object's keys are emitted in alphabetical\n * order so diffs reflect content changes rather than insertion order. Output\n * always ends with a single trailing newline to keep CRLF/POSIX diffs clean.\n */\nexport function serializeGraph(graph: LessonsGraph): string {\n return `${JSON.stringify(canonicalize(graph), null, 2)}\\n`;\n}\n\n/**\n * Order-independent canonical string for a value — equal content compares equal\n * regardless of key insertion order. Used by the merge driver to tell an\n * unchanged record from a genuinely divergent one.\n */\nexport function stableStringify(value: unknown): string {\n return JSON.stringify(canonicalize(value));\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (value === null) return null;\n if (Array.isArray(value)) return value.map(canonicalize);\n if (typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) =>\n a < b ? -1 : 1,\n );\n const out: Record<string, unknown> = {};\n for (const [k, v] of entries) out[k] = canonicalize(v);\n return out;\n }\n return value;\n}\n","import { createHash } from 'node:crypto';\nimport { existsSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { z } from 'zod';\nimport type { Trigger, TriggerKind } from './graph-schema.js';\n\nconst LegacyTriggersSchema = z\n .object({\n file_globs: z.array(z.string()),\n command_patterns: z.array(z.string()),\n keywords: z.array(z.string()),\n })\n .refine((t) => t.file_globs.length + t.command_patterns.length + t.keywords.length > 0, {\n message: 'cluster must declare at least one trigger of any type',\n });\n\nconst LegacyClusterSchema = z.object({\n topic: z.string().regex(/^[a-z0-9-]+$/),\n file: z.string().regex(/\\.md$/),\n summary: z.string().min(1),\n triggers: LegacyTriggersSchema,\n});\n\nexport const LegacyIndexSchema = z.object({\n version: z.literal(1),\n clusters: z.array(LegacyClusterSchema),\n});\n\ntype LegacyCluster = z.infer<typeof LegacyClusterSchema>;\n\ninterface TriggerSpec {\n readonly kind: TriggerKind;\n readonly pattern: string;\n}\n\nexport function collectClusterTriggerIds(\n cluster: LegacyCluster,\n triggersById: Map<string, Trigger>,\n triggerIdByKey: Map<string, string>,\n): string[] {\n const specs: TriggerSpec[] = [\n ...cluster.triggers.file_globs.map((p): TriggerSpec => ({ kind: 'file_glob', pattern: p })),\n ...cluster.triggers.command_patterns.map(\n (p): TriggerSpec => ({ kind: 'command_pattern', pattern: p }),\n ),\n ...cluster.triggers.keywords.map((p): TriggerSpec => ({ kind: 'keyword', pattern: p })),\n ];\n\n const ids: string[] = [];\n for (const spec of specs) {\n const key = `${spec.kind}|${spec.pattern}`;\n let id = triggerIdByKey.get(key);\n if (id === undefined) {\n id = makeTriggerId(spec);\n triggerIdByKey.set(key, id);\n triggersById.set(id, { kind: spec.kind, pattern: spec.pattern });\n }\n if (!ids.includes(id)) ids.push(id);\n }\n return ids;\n}\n\nconst TRIGGER_PREFIX: Record<TriggerKind, string> = {\n file_glob: 'glob',\n command_pattern: 'cmd',\n keyword: 'kw',\n};\n\nfunction makeTriggerId(spec: TriggerSpec): string {\n const hash = createHash('sha1').update(`${spec.kind}|${spec.pattern}`).digest('hex').slice(0, 8);\n return `t-${TRIGGER_PREFIX[spec.kind]}-${hash}`;\n}\n\nexport interface ParsedRule {\n readonly index: number;\n readonly body: string;\n readonly evidence: string[];\n}\n\nconst RULE_HEADING_RE = /^##\\s+Rules\\b.*$/i;\nconst NEXT_HEADING_RE = /^##\\s+/;\nconst RULE_LINE_RE = /^(\\d+)\\.\\s+(.+?)\\s*$/;\nconst EVIDENCE_TAIL_RE = /\\s*\\(Evidence:?\\s+([^)]+)\\)\\s*$/;\nconst EVIDENCE_REF_RE = /L\\d+/g;\n\nexport function parseRulesSection(markdown: string): ParsedRule[] {\n const lines = markdown.split(/\\r?\\n/);\n let inRules = false;\n const rules: ParsedRule[] = [];\n\n for (const line of lines) {\n if (!inRules) {\n if (RULE_HEADING_RE.test(line)) inRules = true;\n continue;\n }\n if (NEXT_HEADING_RE.test(line)) break;\n\n const m = RULE_LINE_RE.exec(line);\n if (m === null) continue;\n\n const ruleIndex = Number(m[1]);\n // Group 2 `(.+?)` is mandatory in RULE_HEADING's line regex, so it is always\n // present when the line matched; same for the EVIDENCE tail's `([^)]+)`.\n let body = m[2]!;\n const evidence: string[] = [];\n\n let tail = EVIDENCE_TAIL_RE.exec(body);\n while (tail !== null) {\n const refs = tail[1]!;\n const matches = refs.match(EVIDENCE_REF_RE);\n if (matches !== null) evidence.unshift(...matches);\n body = body.slice(0, tail.index).trimEnd();\n tail = EVIDENCE_TAIL_RE.exec(body);\n }\n\n rules.push({ index: ruleIndex, body, evidence });\n }\n\n return rules;\n}\n\nconst LEGACY_ARTIFACT_REL = [\n 'index.yaml',\n 'journal.md',\n 'journal.legacy.md',\n 'topics',\n 'distill-ledger.yaml',\n 'distill-proposal.md',\n] as const;\n\nexport function deleteLegacyArtifacts(baseDir: string): string[] {\n const deleted: string[] = [];\n for (const rel of LEGACY_ARTIFACT_REL) {\n const abs = join(baseDir, rel);\n if (!existsSync(abs)) continue;\n rmSync(abs, { recursive: true, force: true });\n deleted.push(abs);\n }\n return deleted;\n}\n","/**\n * MERGE-recovery for the legacy migrator: fold legacy lesson specs into an\n * existing graph through the normal capture path (rule-text dedup,\n * content-addressed trigger dedup, topic union), then remove the legacy\n * artifacts. Never overwrites graph data, so it safely recovers a stranded\n * legacy store coexisting with a populated `lessons.json`.\n */\n\nimport { addLessonInto, type AddLessonInput } from './add.js';\nimport { deleteLegacyArtifacts } from './import-legacy-parse.js';\nimport type { ImportLegacyOptions, ImportLegacyReport } from './import-legacy.js';\nimport { mutateLessonsGraphLocked } from './mutate.js';\nimport type { LessonsPaths } from './paths.js';\n\nexport async function mergeLegacy(\n projectRoot: string,\n paths: LessonsPaths,\n specs: AddLessonInput[],\n summaryByTopic: Map<string, string>,\n options: ImportLegacyOptions,\n): Promise<ImportLegacyReport> {\n let addedLessons = 0;\n const addedTriggers = new Set<string>();\n const touchedTopics = new Set<string>();\n await mutateLessonsGraphLocked(projectRoot, (g) => {\n addedLessons = 0;\n addedTriggers.clear();\n touchedTopics.clear();\n for (const spec of specs) {\n const result = addLessonInto(g, spec, {\n allowNewTopic: true,\n topicSummary: summaryByTopic.get(spec.topic),\n // Legacy lessons may predate the ≥1-trigger requirement; recover them\n // as-is rather than dropping historical knowledge.\n allowNoTrigger: true,\n });\n if (result.isNewLesson) addedLessons += 1;\n for (const t of result.newTriggerIds) addedTriggers.add(t);\n touchedTopics.add(spec.topic);\n }\n });\n\n const deletedPaths = options.deleteLegacy === false ? [] : deleteLegacyArtifacts(paths.base);\n\n return {\n wroteGraphPath: paths.graph,\n deletedPaths,\n topicCount: touchedTopics.size,\n lessonCount: addedLessons,\n triggerCount: addedTriggers.size,\n };\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\n\n/**\n * Default on-disk locations for the lessons subsystem.\n *\n * Canonical store: `<projectRoot>/.agentsmesh/lessons/lessons.json` (the JSON\n * graph). The legacy paths (`journal`, `index`, `topicsDir`) are retained for\n * the one-shot upgrade migrator only; fresh projects never create them.\n */\nexport interface LessonsPaths {\n /** Directory containing every lessons artifact. */\n readonly base: string;\n /** Canonical JSON graph — the single source of truth. */\n readonly graph: string;\n /** Optional per-project recall tuning (recallLimit / recallMaxTokens). */\n readonly config: string;\n /** Legacy append-only journal. Used by the migrator only. */\n readonly journal: string;\n /** Legacy YAML trigger index. Used by the migrator only. */\n readonly index: string;\n /** Legacy per-topic Markdown directory. Used by the migrator only. */\n readonly topicsDir: string;\n}\n\nconst BASE_REL = '.agentsmesh/lessons';\n\nexport function lessonsPaths(projectRoot: string): LessonsPaths {\n const base = join(projectRoot, BASE_REL);\n return {\n base,\n graph: join(base, 'lessons.json'),\n config: join(base, 'config.json'),\n journal: join(base, 'journal.md'),\n index: join(base, 'index.yaml'),\n topicsDir: join(base, 'topics'),\n };\n}\n\n/**\n * Whether the lessons subsystem was fully set up via `agentsmesh init --lessons`\n * (or the import safety net) — as opposed to a graph-only state a bare\n * `lessons add` bootstraps. `config.json` is the tell: `scaffoldLessons` seeds it,\n * but the transactional capture path never does, so its presence means the\n * recall ritual + hook + skill were all wired too. When this is false, lessons\n * may exist on disk but no agent is told to recall them.\n */\nexport function lessonsActivated(projectRoot: string): boolean {\n return existsSync(lessonsPaths(projectRoot).config);\n}\n\n/** The one-line \"you haven't enabled lessons\" pointer the read/capture paths show. */\nexport function lessonsSetupHint(): string {\n return 'lessons is not fully set up here — run `agentsmesh init --lessons`, then `agentsmesh generate`, to wire recall + capture into your AI tools.';\n}\n\n/**\n * Walk up from `projectRoot`'s parent looking for an ancestor that holds a\n * lessons GRAPH (`.agentsmesh/lessons/lessons.json`), returning the first match\n * (or null). Lessons commands resolve their root from the CWD, so an invocation\n * from a subdirectory of a real lessons project silently reads/writes the wrong\n * place — empty recall, or a stray graph created in the subdir. Callers use this\n * to warn (not to relocate: staying CWD-rooted keeps every command consistent).\n *\n * It deliberately keys off the graph file, NOT a bare `.agentsmesh` dir: the\n * global-mode config lives at `~/.agentsmesh` and never holds a lessons graph\n * (`--lessons` is project-only), so matching `.agentsmesh` alone would fire a\n * false \"a project exists above\" on every directory under the home folder.\n */\nexport function ancestorLessonsProjectDir(projectRoot: string): string | null {\n let dir = dirname(resolve(projectRoot));\n let prev = '';\n while (dir !== prev) {\n if (existsSync(lessonsPaths(dir).graph)) return dir;\n prev = dir;\n dir = dirname(dir);\n }\n return null;\n}\n\n/**\n * Project-relative path for a given absolute path, normalized to forward\n * slashes for cross-platform consistency in markdown rule files.\n */\nexport function toRelPath(projectRoot: string, absolute: string): string {\n return relative(projectRoot, absolute).split(sep).join('/');\n}\n\n/**\n * Tier 1 of the lessons contract: the always-on trigger.\n *\n * Lives in the project's root rule (`.agentsmesh/rules/_root.md`) as a managed\n * block, so it reaches every target through canonical rule generation. Universal:\n * only requires the ability to shell-exec the `agentsmesh` CLI. No `Skill` tool,\n * no description-match, no per-target projection.\n *\n * Deliberately minimal — it carries only the BINDING essentials (both commands,\n * the BLOCKING framing, the recall scope, the broad capture scope, the graph\n * path, the MCP fallback). The expansive how-to (full command set, topic\n * workflow, trigger-flag mechanics, the complete rejected-excuse enumeration, and\n * the rebuttal pedagogy) lives in the `lessons` skill (`LESSONS_SKILL_BODY`) so\n * the manual can grow without bloating every target's always-on context.\n *\n * Recall is scoped to MUTATING actions — file edits and state-changing commands —\n * with pure-read commands and the recall query itself explicitly exempt. This\n * removes the infinite regress (recall before the recall command) and the\n * most-flouted \"read-only included\" clause, cutting guarded actions roughly in\n * half (exploration is read-heavy) while keeping recall where it changes outcomes.\n *\n * Structural shape (heading + intro + Recall block + Capture block + closing)\n * survives generate → import → generate round-trip; only the wording inside each\n * block is tightened for maximum agent compliance.\n */\nexport const LESSONS_PROCEDURAL_RULE = `## Lessons (BLOCKING REQUIREMENT — MUST run both, no exceptions; the user will check)\n\nGraph \\`.agentsmesh/lessons/lessons.json\\` is canonical — never hand-edit. Manual: the \\`lessons\\` skill.\n\n**Recall — MUST run before every file edit and every state-changing command** (build/test/install/migrate/git-write): \\`agentsmesh lessons query --file <path> --cmd <command>\\`, then apply every rule. Pure-read commands (cat/ls/grep/git-log) and the recall query itself are exempt.\n\n**Capture — MUST run immediately after any failure** (a failing test/CI/lint/typecheck, a code review, a user correction, a regression, or a wrong assumption — yours or anyone's): \\`agentsmesh lessons add \"<rule>\" --topic <id> --trigger-file <glob> --evidence <sha|lesson-id>\\`.\n\nNo shell? Use the \\`lessons_query\\` / \\`lessons_add\\` MCP tools. Skip either and the system does not exist.`;\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { AddLessonInput } from './add.js';\nimport type { Lesson, Topic, Trigger } from './graph-schema.js';\nimport {\n collectClusterTriggerIds,\n deleteLegacyArtifacts,\n LegacyIndexSchema,\n parseRulesSection,\n} from './import-legacy-parse.js';\nimport { mergeLegacy } from './import-legacy-merge.js';\nimport { lessonsPaths } from './paths.js';\nimport { mutateLessonsGraphLocked } from './mutate.js';\n\nexport interface ImportLegacyOptions {\n /** ISO date stamped onto every imported lesson's `createdAt`. */\n readonly migratedAt: string;\n /**\n * When `true` (default), delete the legacy `index.yaml`, `journal.md`,\n * `topics/`, `distill-ledger.yaml`, and `distill-proposal.md` after a\n * successful migration. Pass `false` to leave them in place (test-only).\n */\n readonly deleteLegacy?: boolean;\n /**\n * Overwrite an existing non-empty graph. Default `false`: migration refuses\n * (throws {@link LessonsGraphExistsError}) when, AT WRITE TIME UNDER THE LOCK,\n * the graph already has lessons — so a concurrent capture is never erased.\n */\n readonly force?: boolean;\n /**\n * MERGE legacy lessons INTO an existing graph instead of replacing it. This is\n * the recovery path for a stranded state — legacy `index.yaml` coexisting with\n * a populated `lessons.json` (an old binary could create this). Each legacy\n * lesson is folded in via the normal capture path: rules dedup by text,\n * triggers content-address and dedup, topics union. Never overwrites graph\n * data; `force` is irrelevant in this mode.\n */\n readonly merge?: boolean;\n}\n\n/** Thrown when migration would overwrite an already-populated graph without `force`. */\nexport class LessonsGraphExistsError extends Error {\n readonly code = 'LESSONS_GRAPH_EXISTS';\n constructor() {\n super('importLegacyLessons: a non-empty lessons.json already exists; pass force to overwrite.');\n this.name = 'LessonsGraphExistsError';\n }\n}\n\nexport interface ImportLegacyReport {\n readonly wroteGraphPath: string;\n readonly deletedPaths: string[];\n readonly topicCount: number;\n readonly lessonCount: number;\n readonly triggerCount: number;\n}\n\n/**\n * One-shot upgrade migrator: reads the legacy YAML index + per-topic\n * Markdown files, emits the new JSON graph, and (by default) removes every\n * legacy artifact so the project lands in a clean state on the new system.\n *\n * Deterministic over (input, options): the graph output and deletion list are\n * fixed. Requires the legacy `index.yaml` to exist — it is read unconditionally\n * and a missing index throws (ENOENT). Callers MUST guard with\n * `existsSync(lessonsPaths(root).index)` before invoking (see\n * `maybeAutoMigrateLessons` and the `import-md` handler); re-running on a\n * post-migration tree, where the legacy files are already gone, throws.\n */\nexport async function importLegacyLessons(\n projectRoot: string,\n options: ImportLegacyOptions,\n): Promise<ImportLegacyReport> {\n const paths = lessonsPaths(projectRoot);\n const indexRaw = readFileSync(paths.index, 'utf8');\n const index = LegacyIndexSchema.parse(parseYaml(indexRaw));\n\n const topics: Record<string, Topic> = {};\n const triggersById = new Map<string, Trigger>();\n const triggerIdByKey = new Map<string, string>();\n const lessons: Record<string, Lesson> = {};\n // Per-lesson specs for the MERGE path (rule + raw trigger patterns + topic).\n const specs: AddLessonInput[] = [];\n const summaryByTopic = new Map<string, string>();\n\n for (const cluster of index.clusters) {\n topics[cluster.topic] = { summary: cluster.summary };\n summaryByTopic.set(cluster.topic, cluster.summary);\n const clusterTriggerIds = collectClusterTriggerIds(cluster, triggersById, triggerIdByKey);\n\n const topicFile = join(projectRoot, cluster.file);\n if (!existsSync(topicFile)) {\n // Fail closed: a declared topic file that is missing means we would\n // migrate an incomplete graph and then delete the legacy source. Refuse\n // before anything is written or deleted.\n throw new Error(\n `importLegacyLessons: declared topic file is missing: ${cluster.file}. Refusing to migrate (legacy artifacts left intact).`,\n );\n }\n const topicMarkdown = readFileSync(topicFile, 'utf8');\n\n for (const { index: ruleIndex, body, evidence } of parseRulesSection(topicMarkdown)) {\n const lessonEvidence = [\n `legacy:${cluster.file}#rule-${ruleIndex}`,\n ...evidence.map((e) => `legacy:${e}`),\n ];\n lessons[`${cluster.topic}-rule-${ruleIndex}`] = {\n rule: body,\n topics: [cluster.topic],\n triggers: clusterTriggerIds,\n evidence: lessonEvidence,\n status: 'active',\n createdAt: options.migratedAt,\n };\n specs.push({\n rule: body,\n topic: cluster.topic,\n triggers: {\n files: cluster.triggers.file_globs,\n commands: cluster.triggers.command_patterns,\n keywords: cluster.triggers.keywords,\n },\n evidence: lessonEvidence,\n createdAt: options.migratedAt,\n });\n }\n }\n\n if (options.merge === true)\n return mergeLegacy(projectRoot, paths, specs, summaryByTopic, options);\n\n const triggers = Object.fromEntries(triggersById.entries());\n\n // Write through the transactional path: lock → load → replace → VALIDATE →\n // atomic save. mutate throws on any error-level finding (e.g. two identical\n // legacy rules → DUPLICATE_RULE), so an invalid migration never persists and\n // the legacy source below is left intact (fail closed).\n await mutateLessonsGraphLocked(projectRoot, (g) => {\n // Re-check existence UNDER the lock (the absent-graph check in callers is\n // racy on its own): if a concurrent writer populated the graph, refuse to\n // clobber it unless force is set. \"Populated\" means ANY content — a graph\n // with hand-curated topics/triggers but zero lessons must not be silently\n // replaced either.\n const populated =\n Object.keys(g.lessons).length > 0 ||\n Object.keys(g.topics).length > 0 ||\n Object.keys(g.triggers).length > 0;\n if (options.force !== true && populated) {\n throw new LessonsGraphExistsError();\n }\n g.version = 1;\n g.lessons = lessons;\n g.topics = topics;\n g.triggers = triggers;\n });\n\n const deletedPaths = options.deleteLegacy === false ? [] : deleteLegacyArtifacts(paths.base);\n\n return {\n wroteGraphPath: paths.graph,\n deletedPaths,\n topicCount: Object.keys(topics).length,\n lessonCount: Object.keys(lessons).length,\n triggerCount: triggersById.size,\n };\n}\n","import { existsSync } from 'node:fs';\nimport { graphFilePath } from './graph-store.js';\nimport { importLegacyLessons, LessonsGraphExistsError } from './import-legacy.js';\nimport { lessonsPaths } from './paths.js';\n\nfunction todayIso(): string {\n const now = new Date();\n const y = now.getUTCFullYear();\n const m = String(now.getUTCMonth() + 1).padStart(2, '0');\n const d = String(now.getUTCDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n}\n\n/**\n * One-shot legacy→JSON migration on first access. Shared by the CLI dispatcher\n * AND the MCP handlers so that an MCP-only agent (query/add) does not strand a\n * legacy store: if it added first it would create `lessons.json`, which then\n * permanently blocks the absent-graph auto-migration. Returns true if it\n * migrated. No-op when a graph already exists or no legacy index is present.\n */\nexport async function maybeAutoMigrateLessons(projectRoot: string): Promise<boolean> {\n if (existsSync(graphFilePath(projectRoot))) return false;\n const paths = lessonsPaths(projectRoot);\n if (!existsSync(paths.index)) return false;\n try {\n await importLegacyLessons(projectRoot, { migratedAt: todayIso() });\n return true;\n } catch (err) {\n // A concurrent writer created the graph between our check and the lock —\n // migration refused (correctly) rather than clobber it. Not an error here.\n if (err instanceof LessonsGraphExistsError) return false;\n throw err;\n }\n}\n","/**\n * Typed error taxonomy for agentsmesh programmatic consumers.\n *\n * All public-API errors inherit from AgentsMeshError and carry a stable `code`\n * property. Consumers can branch on `err instanceof AgentsMeshError && err.code === 'AM_...'`\n * without relying on error message strings.\n */\n\nexport type AgentsMeshErrorCode =\n | 'AM_CONFIG_NOT_FOUND'\n | 'AM_CONFIG_INVALID'\n | 'AM_TARGET_NOT_FOUND'\n | 'AM_TARGET_UNSUPPORTED'\n | 'AM_IMPORT_FAILED'\n | 'AM_GENERATION_FAILED'\n | 'AM_REMOTE_FETCH_FAILED'\n | 'AM_LOCK_ACQUISITION_FAILED'\n | 'AM_LOCK_CONFLICT'\n | 'AM_FILESYSTEM';\n\nexport class AgentsMeshError extends Error {\n readonly code: AgentsMeshErrorCode;\n\n constructor(code: AgentsMeshErrorCode, message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'AgentsMeshError';\n this.code = code;\n }\n}\n\nexport class ConfigNotFoundError extends AgentsMeshError {\n readonly path: string;\n\n constructor(path: string, options?: { cause?: unknown; message?: string }) {\n super(\n 'AM_CONFIG_NOT_FOUND',\n options?.message ??\n `agentsmesh.yaml not found at ${path}. Run 'agentsmesh init' to create one.`,\n options,\n );\n this.name = 'ConfigNotFoundError';\n this.path = path;\n }\n}\n\nexport class ConfigValidationError extends AgentsMeshError {\n readonly issues: readonly string[];\n\n constructor(path: string, issues: readonly string[], options?: { cause?: unknown }) {\n super(\n 'AM_CONFIG_INVALID',\n `Invalid config at ${path}: ${issues.join('; ')}. Fix the YAML and try again.`,\n options,\n );\n this.name = 'ConfigValidationError';\n this.issues = issues;\n }\n}\n\nexport class TargetNotFoundError extends AgentsMeshError {\n readonly target: string;\n\n constructor(target: string, options?: { cause?: unknown; supported?: readonly string[] }) {\n const suffix = options?.supported ? ` Supported: ${options.supported.join(', ')}.` : '';\n super('AM_TARGET_NOT_FOUND', `Unknown target \"${target}\".${suffix}`, options);\n this.name = 'TargetNotFoundError';\n this.target = target;\n }\n}\n\nexport class ImportError extends AgentsMeshError {\n readonly target: string;\n\n constructor(target: string, message: string, options?: { cause?: unknown }) {\n super('AM_IMPORT_FAILED', `Import from ${target} failed: ${message}`, options);\n this.name = 'ImportError';\n this.target = target;\n }\n}\n\nexport class GenerationError extends AgentsMeshError {\n constructor(message: string, options?: { cause?: unknown }) {\n super('AM_GENERATION_FAILED', message, options);\n this.name = 'GenerationError';\n }\n}\n\nexport class RemoteFetchError extends AgentsMeshError {\n readonly source: string;\n\n constructor(source: string, message: string, options?: { cause?: unknown }) {\n super('AM_REMOTE_FETCH_FAILED', `Remote fetch for \"${source}\" failed: ${message}`, options);\n this.name = 'RemoteFetchError';\n this.source = source;\n }\n}\n\nexport class LockAcquisitionError extends AgentsMeshError {\n readonly lockPath: string;\n readonly holder: string;\n /** Human-readable lock name surfaced in the message, e.g. \"lessons lock\". */\n readonly label: string;\n\n constructor(lockPath: string, holder: string, options?: { cause?: unknown; label?: string }) {\n const label = options?.label ?? 'lock';\n super(\n 'AM_LOCK_ACQUISITION_FAILED',\n `Could not acquire ${label} at ${lockPath}: currently held by ${holder}. ` +\n `Wait for the other process to finish, or remove ${lockPath} manually if you are sure no agentsmesh process is running.`,\n options,\n );\n this.name = 'LockAcquisitionError';\n this.lockPath = lockPath;\n this.holder = holder;\n this.label = label;\n }\n}\n\nexport class FileSystemError extends AgentsMeshError {\n readonly path: string;\n readonly errnoCode?: string;\n\n constructor(path: string, message: string, options?: { cause?: unknown; errnoCode?: string }) {\n super('AM_FILESYSTEM', message, options);\n this.name = 'FileSystemError';\n this.path = path;\n this.errnoCode = options?.errnoCode;\n }\n}\n","/**\n * Cross-platform process lock backed by an atomic mkdir.\n *\n * Acquire semantics: mkdir with no `recursive` option is atomic per POSIX and\n * returns EEXIST if the directory already exists. That makes it a reliable\n * cross-process mutex without any third-party dependency.\n *\n * Stale recovery: the holder writes its PID and start timestamp into the lock\n * dir. On contention we peek at the PID; if the process is gone or the lock is\n * older than `staleMs`, we evict it and retry.\n */\n\nimport { mkdir, readFile, writeFile, rm, stat } from 'node:fs/promises';\nimport { rmSync } from 'node:fs';\nimport { hostname } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { LockAcquisitionError } from '../../core/errors.js';\n\nconst DEFAULT_STALE_MS = 60_000;\nconst DEFAULT_RETRIES = 30;\nconst DEFAULT_RETRY_DELAY_MS = 200;\n// `tryAcquire` does `mkdir(lockPath)` then `writeFile(holder.json)`. Between\n// those two calls, a competing acquirer can see the lock dir without metadata.\n// Treat such a dir as held (not orphaned) for this grace window so the in-flight\n// owner gets a chance to finish writing `holder.json`. Older missing-metadata\n// dirs are still evicted as orphaned.\nconst YOUNG_LOCK_GRACE_MS = 2_000;\n\ninterface LockMetadata {\n pid: number;\n started: number;\n hostname?: string;\n}\n\nexport interface LockOptions {\n /** Maximum retry attempts before throwing LockAcquisitionError. */\n retries?: number;\n /** Delay between retries in ms. */\n retryDelayMs?: number;\n /** Lock age beyond which an existing lock is treated as stale and evicted. */\n staleMs?: number;\n /** Human-readable lock name surfaced in LockAcquisitionError, e.g. \"lessons lock\". */\n label?: string;\n}\n\nexport type LockRelease = () => Promise<void>;\n\n/**\n * Acquire an exclusive process-level lock.\n *\n * @param lockPath - Absolute path where the lock directory will be created.\n * @param opts - Retry/stale tuning knobs.\n * @returns A release function; callers must invoke it in a `finally` block.\n * @throws {LockAcquisitionError} if the lock cannot be acquired within the retry budget.\n */\nexport async function acquireProcessLock(\n lockPath: string,\n opts: LockOptions = {},\n): Promise<LockRelease> {\n const retries = opts.retries ?? DEFAULT_RETRIES;\n const delay = opts.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const stale = opts.staleMs ?? DEFAULT_STALE_MS;\n\n await mkdir(dirname(lockPath), { recursive: true });\n\n let attempt = 0;\n while (true) {\n const acquired = await tryAcquire(lockPath);\n if (acquired) return acquired;\n\n const existing = await inspectLock(lockPath);\n if (existing !== 'young' && isStale(existing, stale)) {\n await rm(lockPath, { recursive: true, force: true }).catch(() => {});\n // Stale eviction is bookkeeping, not a wait — try again without consuming retry budget.\n continue;\n }\n\n if (attempt >= retries) {\n const holder = existing === 'young' ? null : existing;\n throw new LockAcquisitionError(lockPath, describeHolder(holder), { label: opts.label });\n }\n attempt++;\n await sleep(delay);\n }\n}\n\nasync function tryAcquire(lockPath: string): Promise<LockRelease | null> {\n try {\n await mkdir(lockPath, { recursive: false });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') return null;\n throw err;\n }\n\n const metadataPath = join(lockPath, 'holder.json');\n const metadata: LockMetadata = {\n pid: process.pid,\n started: Date.now(),\n hostname: getHostname(),\n };\n await writeFile(metadataPath, JSON.stringify(metadata), 'utf-8');\n\n let released = false;\n const cleanup = (): void => {\n if (released) return;\n released = true;\n try {\n rmSync(lockPath, { recursive: true, force: true });\n } catch {\n // Best-effort cleanup on signal/exit.\n }\n };\n const signalHandler = (signal: NodeJS.Signals): void => {\n cleanup();\n // Re-raise: a registered listener suppresses the default terminate, so\n // without this the FIRST Ctrl-C would not exit and the critical section\n // would keep running after its lock dir was already removed. `once` has\n // deregistered this listener, so the re-raised signal takes the default\n // disposition (or reaches any other handler the host registered).\n process.kill(process.pid, signal);\n };\n process.once('SIGINT', signalHandler);\n process.once('SIGTERM', signalHandler);\n process.once('exit', cleanup);\n\n return async () => {\n if (released) return;\n released = true;\n process.off('SIGINT', signalHandler);\n process.off('SIGTERM', signalHandler);\n process.off('exit', cleanup);\n await rm(lockPath, { recursive: true, force: true }).catch(() => {});\n };\n}\n\nasync function inspectLock(lockPath: string): Promise<LockMetadata | 'young' | null> {\n try {\n const raw = await readFile(join(lockPath, 'holder.json'), 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n if (!isLockMetadata(parsed)) return null;\n return parsed;\n } catch {\n // holder.json is missing or unreadable. The lock dir is either still\n // bootstrapping its metadata (young) or genuinely orphaned (old).\n // Allow negative `ageMs` because under suite-load the directory's mtime\n // can be a hair ahead of `Date.now()` due to FS-vs-clock resolution skew;\n // such a dir is by definition young.\n try {\n const info = await stat(lockPath);\n const ageMs = Date.now() - info.mtimeMs;\n if (ageMs < YOUNG_LOCK_GRACE_MS) return 'young';\n } catch {\n // lockPath gone — treat as null so the next tryAcquire can mkdir.\n }\n return null;\n }\n}\n\nfunction isStale(meta: LockMetadata | null, staleMs: number): boolean {\n if (!meta) return true;\n const age = Date.now() - meta.started;\n if (age > staleMs) return true;\n if (meta.hostname && meta.hostname !== getHostname()) return false;\n return !isProcessAlive(meta.pid);\n}\n\nfunction isProcessAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n // ESRCH = no such process. EPERM = process exists but not ours (still alive).\n return (err as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\nfunction describeHolder(meta: LockMetadata | null): string {\n if (!meta) return 'unknown (unreadable lock metadata)';\n const host = meta.hostname ? `${meta.hostname}:` : '';\n return `${host}pid ${meta.pid} (running ${Date.now() - meta.started}ms)`;\n}\n\nfunction isLockMetadata(value: unknown): value is LockMetadata {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as Record<string, unknown>;\n return typeof v.pid === 'number' && typeof v.started === 'number';\n}\n\nfunction getHostname(): string {\n return hostname();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * Process lock for lessons-graph writes.\n *\n * Multiple harnesses can call `agentsmesh lessons add` concurrently — capture\n * the rule once per failure, even when a hooked CI step and the user's editor\n * race for the same `lessons.json`. The lock lives at\n * `.agentsmesh/lessons/.lessons.lock` and reuses the same `acquireProcessLock`\n * primitive as `.install.lock` / `.generate.lock`, so stale-eviction, signal\n * cleanup, and PID metadata all behave identically.\n */\n\nimport { mkdir } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport {\n acquireProcessLock,\n type LockOptions,\n type LockRelease,\n} from '../utils/filesystem/process-lock.js';\n\nexport const LESSONS_LOCK_FILENAME = '.lessons.lock';\n\nexport function lessonsLockPath(projectRoot: string): string {\n return resolve(projectRoot, '.agentsmesh/lessons', LESSONS_LOCK_FILENAME);\n}\n\nexport async function acquireLessonsLock(\n projectRoot: string,\n opts: LockOptions = {},\n): Promise<LockRelease> {\n const lockPath = lessonsLockPath(projectRoot);\n await mkdir(dirname(lockPath), { recursive: true });\n return acquireProcessLock(lockPath, { ...opts, label: 'lessons lock' });\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport type { ValidationFinding } from './validate.js';\n\nexport function collectDanglingRefs(graph: LessonsGraph, findings: ValidationFinding[]): void {\n for (const [lessonId, lesson] of Object.entries(graph.lessons)) {\n for (const topicId of lesson.topics) {\n if (graph.topics[topicId] === undefined) {\n findings.push({\n level: 'error',\n code: 'DANGLING_TOPIC',\n message: `Lesson \"${lessonId}\" references unknown topic \"${topicId}\".`,\n lessonId,\n topicId,\n });\n }\n }\n for (const triggerId of lesson.triggers) {\n if (graph.triggers[triggerId] === undefined) {\n findings.push({\n level: 'error',\n code: 'DANGLING_TRIGGER',\n message: `Lesson \"${lessonId}\" references unknown trigger \"${triggerId}\".`,\n lessonId,\n triggerId,\n });\n }\n }\n if (lesson.supersededBy !== undefined && graph.lessons[lesson.supersededBy] === undefined) {\n findings.push({\n level: 'error',\n code: 'DANGLING_SUPERSEDER',\n message: `Lesson \"${lessonId}\" supersededBy unknown lesson \"${lesson.supersededBy}\".`,\n lessonId,\n });\n }\n }\n}\n\n/**\n * A lesson must reference each topic and trigger at most once. A repeated\n * reference (only reachable via a raw mutation / hand-edit — `add` unions and so\n * dedups) double-counts in fanout accounting and skews ranking specificity, so\n * flag it as an error.\n */\nexport function collectDuplicateRefs(graph: LessonsGraph, findings: ValidationFinding[]): void {\n for (const [lessonId, lesson] of Object.entries(graph.lessons)) {\n for (const topicId of firstDuplicates(lesson.topics)) {\n findings.push({\n level: 'error',\n code: 'DUPLICATE_TOPIC_REF',\n message: `Lesson \"${lessonId}\" references topic \"${topicId}\" more than once.`,\n lessonId,\n topicId,\n });\n }\n for (const triggerId of firstDuplicates(lesson.triggers)) {\n findings.push({\n level: 'error',\n code: 'DUPLICATE_TRIGGER_REF',\n message: `Lesson \"${lessonId}\" references trigger \"${triggerId}\" more than once.`,\n lessonId,\n triggerId,\n });\n }\n }\n}\n\n/** The distinct values that appear two or more times in `ids`, in first-seen order. */\nfunction firstDuplicates(ids: readonly string[]): string[] {\n const seen = new Set<string>();\n const dup = new Set<string>();\n for (const id of ids) {\n if (seen.has(id)) dup.add(id);\n else seen.add(id);\n }\n return [...dup];\n}\n\nexport function collectStatusInvariants(graph: LessonsGraph, findings: ValidationFinding[]): void {\n for (const [lessonId, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status === 'superseded' && lesson.supersededBy === undefined) {\n findings.push({\n level: 'error',\n code: 'SUPERSEDED_WITHOUT_TARGET',\n message: `Lesson \"${lessonId}\" has status \"superseded\" but no supersededBy target.`,\n lessonId,\n });\n }\n if (lesson.status === 'active' && lesson.supersededBy !== undefined) {\n findings.push({\n level: 'error',\n code: 'ACTIVE_WITH_SUPERSEDER',\n message: `Lesson \"${lessonId}\" has status \"active\" but declares supersededBy.`,\n lessonId,\n });\n }\n }\n}\n\n/**\n * Self-supersession, supersession cycles, and inactive superseders. A\n * superseded lesson must point at a *different*, ultimately-active replacement;\n * otherwise recall silently drops knowledge with no live successor.\n */\nexport function collectLifecycleInvariants(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n): void {\n for (const [lessonId, lesson] of Object.entries(graph.lessons)) {\n if (lesson.supersededBy === undefined) continue;\n if (lesson.supersededBy === lessonId) {\n findings.push({\n level: 'error',\n code: 'SELF_SUPERSEDED',\n message: `Lesson \"${lessonId}\" is superseded by itself.`,\n lessonId,\n });\n continue;\n }\n const target = graph.lessons[lesson.supersededBy];\n if (target !== undefined && target.status !== 'active') {\n findings.push({\n level: 'error',\n code: 'INACTIVE_SUPERSEDER',\n message: `Lesson \"${lessonId}\" is superseded by \"${lesson.supersededBy}\", which is itself ${target.status} — the chain dead-ends with no live replacement.`,\n lessonId,\n });\n }\n }\n collectSupersedeCycles(graph, findings);\n}\n\nfunction collectSupersedeCycles(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const reported = new Set<string>();\n for (const startId of Object.keys(graph.lessons)) {\n const seen = new Set<string>();\n let cur: string | undefined = startId;\n while (cur !== undefined) {\n if (seen.has(cur)) {\n if (cur !== startId || reported.has(cur)) break;\n reported.add(cur);\n findings.push({\n level: 'error',\n code: 'SUPERSEDE_CYCLE',\n message: `Lesson \"${startId}\" is part of a supersededBy cycle.`,\n lessonId: startId,\n });\n break;\n }\n seen.add(cur);\n const next: string | undefined = graph.lessons[cur]?.supersededBy;\n if (next === cur) break; // self-supersession reported separately\n cur = next;\n }\n }\n}\n\nexport function collectReachability(graph: LessonsGraph, findings: ValidationFinding[]): void {\n for (const [lessonId, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status === 'active' && lesson.triggers.length === 0) {\n findings.push({\n level: 'warning',\n code: 'UNREACHABLE_LESSON',\n message: `Active lesson \"${lessonId}\" has no triggers and can never be recalled.`,\n lessonId,\n });\n }\n }\n}\n\nexport function collectOrphans(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const referencedTopics = new Set<string>();\n const referencedTriggers = new Set<string>();\n for (const lesson of Object.values(graph.lessons)) {\n for (const t of lesson.topics) referencedTopics.add(t);\n for (const t of lesson.triggers) referencedTriggers.add(t);\n }\n for (const topicId of Object.keys(graph.topics)) {\n if (!referencedTopics.has(topicId)) {\n findings.push({\n level: 'warning',\n code: 'ORPHAN_TOPIC',\n message: `Topic \"${topicId}\" is not referenced by any lesson.`,\n topicId,\n });\n }\n }\n for (const triggerId of Object.keys(graph.triggers)) {\n if (!referencedTriggers.has(triggerId)) {\n findings.push({\n level: 'warning',\n code: 'ORPHAN_TRIGGER',\n message: `Trigger \"${triggerId}\" is not referenced by any lesson.`,\n triggerId,\n });\n }\n }\n}\n","/** Thompson NFA construction: compile an {@link AstNode} tree to an ε-NFA. */\n\nimport type { AstNode } from './ast.js';\n\nexport type AssertKind = 'start' | 'end' | 'wordB' | 'nonWordB';\n\nexport interface State {\n eps: number[];\n asserts: { kind: AssertKind; target: number }[];\n chars: { test: (c: string) => boolean; target: number }[];\n}\n\nexport interface CompiledNfa {\n readonly states: State[];\n readonly start: number;\n readonly accept: number;\n}\n\n/**\n * Cap on compiled NFA states. A short pattern can still expand to a huge NFA via\n * counted repetition (`a{1000}` ≈ 2000 states, `a{1000}` ×10 ≈ 20000). This\n * bounds COMPILE memory; `alloc` throws once exceeded and the pattern is rejected\n * (UNSAFE). Match TIME is bounded separately by the work budget. Real command\n * patterns are tiny (< 200 states).\n */\nconst MAX_NFA_STATES = 2000;\n\nclass Builder {\n readonly states: State[] = [];\n alloc(): number {\n if (this.states.length >= MAX_NFA_STATES) {\n throw new Error(`NFA state limit exceeded (${MAX_NFA_STATES}); pattern expands too large`);\n }\n this.states.push({ eps: [], asserts: [], chars: [] });\n return this.states.length - 1;\n }\n}\n\n/** `.` matches any char EXCEPT a line terminator (JS without the `s`/dotAll flag). */\nfunction isNonLineTerminator(c: string): boolean {\n return c !== '\\n' && c !== '\\r' && c !== '\\u2028' && c !== '\\u2029';\n}\n\n/** Compile an AST fragment, returning its [start, end] state indices (end has no outgoing). */\nfunction compileNode(b: Builder, node: AstNode): { start: number; end: number } {\n switch (node.k) {\n case 'empty':\n case 'assert': {\n const s = b.alloc();\n const e = b.alloc();\n if (node.k === 'assert') b.states[s]!.asserts.push({ kind: node.kind, target: e });\n else b.states[s]!.eps.push(e);\n return { start: s, end: e };\n }\n case 'char':\n case 'any':\n case 'class': {\n const s = b.alloc();\n const e = b.alloc();\n const test =\n node.k === 'char'\n ? (c: string): boolean => c === node.ch\n : node.k === 'any'\n ? isNonLineTerminator\n : node.test;\n b.states[s]!.chars.push({ test, target: e });\n return { start: s, end: e };\n }\n case 'concat': {\n if (node.items.length === 0) return compileNode(b, { k: 'empty' });\n let first: { start: number; end: number } | null = null;\n let prevEnd = -1;\n for (const item of node.items) {\n const frag = compileNode(b, item);\n if (first === null) first = frag;\n else b.states[prevEnd]!.eps.push(frag.start);\n prevEnd = frag.end;\n }\n return { start: first!.start, end: prevEnd };\n }\n case 'alt': {\n const s = b.alloc();\n const e = b.alloc();\n for (const opt of node.opts) {\n const frag = compileNode(b, opt);\n b.states[s]!.eps.push(frag.start);\n b.states[frag.end]!.eps.push(e);\n }\n return { start: s, end: e };\n }\n case 'opt': {\n const s = b.alloc();\n const e = b.alloc();\n const frag = compileNode(b, node.node);\n b.states[s]!.eps.push(frag.start, e);\n b.states[frag.end]!.eps.push(e);\n return { start: s, end: e };\n }\n case 'star': {\n const s = b.alloc();\n const e = b.alloc();\n const frag = compileNode(b, node.node);\n b.states[s]!.eps.push(frag.start, e);\n b.states[frag.end]!.eps.push(frag.start, e);\n return { start: s, end: e };\n }\n case 'plus': {\n const e = b.alloc();\n const frag = compileNode(b, node.node);\n b.states[frag.end]!.eps.push(frag.start, e);\n return { start: frag.start, end: e };\n }\n }\n}\n\nexport function compileNfa(ast: AstNode): CompiledNfa {\n const b = new Builder();\n const { start, end } = compileNode(b, ast);\n return { states: b.states, start, accept: end };\n}\n","/**\n * Linear-time simulation of the compiled command_pattern NFA.\n *\n * Simulates the ε-NFA WITHOUT backtracking: the active state set is advanced one\n * input character at a time, so matching is O(input × states) regardless of the\n * pattern — no catastrophic backtracking is possible (a JS `RegExp` cannot give\n * this guarantee). Search is unanchored (like `RegExp.test`): a fresh start\n * thread is seeded at every position; `^`/`$`/`\\b` are position-gated assertions.\n */\n\nimport type { AstNode } from './ast.js';\nimport { type AssertKind, compileNfa } from './nfa-compile.js';\n\n/**\n * A shared, mutable work budget. `remaining` is decremented per unit of NFA work\n * (state visited / transition followed); when it reaches zero the matcher gives\n * up and reports a non-match. Pass ONE budget across all triggers in a single\n * recall so total work is bounded query-wide, not just per pattern.\n */\nexport interface WorkBudget {\n remaining: number;\n}\n\nexport interface LinearMatcher {\n /**\n * True if the pattern matches anywhere in `input` (unanchored, like\n * RegExp.test). Decrements `budget` as it works; if the budget is exhausted it\n * returns false (a safe non-match — never a false positive, no invented input\n * endpoint). Without a budget it runs to completion.\n */\n test(input: string, budget?: WorkBudget): boolean;\n}\n\nfunction wordBoundary(input: string, pos: number): boolean {\n const before = pos > 0 && /[A-Za-z0-9_]/.test(input[pos - 1]!);\n const after = pos < input.length && /[A-Za-z0-9_]/.test(input[pos]!);\n return before !== after;\n}\n\nfunction assertHolds(kind: AssertKind, input: string, pos: number): boolean {\n switch (kind) {\n case 'start':\n return pos === 0;\n case 'end':\n return pos === input.length;\n case 'wordB':\n return wordBoundary(input, pos);\n case 'nonWordB':\n return !wordBoundary(input, pos);\n }\n}\n\n/** Build a {@link LinearMatcher} from an AST (compiles it, then simulates). */\nexport function buildMatcher(ast: AstNode): LinearMatcher {\n const { states, start, accept } = compileNfa(ast);\n\n // ε/assertion closure at boundary `pos`, accumulating reachable states into\n // `set`. ITERATIVE (explicit stack) — a recursive walk overflows the call\n // stack on long ε-chains (e.g. `(){1000}` expands to thousands of ε-links).\n // Decrements the work budget per state visited; stops early when exhausted.\n const closure = (\n set: Set<number>,\n idx: number,\n input: string,\n pos: number,\n budget: WorkBudget,\n ): void => {\n const stack = [idx];\n while (stack.length > 0) {\n if (budget.remaining <= 0) return;\n const cur = stack.pop()!;\n if (set.has(cur)) continue;\n set.add(cur);\n budget.remaining -= 1;\n for (const t of states[cur]!.eps) if (!set.has(t)) stack.push(t);\n for (const a of states[cur]!.asserts) {\n if (assertHolds(a.kind, input, pos) && !set.has(a.target)) stack.push(a.target);\n }\n }\n };\n\n return {\n // The input is matched in full (no truncation — truncation would miss suffix\n // matches and let `$` falsely match an invented endpoint). Work is bounded by\n // the shared budget instead: when it runs out we report a safe non-match.\n test(input: string, budget?: WorkBudget): boolean {\n const b: WorkBudget = budget ?? { remaining: Number.POSITIVE_INFINITY };\n if (b.remaining <= 0) return false;\n let current = new Set<number>();\n for (let pos = 0; pos <= input.length; pos += 1) {\n closure(current, start, input, pos, b); // unanchored: seed a start thread here\n if (current.has(accept)) return true;\n if (b.remaining <= 0) return false; // budget exhausted → safe non-match\n if (pos === input.length) break;\n const ch = input[pos]!;\n const next = new Set<number>();\n for (const s of current) {\n b.remaining -= 1;\n for (const t of states[s]!.chars) {\n if (t.test(ch)) closure(next, t.target, input, pos + 1, b);\n }\n }\n current = next;\n }\n return current.has(accept);\n },\n };\n}\n","/** AST + error type for the linear command_pattern engine (see parse.ts). */\n\nexport type AstNode =\n | { k: 'empty' }\n | { k: 'char'; ch: string }\n | { k: 'any' }\n | { k: 'class'; test: (c: string) => boolean }\n | { k: 'assert'; kind: 'start' | 'end' | 'wordB' | 'nonWordB' }\n | { k: 'concat'; items: AstNode[] }\n | { k: 'alt'; opts: AstNode[] }\n | { k: 'star'; node: AstNode }\n | { k: 'plus'; node: AstNode }\n | { k: 'opt'; node: AstNode };\n\n/** Thrown by the parser for syntax the linear engine cannot evaluate. */\nexport class UnsupportedRegexError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UnsupportedRegexError';\n }\n}\n","/** Helpers for {@link parseRegex}: bounded-repeat expansion and escape handling. */\n\nimport { type AstNode, UnsupportedRegexError } from './ast.js';\n\nexport const MAX_REPEAT = 1000;\n\nexport const isWord = (c: string): boolean => /[A-Za-z0-9_]/.test(c);\n\n/** Expand `{min,max}` into required copies + optional/star copies (linear-engine has no counted repeat). */\nexport function expandRepeat(atom: AstNode, min: number, max: number): AstNode {\n const items: AstNode[] = [];\n for (let k = 0; k < min; k += 1) items.push(atom);\n if (max === Infinity) {\n items.push({ k: 'star', node: atom });\n } else {\n for (let k = min; k < max; k += 1) items.push({ k: 'opt', node: atom });\n }\n if (items.length === 0) return { k: 'empty' };\n return items.length === 1 ? items[0]! : { k: 'concat', items };\n}\n\n/** Predicate for a class escape (`\\d \\w \\s` …); null when the escape is a literal. */\nexport function escapeClass(c: string): ((c: string) => boolean) | null {\n switch (c) {\n case 'd':\n return (x) => x >= '0' && x <= '9';\n case 'D':\n return (x) => !(x >= '0' && x <= '9');\n case 'w':\n return isWord;\n case 'W':\n return (x) => !isWord(x);\n case 's':\n return (x) => /\\s/.test(x);\n case 'S':\n return (x) => !/\\s/.test(x);\n default:\n return null;\n }\n}\n\nconst HEX2 = /^[0-9a-fA-F]{2}$/;\nconst HEX4 = /^[0-9a-fA-F]{4}$/;\n\n/**\n * Read a `\\xHH` / `\\uHHHH` escape. `i` points AFTER the escape letter `c`\n * (`x` or `u`); returns the decoded char and how many EXTRA chars to consume.\n * Falls back to the literal letter (len 0) when the hex form is malformed — this\n * matches `new RegExp` WITHOUT the `u` flag (how lessons compile patterns), where\n * `\\x`/`\\u` not followed by valid hex is the literal `x`/`u`. `\\u{…}` is left\n * undecoded for the same reason (it only means a code point under the `u` flag).\n */\nexport function readUnicodeEscape(src: string, i: number, c: string): { ch: string; len: number } {\n if (c === 'x') {\n const hex = src.slice(i, i + 2);\n return HEX2.test(hex)\n ? { ch: String.fromCharCode(parseInt(hex, 16)), len: 2 }\n : { ch: 'x', len: 0 };\n }\n const hex = src.slice(i, i + 4);\n return HEX4.test(hex)\n ? { ch: String.fromCharCode(parseInt(hex, 16)), len: 4 }\n : { ch: 'u', len: 0 };\n}\n\n/**\n * Read a `\\cX` control escape (`\\cA` → U+0001 … `\\cZ` → U+001A). `i` points AFTER\n * the `c`. `\\c` NOT followed by a letter is rejected (fail closed) rather than\n * silently diverging — `new RegExp` without the `u` flag treats `\\c1` as the\n * literal `\\c1`, which the linear engine does not reproduce.\n */\nexport function readControlEscape(src: string, i: number): { ch: string; len: number } {\n const x = src[i];\n if (x === undefined || !/[A-Za-z]/.test(x)) {\n throw new UnsupportedRegexError('\\\\c must be followed by a letter');\n }\n return { ch: String.fromCharCode(x.charCodeAt(0) & 0x1f), len: 1 };\n}\n\n/**\n * The character an escape stands for INSIDE a character class. Unlike outside a\n * class, `\\b` is a backspace (U+0008), not a word boundary. `i` points after `e`.\n */\nexport function classEscapeChar(src: string, i: number, e: string): { ch: string; len: number } {\n if (e === 'b') return { ch: '\\b', len: 0 };\n if (e === 'c') return readControlEscape(src, i);\n if (e === 'x' || e === 'u') return readUnicodeEscape(src, i, e);\n return { ch: escapeLiteral(e), len: 0 };\n}\n\n/** The literal character an escape stands for (`\\t`, `\\n`, …, or the char itself). */\nexport function escapeLiteral(c: string): string {\n switch (c) {\n case 't':\n return '\\t';\n case 'n':\n return '\\n';\n case 'r':\n return '\\r';\n case 'f':\n return '\\f';\n case 'v':\n return '\\v';\n case '0':\n return '\\0';\n default:\n return c; // \\. \\/ \\( … → the literal character\n }\n}\n","/**\n * Parser for the linear command_pattern matcher: regex source → AST. Supports\n * literals, escapes (`\\d \\w \\s`, `\\xHH`, `\\uHHHH`, `\\cX`, control chars), `.`,\n * char classes, anchors (`^ $ \\b \\B`), groups, `|`, and quantifiers (`* + ?`,\n * `{n,m}`, lazy). Throws {@link UnsupportedRegexError} for backreferences and\n * lookarounds (a non-backtracking engine cannot evaluate them); bounded `{n,m}`\n * is expanded at parse time with an upper bound to keep the NFA small.\n */\n\nimport { type AstNode, UnsupportedRegexError } from './ast.js';\nimport {\n classEscapeChar,\n escapeClass,\n escapeLiteral,\n expandRepeat,\n MAX_REPEAT,\n readControlEscape,\n readUnicodeEscape,\n} from './parse-helpers.js';\n\nexport function parseRegex(src: string): AstNode {\n let i = 0;\n\n const peek = (): string | undefined => src[i];\n const eat = (): string => src[i++]!;\n\n function parseAlt(): AstNode {\n const opts = [parseConcat()];\n while (peek() === '|') {\n i += 1;\n opts.push(parseConcat());\n }\n return opts.length === 1 ? opts[0]! : { k: 'alt', opts };\n }\n\n function parseConcat(): AstNode {\n const items: AstNode[] = [];\n while (i < src.length && peek() !== '|' && peek() !== ')') {\n items.push(parseQuantified());\n }\n if (items.length === 0) return { k: 'empty' };\n return items.length === 1 ? items[0]! : { k: 'concat', items };\n }\n\n function parseQuantified(): AstNode {\n const atom = parseAtom();\n const q = peek();\n if (q === '*' || q === '+' || q === '?') {\n i += 1;\n if (peek() === '?') i += 1; // lazy — same match-existence for boolean search\n return q === '*'\n ? { k: 'star', node: atom }\n : q === '+'\n ? { k: 'plus', node: atom }\n : { k: 'opt', node: atom };\n }\n if (q === '{') {\n const repeat = tryParseBrace();\n if (repeat !== null) return expandRepeat(atom, repeat.min, repeat.max);\n }\n return atom;\n }\n\n function tryParseBrace(): { min: number; max: number } | null {\n const m = /^\\{(\\d+)(,(\\d*)?)?\\}/.exec(src.slice(i));\n if (m === null) return null; // literal '{'\n i += m[0].length;\n if (peek() === '?') i += 1; // lazy\n const min = Number(m[1]);\n const max =\n m[2] === undefined ? min : m[3] === '' || m[3] === undefined ? Infinity : Number(m[3]);\n if (min > MAX_REPEAT || (max !== Infinity && max > MAX_REPEAT)) {\n throw new UnsupportedRegexError(`Repeat count over ${MAX_REPEAT} not supported: {${m[1]}…}`);\n }\n return { min, max };\n }\n\n function parseAtom(): AstNode {\n const c = peek();\n if (c === '(') return parseGroup();\n if (c === '[') return parseClass();\n if (c === '\\\\') return parseEscape();\n if (c === '.') {\n i += 1;\n return { k: 'any' };\n }\n if (c === '^') {\n i += 1;\n return { k: 'assert', kind: 'start' };\n }\n if (c === '$') {\n i += 1;\n return { k: 'assert', kind: 'end' };\n }\n if (c === undefined || c === '*' || c === '+' || c === '?' || c === ')') {\n throw new UnsupportedRegexError(`Unexpected '${c ?? '<end>'}' in pattern`);\n }\n i += 1;\n return { k: 'char', ch: c };\n }\n\n function parseGroup(): AstNode {\n i += 1; // consume '('\n if (peek() === '?') {\n const c2 = src[i + 1];\n if (c2 === '=' || c2 === '!' || c2 === '<') {\n if (!(c2 === '<' && /[A-Za-z]/.test(src[i + 2] ?? ''))) {\n throw new UnsupportedRegexError('Lookaround assertions are not supported');\n }\n }\n // (?: …) or (?<name> …): skip the prefix, treat as a plain group\n if (c2 === ':') i += 2;\n else if (c2 === '<') {\n i += 2;\n while (i < src.length && src[i] !== '>') i += 1;\n i += 1;\n }\n }\n const inner = parseAlt();\n if (peek() !== ')') throw new UnsupportedRegexError('Unbalanced group');\n i += 1; // consume ')'\n return inner;\n }\n\n function parseEscape(): AstNode {\n i += 1; // consume '\\'\n const c = peek();\n if (c === undefined) throw new UnsupportedRegexError('Trailing backslash');\n if (/[1-9]/.test(c) || c === 'k')\n throw new UnsupportedRegexError('Backreferences are not supported');\n i += 1;\n if (c === 'b') return { k: 'assert', kind: 'wordB' };\n if (c === 'B') return { k: 'assert', kind: 'nonWordB' };\n const cls = escapeClass(c);\n if (cls !== null) return { k: 'class', test: cls };\n if (c === 'x' || c === 'u' || c === 'c') {\n const { ch, len } = c === 'c' ? readControlEscape(src, i) : readUnicodeEscape(src, i, c);\n i += len;\n return { k: 'char', ch };\n }\n return { k: 'char', ch: escapeLiteral(c) };\n }\n\n function parseClass(): AstNode {\n i += 1; // consume '['\n const negate = peek() === '^';\n if (negate) i += 1;\n // JS semantics: `[]` is an empty class (matches nothing) and `[^]` matches\n // anything — a leading `]` is NOT a literal member (that is POSIX). Use `[\\]]`.\n const tests: Array<(c: string) => boolean> = [];\n while (i < src.length && peek() !== ']') {\n tests.push(parseClassMember());\n }\n if (peek() !== ']') throw new UnsupportedRegexError('Unterminated character class');\n i += 1; // consume ']'\n const base = (c: string): boolean => tests.some((t) => t(c));\n return { k: 'class', test: negate ? (c) => !base(c) : base };\n }\n\n function parseClassMember(): (c: string) => boolean {\n let lo: string;\n if (peek() === '\\\\') {\n i += 1;\n const e = eat();\n const cls = escapeClass(e);\n if (cls !== null) return cls;\n const r = classEscapeChar(src, i, e);\n i += r.len;\n lo = r.ch;\n } else {\n lo = eat();\n }\n if (peek() === '-' && src[i + 1] !== undefined && src[i + 1] !== ']') {\n i += 1; // consume '-'\n let hi: string;\n if (peek() === '\\\\') {\n i += 1;\n const e2 = eat();\n const r = classEscapeChar(src, i, e2);\n i += r.len;\n hi = r.ch;\n } else {\n hi = eat();\n }\n const a = lo.codePointAt(0)!;\n const b = hi.codePointAt(0)!;\n return (c) => {\n const p = c.codePointAt(0)!;\n return p >= a && p <= b;\n };\n }\n return (c) => c === lo;\n }\n\n const ast = parseAlt();\n if (i !== src.length) throw new UnsupportedRegexError(`Unexpected '${peek()}' at ${i}`);\n return ast;\n}\n","/**\n * Linear-time matcher for `command_pattern` triggers — an in-repo, dependency-free\n * non-backtracking regex engine (Thompson NFA). Recall executes author-supplied\n * patterns against the command string on a mandatory hot path; a backtracking\n * `RegExp` can be driven super-linear (`(a+)+`, `a+a+`, even `a+b` is quadratic\n * on a long non-matching input), so command patterns run here instead, where\n * matching is provably linear in the input length for any compilable pattern.\n *\n * `compileLinearMatcher` returns null for patterns the linear engine cannot\n * evaluate — invalid syntax, backreferences, or lookarounds — so callers fail\n * closed: validation rejects them (UNSAFE_TRIGGER_PATTERN) and recall skips them.\n */\n\nimport { buildMatcher, type LinearMatcher } from './nfa.js';\nimport { parseRegex } from './parse.js';\n\nexport type { LinearMatcher, WorkBudget } from './nfa.js';\n\nconst cache = new Map<string, LinearMatcher | null>();\n\nexport function compileLinearMatcher(pattern: string): LinearMatcher | null {\n const hit = cache.get(pattern);\n if (hit !== undefined || cache.has(pattern)) return hit ?? null;\n let matcher: LinearMatcher | null;\n try {\n matcher = buildMatcher(parseRegex(pattern));\n } catch {\n matcher = null; // unsupported construct or invalid syntax → fail closed\n }\n cache.set(pattern, matcher);\n return matcher;\n}\n","/**\n * Safety gate for `command_pattern` triggers.\n *\n * Recall is mandatory (it runs before every edit/command) and matches\n * author-supplied patterns against the command string. A backtracking `RegExp`\n * can be driven super-linear by a crafted pattern — `(a+)+`, `(a|aa)+`, `a+a+`,\n * or even `a+b` (quadratic on a long non-matching input) — so one lesson could\n * hang recall. Local inspection of quantifier shape CANNOT prove a backtracking\n * regex linear, so we do not try: command patterns are matched by an in-repo\n * non-backtracking engine ({@link compileLinearMatcher}), which is provably\n * linear in the input length for any pattern it can compile.\n *\n * A pattern is \"safe\" iff the linear engine can compile it. Patterns it cannot\n * evaluate (invalid syntax, backreferences, lookarounds) are rejected at capture\n * (UNSAFE_TRIGGER_PATTERN) and skipped at read time — fail closed.\n */\n\nimport { compileLinearMatcher, type LinearMatcher } from './regex-linear/index.js';\n\n/** Patterns longer than this are treated as unsafe outright (defensive bound). */\nconst MAX_PATTERN_LENGTH = 1000;\n\n/** True when `pattern` can be matched by the linear engine (no ReDoS risk). */\nexport function isSafeRegexPattern(pattern: string): boolean {\n if (pattern.length > MAX_PATTERN_LENGTH) return false;\n return compileLinearMatcher(pattern) !== null;\n}\n\n/**\n * Return a linear-time matcher for a `command_pattern` used in recall, or null\n * when the pattern is over-long or outside the engine's support (recall treats\n * null as a non-match, never executing a backtracking regex). Memoized inside\n * {@link compileLinearMatcher}.\n */\nexport function getCommandMatcher(pattern: string): LinearMatcher | null {\n if (pattern.length > MAX_PATTERN_LENGTH) return null;\n return compileLinearMatcher(pattern);\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport {\n isLowSignalKeyword,\n keywordNeedleLosesTokens,\n MAX_RECOMMENDED_KEYWORD_TOKENS,\n} from './keyword-signal.js';\nimport { tokenize } from './ranking-text.js';\nimport { isSafeRegexPattern } from './regex-safety.js';\nimport type { ValidationFinding } from './validate.js';\n\nexport function collectDuplicateRules(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const byKey = new Map<string, string[]>();\n for (const [lessonId, lesson] of Object.entries(graph.lessons)) {\n // Only active lessons compete: a superseded/deprecated copy is not recalled,\n // so it is not a functional duplicate — this is what lets `merge` repair a\n // duplicate by superseding the loser.\n if (lesson.status !== 'active') continue;\n const key = normalizeRule(lesson.rule);\n const bucket = byKey.get(key) ?? [];\n bucket.push(lessonId);\n byKey.set(key, bucket);\n }\n for (const [key, ids] of byKey) {\n if (ids.length < 2) continue;\n const sorted = [...ids].sort();\n for (const lessonId of sorted) {\n const others = sorted.filter((other) => other !== lessonId);\n findings.push({\n level: 'error',\n code: 'DUPLICATE_RULE',\n message: `Lesson \"${lessonId}\" duplicates rule text of: ${others.join(', ')} (normalized key: \"${key.slice(0, 60)}\").`,\n lessonId,\n });\n }\n }\n}\n\n/**\n * A `command_pattern` trigger whose pattern is not a valid regex is dead: recall\n * compiles it with `new RegExp` and a throw is swallowed as a non-match, so the\n * lesson silently becomes unreachable via that trigger. A *valid* pattern that\n * is ReDoS-unsafe (catastrophic backtracking, e.g. `(a+)+`) is worse: recall\n * would execute it on every command and could hang. Flag both as errors so the\n * transactional write path rejects them at capture time (recall additionally\n * skips them at runtime — see regex-safety.ts).\n */\nexport function collectInvalidTriggerPatterns(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n): void {\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'command_pattern') continue;\n try {\n new RegExp(trigger.pattern);\n } catch (err) {\n findings.push({\n level: 'error',\n code: 'INVALID_TRIGGER_PATTERN',\n message: `Trigger \"${triggerId}\" has an invalid command_pattern regex (${trigger.pattern}): ${err instanceof Error ? err.message : String(err)}.`,\n triggerId,\n });\n continue;\n }\n if (!isSafeRegexPattern(trigger.pattern)) {\n findings.push({\n level: 'error',\n code: 'UNSAFE_TRIGGER_PATTERN',\n message: `Trigger \"${triggerId}\" has a command_pattern regex outside the provably-linear subset (${trigger.pattern}): it can backtrack catastrophically (e.g. a quantified group like (a+)+ or (a|aa)+, adjacent repetition like a+a+, or a backreference/lookaround). Rewrite using a linear pattern.`,\n triggerId,\n });\n }\n }\n}\n\n/**\n * A `file_glob` trigger whose pattern contains a backslash is dead: recall\n * relativizes every `--file` input to forward slashes (normalizeRecallFile),\n * so picomatch never matches a backslash pattern and the lesson silently\n * becomes unreachable via that trigger. `add` normalizes new patterns; this is\n * the `validate` counterpart that surfaces any backslash pattern stored before\n * the normalization existed (or inserted by a hand-edit).\n */\nexport function collectBackslashGlobPatterns(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n): void {\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'file_glob') continue;\n if (!trigger.pattern.includes('\\\\')) continue;\n findings.push({\n level: 'error',\n code: 'BACKSLASH_GLOB_PATTERN',\n message: `Trigger \"${triggerId}\" has a file_glob pattern with a backslash (${trigger.pattern}); recall normalizes paths to forward slashes, so it never fires. Replace \\\\ with /.`,\n triggerId,\n });\n }\n}\n\n/**\n * Trigger ids are content-addressed from (kind, pattern), so `add` can never\n * create two nodes for the same pattern. Validation enforces the invariant\n * structurally — a public/low-level mutation (or hand-edit) that inserts a\n * second id for an existing (kind, pattern) would bypass deduplication and\n * distort fanout accounting and ranking specificity. Flag every member of a\n * duplicate group as an error.\n */\nexport function collectDuplicateTriggers(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const byKey = new Map<string, string[]>();\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n const key = `${trigger.kind}|${trigger.pattern}`;\n const bucket = byKey.get(key) ?? [];\n bucket.push(triggerId);\n byKey.set(key, bucket);\n }\n for (const [key, ids] of byKey) {\n if (ids.length < 2) continue;\n const sorted = [...ids].sort();\n for (const triggerId of sorted) {\n const others = sorted.filter((other) => other !== triggerId);\n findings.push({\n level: 'error',\n code: 'DUPLICATE_TRIGGER',\n message: `Trigger \"${triggerId}\" duplicates (kind, pattern) of: ${others.join(', ')} (key: \"${key}\").`,\n triggerId,\n });\n }\n }\n}\n\n/** Active-fanout threshold above which a trigger is \"broad\" (recall leans on ranking). */\nconst HIGH_FANOUT_THRESHOLD = 10;\n\n/**\n * One summary warning (not one-per-trigger — that would be noise on a broad\n * graph) reporting how many triggers fan out past the threshold. Surfaces the\n * trigger imprecision that ranking compensates for, rather than hiding it.\n */\nexport function collectFanout(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const fanout = new Map<string, number>();\n for (const lesson of Object.values(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n for (const t of lesson.triggers) fanout.set(t, (fanout.get(t) ?? 0) + 1);\n }\n let over = 0;\n let max = 0;\n for (const n of fanout.values()) {\n if (n > HIGH_FANOUT_THRESHOLD) over += 1;\n if (n > max) max = n;\n }\n if (over > 0) {\n findings.push({\n level: 'warning',\n code: 'HIGH_FANOUT_TRIGGERS',\n message: `${over} trigger(s) each match more than ${HIGH_FANOUT_THRESHOLD} active lessons (max ${max}); recall returns the ranked top by default — consider per-lesson trigger refinement to improve precision.`,\n });\n }\n}\n\n/**\n * Flag keyword triggers whose pattern is too long to realistically match recall\n * (see keyword-signal.ts). Only triggers referenced by an ACTIVE lesson are\n * reported: a long keyword on a superseded/deprecated lesson never recalls\n * anyway, and an unreferenced one is already an ORPHAN_TRIGGER. This is the\n * `validate` counterpart to the capture-time LOW_SIGNAL_KEYWORD guardrail, so a\n * graph built before the guardrail existed still surfaces its dead keywords.\n */\nexport function collectLowSignalKeywords(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const activeTriggerIds = new Set<string>();\n for (const lesson of Object.values(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n for (const t of lesson.triggers) activeTriggerIds.add(t);\n }\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'keyword') continue;\n if (!activeTriggerIds.has(triggerId)) continue;\n if (!isLowSignalKeyword(trigger.pattern)) continue;\n findings.push({\n level: 'warning',\n code: 'LOW_SIGNAL_KEYWORD',\n message: `Keyword trigger \"${triggerId}\" carries more than ${MAX_RECOMMENDED_KEYWORD_TOKENS} tokens (${trigger.pattern}); recall matches a keyword only as a substring of --keyword or a contiguous token-run in the file/command, so it rarely fires — use a short distinctive phrase.`,\n triggerId,\n });\n }\n}\n\n/**\n * Flag keyword triggers (referenced by an ACTIVE lesson) whose needle cannot fire\n * on the mandatory `--file`/`--cmd` recall path: either it tokenizes to nothing\n * (all stopwords) or it loses tokens to stopword filtering so the phrase can never\n * appear as a contiguous run in file/command text (see keyword-signal.ts). This is\n * the `validate` counterpart to the capture-time STOPWORD_KEYWORD guardrail — and,\n * for a single dead keyword, to the UNRECALLABLE_LESSON block — so a graph built\n * before those existed still surfaces its structurally-dead keywords. Warn-only:\n * such a keyword can still fire via an explicit `--keyword` substring.\n */\nexport function collectStopwordKeywords(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n): void {\n const activeTriggerIds = new Set<string>();\n for (const lesson of Object.values(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n for (const t of lesson.triggers) activeTriggerIds.add(t);\n }\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'keyword') continue;\n if (!activeTriggerIds.has(triggerId)) continue;\n if (tokenize(trigger.pattern).length !== 0 && !keywordNeedleLosesTokens(trigger.pattern)) {\n continue;\n }\n findings.push({\n level: 'warning',\n code: 'STOPWORD_KEYWORD',\n message: `Keyword trigger \"${triggerId}\" (${trigger.pattern}) loses tokens to stopword filtering, so its needle can never appear as a contiguous run on the mandatory --file/--cmd recall path — drop the stopwords (e.g. \"state art\" instead of \"state of the art\"), or detach it with \\`lessons untrigger\\`.`,\n triggerId,\n });\n }\n}\n\nfunction normalizeRule(rule: string): string {\n return rule.trim().replace(/\\s+/g, ' ').toLowerCase();\n}\n","import { LessonsGraphSchema, type LessonsGraph } from './graph-schema.js';\nimport {\n collectDanglingRefs,\n collectDuplicateRefs,\n collectLifecycleInvariants,\n collectOrphans,\n collectReachability,\n collectStatusInvariants,\n} from './validate-checks.js';\nimport {\n collectBackslashGlobPatterns,\n collectDuplicateRules,\n collectDuplicateTriggers,\n collectFanout,\n collectInvalidTriggerPatterns,\n collectLowSignalKeywords,\n collectStopwordKeywords,\n} from './validate-quality.js';\nimport { collectDeadFileGlobs, collectRunnerAnchoredPatterns } from './validate-liveness.js';\n\nexport type ValidationLevel = 'error' | 'warning';\n\nexport interface ValidationFinding {\n readonly level: ValidationLevel;\n readonly code: string;\n readonly message: string;\n readonly lessonId?: string;\n readonly topicId?: string;\n readonly triggerId?: string;\n}\n\nexport interface ValidationReport {\n /** True when no `error`-level findings exist (warnings do not affect `ok`). */\n readonly ok: boolean;\n readonly findings: ValidationFinding[];\n}\n\nexport interface ValidateOptions {\n /**\n * Working-tree file list (project-relative, forward-slash) for the dead-glob\n * liveness check. When omitted the check is SKIPPED — the pure write-barrier\n * call in `mutate.ts` passes nothing, so `add` never walks the tree and a\n * liveness warning can never block a write. The CLI/lint callers supply it.\n */\n readonly knownPaths?: ReadonlySet<string>;\n}\n\nexport function validateLessonsGraph(\n graph: LessonsGraph,\n options: ValidateOptions = {},\n): ValidationReport {\n const findings: ValidationFinding[] = [];\n\n const schemaResult = LessonsGraphSchema.safeParse(graph);\n if (!schemaResult.success) {\n findings.push({\n level: 'error',\n code: 'SCHEMA_INVALID',\n message: schemaResult.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; '),\n });\n return { ok: false, findings };\n }\n\n collectDanglingRefs(graph, findings);\n collectDuplicateRefs(graph, findings);\n collectStatusInvariants(graph, findings);\n collectLifecycleInvariants(graph, findings);\n collectDuplicateRules(graph, findings);\n collectReachability(graph, findings);\n collectInvalidTriggerPatterns(graph, findings);\n collectBackslashGlobPatterns(graph, findings);\n collectDuplicateTriggers(graph, findings);\n collectOrphans(graph, findings);\n collectFanout(graph, findings);\n collectLowSignalKeywords(graph, findings);\n collectStopwordKeywords(graph, findings);\n collectRunnerAnchoredPatterns(graph, findings);\n if (options.knownPaths !== undefined) collectDeadFileGlobs(graph, findings, options.knownPaths);\n\n const ok = findings.every((f) => f.level !== 'error');\n return { ok, findings };\n}\n","import { maybeAutoMigrateLessons } from './auto-migrate.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { saveLessonsGraph, tryLoadLessonsGraph } from './graph-store.js';\nimport { acquireLessonsLock } from './lessons-lock.js';\nimport { validateLessonsGraph } from './validate.js';\n\nexport interface MutateOptions {\n readonly retries?: number;\n}\n\nfunction emptyGraph(): LessonsGraph {\n return { version: 1, lessons: {}, topics: {}, triggers: {} };\n}\n\n/**\n * The raw transactional write path (NO legacy migration): acquire the lock,\n * load (or start empty), apply `mutator`, **validate**, and only then persist\n * via the atomic save. Writes are serialized, never truncate the file, and never\n * persist an error-level-invalid graph.\n *\n * INTERNAL — not exported from the public surface. The legacy migrator\n * (`importLegacyLessons`) and scaffolding (`scaffoldLessons`) write through here\n * precisely because they must NOT trigger migration: the migrator IS the\n * migration (calling the migrating `mutateLessonsGraph` would recurse) and\n * scaffolding deliberately creates a fresh empty graph. Every other writer uses\n * `mutateLessonsGraph` below so a first write can never strand a legacy store.\n */\nexport async function mutateLessonsGraphLocked<T>(\n projectRoot: string,\n mutator: (graph: LessonsGraph) => T | Promise<T>,\n options: MutateOptions = {},\n): Promise<Awaited<T>> {\n const release = await acquireLessonsLock(projectRoot, { retries: options.retries });\n try {\n const graph = tryLoadLessonsGraph(projectRoot) ?? emptyGraph();\n // Await the mutator UNDER the lock so async mutations are fully applied\n // before we validate and persist — otherwise a Promise-returning mutator's\n // changes would be saved before they happened (silent data loss).\n const result = await mutator(graph);\n\n const report = validateLessonsGraph(graph);\n if (!report.ok) {\n const errors = report.findings\n .filter((f) => f.level === 'error')\n .map((f) => `${f.code}: ${f.message}`)\n .join('; ');\n throw new Error(`mutateLessonsGraph: refusing to write an invalid graph — ${errors}`);\n }\n\n saveLessonsGraph(projectRoot, graph);\n return result;\n } finally {\n await release();\n }\n}\n\n/**\n * The public transactional write path: migrate a legacy store FIRST (so even a\n * first raw mutation cannot create an empty `lessons.json` and strand\n * `index.yaml`), then run the locked transaction. Every mutating operation\n * (add, merge, deprecate, strip-markers, …) and any third-party consumer routes\n * through here. `maybeAutoMigrateLessons` is a no-op (one stat) when a graph\n * already exists or no legacy index is present, and runs before the lock is\n * taken, so there is no re-entrancy with the migrator's own locked write.\n */\nexport async function mutateLessonsGraph<T>(\n projectRoot: string,\n mutator: (graph: LessonsGraph) => T | Promise<T>,\n options: MutateOptions = {},\n): Promise<Awaited<T>> {\n await maybeAutoMigrateLessons(projectRoot);\n return mutateLessonsGraphLocked(projectRoot, mutator, options);\n}\n","import type { LessonsGraph, TriggerKind } from './graph-schema.js';\nimport { keywordNeedleLosesTokens } from './keyword-signal.js';\nimport { tokenize } from './ranking-text.js';\nimport { isSafeRegexPattern } from './regex-safety.js';\n\n/**\n * Trigger EFFECTIVENESS: can a trigger ever fire on the mandatory `--file`/`--cmd`\n * recall path? A lesson whose every trigger is ineffective there is unrecallable\n * in practice — captured, then silently lost. This is the blocking counterpart to\n * the warn-only capture guardrails: `add` rejects a capture with zero effective\n * triggers (see `addLessonInto`), where the guardrails only nudge.\n *\n * A trigger is ineffective when:\n * - `keyword`: its needle carries no matchable token after stopword filtering, or\n * loses tokens to stopwords so the phrase can never appear as a contiguous run\n * in `--file`/`--cmd` text (see keyword-signal.ts). NOTE this is scoped to the\n * mandatory path — such a keyword can still fire via an explicit `--keyword`\n * substring, which is the documented anti-pattern, not the mandatory recall.\n * - `command_pattern`: the regex is invalid (recall compiles with `new RegExp`\n * and swallows the throw as a non-match) or outside the provably-linear engine\n * (recall skips it to avoid ReDoS) — either way it never matches at recall.\n * - `file_glob`: NEVER flagged here. Input normalization (`add-helpers.ts`) makes\n * syntactically-dead globs unreachable, and dead-vs-tree is a warn-only liveness\n * concern (DEAD_GLOB guardrail), not a structural block.\n */\n\nexport interface IneffectiveTrigger {\n readonly id: string;\n readonly kind: TriggerKind;\n readonly pattern: string;\n readonly reason: string;\n}\n\nexport function ineffectiveTriggers(\n graph: LessonsGraph,\n triggerIds: readonly string[],\n): IneffectiveTrigger[] {\n const out: IneffectiveTrigger[] = [];\n for (const id of triggerIds) {\n const trigger = graph.triggers[id];\n if (trigger === undefined) continue; // dangling ref — can't classify, leave to validate\n const reason = ineffectiveReason(trigger.kind, trigger.pattern);\n if (reason !== null) out.push({ id, kind: trigger.kind, pattern: trigger.pattern, reason });\n }\n return out;\n}\n\nfunction ineffectiveReason(kind: TriggerKind, pattern: string): string | null {\n if (kind === 'keyword') {\n if (tokenize(pattern).length === 0) {\n return 'keyword has no matchable token after stopword filtering — it cannot fire on the mandatory --file/--cmd recall path';\n }\n if (keywordNeedleLosesTokens(pattern)) {\n return 'keyword contains stopwords/short words, so its needle can never appear as a contiguous run on the mandatory --file/--cmd recall path';\n }\n return null;\n }\n if (kind === 'command_pattern') {\n let valid = true;\n try {\n new RegExp(pattern);\n } catch {\n valid = false;\n }\n if (!valid) {\n return 'invalid regex — recall compiles it with new RegExp and swallows the throw as a non-match, so it never fires';\n }\n if (!isSafeRegexPattern(pattern)) {\n return 'regex is outside the provably-linear engine — recall skips it (ReDoS guard), so it never fires';\n }\n return null;\n }\n return null; // file_glob and any future kind: not structurally ineffective\n}\n\n/** Count of `triggerIds` that CAN fire on the mandatory --file/--cmd recall path. */\nexport function effectiveTriggerCount(\n graph: LessonsGraph,\n triggerIds: readonly string[],\n): number {\n return triggerIds.length - ineffectiveTriggers(graph, triggerIds).length;\n}\n\n/**\n * Dead triggers that should BLOCK capture (used by `addLessonInto`). This is a\n * STRICT SUBSET of {@link ineffectiveTriggers}: a `command_pattern` is excluded\n * because the transactional write barrier already rejects an invalid/unsafe\n * command regex with its own error (INVALID/UNSAFE_TRIGGER_PATTERN). Blocking it\n * here too would only pre-empt that clearer, established rejection — so the block\n * meaningfully adds only the keyword-dead case (which the write barrier passes).\n */\nexport function blockingDeadTriggers(\n graph: LessonsGraph,\n triggerIds: readonly string[],\n): IneffectiveTrigger[] {\n return ineffectiveTriggers(graph, triggerIds).filter((t) => t.kind !== 'command_pattern');\n}\n","import { makeLessonId, mergeTriggers, normalizeRule, todayIso, union } from './add-helpers.js';\nimport {\n NoTriggerError,\n RuleTooLongError,\n UnknownTopicError,\n UnrecallableLessonError,\n} from './add-errors.js';\nimport type { AutoPruneSummary } from './auto-prune.js';\nimport {\n type GuardrailWarning,\n inspectCapturedLesson,\n nearDuplicateWarning,\n} from './capture-guardrails.js';\nimport { MAX_RULE_LENGTH, type LessonsGraph } from './graph-schema.js';\nimport { mutateLessonsGraph } from './mutate.js';\nimport { blockingDeadTriggers } from './trigger-effectiveness.js';\n\n// Re-export the capture rejection errors so existing `from './add.js'` importers\n// (CLI/MCP surfacing, tests) keep working after the split into add-errors.ts.\nexport {\n NoTriggerError,\n RuleTooLongError,\n UnknownTopicError,\n UnrecallableLessonError,\n} from './add-errors.js';\n\nexport interface AddLessonTriggers {\n readonly files?: readonly string[];\n readonly commands?: readonly string[];\n readonly keywords?: readonly string[];\n}\n\nexport interface AddLessonInput {\n readonly rule: string;\n readonly topic: string;\n readonly triggers: AddLessonTriggers;\n readonly evidence?: readonly string[];\n readonly rationale?: string;\n readonly createdAt?: string;\n}\n\nexport interface AddLessonOptions {\n readonly allowNewTopic?: boolean;\n readonly topicSummary?: string;\n readonly retries?: number;\n /**\n * Skip the \"a lesson needs at least one trigger\" guard. Set only by the\n * legacy-merge recovery path, which folds historical lessons that may predate\n * the requirement; interactive capture (CLI/MCP) always enforces it so a fresh\n * agent cannot create an unreachable lesson.\n */\n readonly allowNoTrigger?: boolean;\n /**\n * Working-tree file list (project-relative, forward-slash) enabling the\n * warn-only DEAD_GLOB guardrail. The capture entry point supplies it; the\n * legacy-merge path omits it, so no tree walk happens off the capture path.\n */\n readonly knownPaths?: ReadonlySet<string>;\n}\n\nexport interface AddLessonResult {\n readonly id: string;\n readonly isNewLesson: boolean;\n readonly isNewTopic: boolean;\n readonly newTriggerIds: string[];\n /** Non-blocking capture guardrail warnings for the resulting (merged) lesson. */\n readonly warnings: GuardrailWarning[];\n /**\n * Counts of structural cruft the opt-in auto-prune cleaned up right after this\n * capture (config `autoPrune: true`). Present only when something was pruned;\n * absent when auto-prune is off or there was nothing to clean.\n */\n readonly autoPruned?: AutoPruneSummary;\n}\n\nfunction countInputTriggers(triggers: AddLessonInput['triggers']): number {\n return (\n (triggers.files?.length ?? 0) +\n (triggers.commands?.length ?? 0) +\n (triggers.keywords?.length ?? 0)\n );\n}\n\nexport async function addLesson(\n projectRoot: string,\n input: AddLessonInput,\n options: AddLessonOptions = {},\n): Promise<AddLessonResult> {\n // mutateLessonsGraph migrates a legacy store first, so the very first capture\n // cannot create lessons.json over an unmigrated index.yaml and strand it.\n return mutateLessonsGraph(projectRoot, (graph) => addLessonInto(graph, input, options), {\n retries: options.retries,\n });\n}\n\n/**\n * Pure mutation over the loaded graph. Dedup is by normalized rule text across\n * ALL topics: a re-captured rule UPSERTS — its new triggers, evidence,\n * rationale, and topic are merged into the existing lesson rather than silently\n * dropped, and no duplicate is created (so the active-only DUPLICATE_RULE check\n * stays satisfied). Exported so legacy MERGE recovery can fold each legacy\n * lesson into an existing graph through the same dedup + content-addressing path.\n */\nexport function addLessonInto(\n graph: LessonsGraph,\n input: AddLessonInput,\n options: AddLessonOptions,\n): AddLessonResult {\n const ruleKey = normalizeRule(input.rule);\n const trimmedRule = input.rule.trim();\n // A rule far longer than one sentence is a malformed capture; block it before\n // it can bloat every recall that surfaces it (the hook also truncates as a\n // last-resort defense for already-stored / hostile graphs).\n if (trimmedRule.length > MAX_RULE_LENGTH) {\n throw new RuleTooLongError(trimmedRule.length, MAX_RULE_LENGTH);\n }\n const existingId = findExistingLessonByRule(graph, ruleKey);\n\n // Topic validity is checked first so an unknown-topic / missing-summary error\n // takes precedence over the trigger guard below (clearer, and stable for the\n // documented exit codes).\n const isNewTopic = graph.topics[input.topic] === undefined;\n if (isNewTopic) {\n if (options.allowNewTopic !== true) throw new UnknownTopicError(input.topic);\n if (options.topicSummary === undefined || options.topicSummary.length === 0) {\n throw new Error(`addLesson: new topic \"${input.topic}\" requires topicSummary.`);\n }\n graph.topics[input.topic] = { summary: options.topicSummary };\n }\n\n // A lesson with no trigger can never be recalled. Enforce ≥1 trigger on the\n // RESULTING lesson (an upsert keeps the existing lesson's triggers, so it may\n // pass no new ones). Skipped only by legacy-merge recovery.\n if (options.allowNoTrigger !== true) {\n const existingTriggers =\n existingId !== null ? (graph.lessons[existingId]?.triggers.length ?? 0) : 0;\n if (countInputTriggers(input.triggers) === 0 && existingTriggers === 0) {\n throw new NoTriggerError();\n }\n }\n\n const { triggerIds, newTriggerIds } = mergeTriggers(graph, input.triggers);\n\n // A lesson whose RESULTING triggers are ALL dead on the mandatory --file/--cmd\n // recall path is unrecallable — block it (the symmetric, blocking counterpart\n // to the warn-only guardrails). Computed on the merged set, so an upsert that\n // adds a dead trigger to an already-effective lesson is fine. command_pattern\n // deadness is deferred to the write barrier (see blockingDeadTriggers), so this\n // block adds the keyword-dead case the barrier passes. Skipped only by\n // legacy-merge recovery (same escape hatch as the NoTriggerError check above).\n // A throw here aborts the transactional write, so nothing is persisted.\n if (options.allowNoTrigger !== true) {\n const resultingTriggers =\n existingId !== null ? union(graph.lessons[existingId]!.triggers, triggerIds) : triggerIds;\n const blockingDead = blockingDeadTriggers(graph, resultingTriggers);\n if (resultingTriggers.length > 0 && blockingDead.length === resultingTriggers.length) {\n throw new UnrecallableLessonError(blockingDead);\n }\n }\n\n if (existingId !== null) {\n // existingId came from Object.entries(graph.lessons), so it is present.\n const existing = graph.lessons[existingId]!;\n graph.lessons[existingId] = {\n ...existing,\n topics: union(existing.topics, [input.topic]),\n triggers: union(existing.triggers, triggerIds),\n evidence: union(existing.evidence, input.evidence ?? []),\n ...(existing.rationale === undefined && input.rationale !== undefined\n ? { rationale: input.rationale }\n : {}),\n };\n return {\n id: existingId,\n isNewLesson: false,\n isNewTopic,\n newTriggerIds,\n // Near-duplicate detection is meaningless on an upsert (the lesson IS the\n // match), so only DEAD_GLOB/hygiene warnings apply here.\n warnings: inspectCapturedLesson(graph, existingId, options.knownPaths),\n };\n }\n\n const id = makeLessonId(graph, input.topic, ruleKey);\n graph.lessons[id] = {\n rule: trimmedRule,\n topics: [input.topic],\n triggers: triggerIds,\n evidence: input.evidence === undefined ? [] : [...input.evidence],\n status: 'active',\n createdAt: input.createdAt ?? todayIso(),\n ...(input.rationale === undefined ? {} : { rationale: input.rationale }),\n };\n const warnings = inspectCapturedLesson(graph, id, options.knownPaths);\n const nearDup = nearDuplicateWarning(graph, id);\n return {\n id,\n isNewLesson: true,\n isNewTopic,\n newTriggerIds,\n warnings: nearDup === null ? warnings : [...warnings, nearDup],\n };\n}\n\n/**\n * Find an ACTIVE lesson with the same normalized rule. Inactive\n * (deprecated/superseded) lessons are ignored on purpose: re-capturing a rule\n * whose only match is dead must produce a fresh ACTIVE lesson (a live\n * replacement), not silently enrich a corpse that recall will never surface.\n */\nfunction findExistingLessonByRule(graph: LessonsGraph, ruleKey: string): string | null {\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n if (normalizeRule(lesson.rule) === ruleKey) return id;\n }\n return null;\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport type { MatchedLesson } from './query.js';\n\n/**\n * Ranking signals derived from graph STRUCTURE (not text — that lives in\n * ranking-text.ts). Split out of ranking.ts to keep each file within the\n * repository 200-line limit; ranking.ts owns the RRF fusion and capping.\n */\n\n/** Active-lesson reference count per trigger — the fanout used for specificity. */\nexport function buildFanout(graph: LessonsGraph): Map<string, number> {\n const fanout = new Map<string, number>();\n for (const lesson of Object.values(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n for (const t of lesson.triggers) fanout.set(t, (fanout.get(t) ?? 0) + 1);\n }\n return fanout;\n}\n\n/**\n * Per-query topic coherence, keyed by lesson id. For each topic, count how many\n * lessons in THIS query's matched set reference it; a lesson's coherence is the\n * max over its own topics — \"this query is mostly about topic X, and I'm in X\".\n *\n * Computed over the matched set (not the whole graph) on purpose: it reflects\n * what the current query is about, so it cannot simply favour the largest topic\n * in the corpus. When several matched lessons cluster in one topic, that topic\n * is probably what the query is about, and its members are boosted together.\n */\nexport function buildTopicCoherence(matches: readonly MatchedLesson[]): Map<string, number> {\n const topicCount = new Map<string, number>();\n for (const { lesson } of matches) {\n for (const t of lesson.topics) topicCount.set(t, (topicCount.get(t) ?? 0) + 1);\n }\n const coherence = new Map<string, number>();\n for (const { id, lesson } of matches) {\n let best = 0;\n // Every topic of a matched lesson was counted in the first pass, so the\n // lookup always hits — assert it (mirrors ranking.ts's fanout invariant).\n for (const t of lesson.topics) best = Math.max(best, topicCount.get(t)!);\n coherence.set(id, best);\n }\n return coherence;\n}\n","import { MAX_RECOMMENDED_TRIGGERS } from './capture-guardrails.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { buildFanout } from './ranking-signals.js';\nimport { deadFileGlobIds } from './validate-liveness.js';\n\n/**\n * Graph curation. Two safe, deterministic operations, both reversible via git\n * (lessons.json is the committed source of truth):\n *\n * 1. Trim over-cap ACTIVE lessons down to `cap` triggers, dropping the\n * highest-fanout (least specific) triggers first — they are the ones that\n * dilute recall the most. Never trims below one trigger.\n * 2. Remove dead triggers — those no ACTIVE lesson references (orphans, or\n * referenced only by superseded/deprecated lessons) — from the table and\n * strip their (now non-recall-bearing) references everywhere.\n *\n * `planPrune` is a pure read; `applyPruneToGraph` mutates a loaded graph in\n * place (call it inside `mutateLessonsGraph` so the write stays transactional).\n */\n\nexport interface LessonTrim {\n readonly id: string;\n /** Trigger ids dropped from this lesson (kept the most specific `cap`). */\n readonly removedTriggers: string[];\n readonly keptCount: number;\n}\n\nexport interface PrunePlan {\n /** Triggers removed from the table entirely (dead: no active lesson uses them). */\n readonly removedTriggerIds: string[];\n /** Topics removed from the table entirely (referenced by zero lessons, any status). */\n readonly removedTopicIds: string[];\n /** Active lessons trimmed down to the cap. */\n readonly trimmedLessons: LessonTrim[];\n /** Dead `file_glob` triggers detached from a lesson that still keeps ≥1 trigger. */\n readonly removedDeadGlobs: LessonTrim[];\n /** Active lessons left unreachable (every trigger is a dead glob) — REPORTED, not modified (stripping would strand them). */\n readonly unreachableLessons: string[];\n /** The effective per-lesson trigger cap used (clamped to ≥ 1). */\n readonly cap: number;\n}\n\nexport interface PruneOptions {\n /** Per-lesson trigger cap. Defaults to the capture guardrail recommendation. */\n readonly cap?: number;\n /**\n * Working-tree file list (project-relative, forward-slash). When provided,\n * prune also GCs dead `file_glob` triggers. Omitted → no liveness pruning, so\n * the transactional write barrier (which has no tree) never strips a glob.\n */\n readonly knownPaths?: ReadonlySet<string>;\n /**\n * Drop the highest-fanout triggers from over-cap active lessons. Defaults to\n * `true` (the full `lessons prune`). Set `false` for the GC-only subset\n * (orphan triggers/topics + non-stranding dead-glob detach) that opt-in\n * auto-prune runs — it never removes a trigger from a within-cap lesson.\n */\n readonly trimOverCap?: boolean;\n}\n\n/** Compute (without mutating) what a prune would change. */\nexport function planPrune(graph: LessonsGraph, options: PruneOptions = {}): PrunePlan {\n const cap = Math.max(1, options.cap ?? MAX_RECOMMENDED_TRIGGERS);\n const fanout = buildFanout(graph);\n\n const trimmedLessons: LessonTrim[] = [];\n // Trigger ids each active lesson keeps after trimming — drives liveness below.\n const keptByLesson = new Map<string, readonly string[]>();\n\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n if (options.trimOverCap === false || lesson.triggers.length <= cap) {\n keptByLesson.set(id, lesson.triggers);\n continue;\n }\n // Most specific (lowest fanout) first; deterministic id tie-break.\n // This lesson is active, so buildFanout counted all of its triggers — the\n // lookups always hit (mirrors ranking.ts's fanout invariant).\n const ordered = [...lesson.triggers].sort((a, b) => {\n const fa = fanout.get(a)!;\n const fb = fanout.get(b)!;\n return fa !== fb ? fa - fb : a < b ? -1 : 1;\n });\n const drop = new Set(ordered.slice(cap));\n const kept = lesson.triggers.filter((t) => !drop.has(t)); // preserve original order\n keptByLesson.set(id, kept);\n trimmedLessons.push({ id, removedTriggers: [...drop], keptCount: kept.length });\n }\n\n // Dead-glob GC: detach a dead `file_glob` from a lesson, but only when the\n // lesson keeps ≥1 other trigger — never strand it. A lesson whose every\n // (post-trim) trigger is a dead glob is reported as unreachable and left as-is\n // (stripping its last trigger would make it invalid / unrecallable).\n const removedDeadGlobs: LessonTrim[] = [];\n const unreachableLessons: string[] = [];\n if (options.knownPaths !== undefined) {\n const dead = deadFileGlobIds(graph, options.knownPaths);\n if (dead.size > 0) {\n for (const [id, kept] of keptByLesson) {\n const deadInLesson = kept.filter((t) => dead.has(t));\n if (deadInLesson.length === 0) continue;\n const remaining = kept.filter((t) => !dead.has(t));\n if (remaining.length >= 1) {\n keptByLesson.set(id, remaining);\n removedDeadGlobs.push({ id, removedTriggers: deadInLesson, keptCount: remaining.length });\n } else {\n unreachableLessons.push(id);\n }\n }\n unreachableLessons.sort();\n }\n }\n\n const live = new Set<string>();\n for (const kept of keptByLesson.values()) for (const t of kept) live.add(t);\n const removedTriggerIds = Object.keys(graph.triggers)\n .filter((t) => !live.has(t))\n .sort();\n\n // Topic GC: a topic referenced by NO lesson (any status) is dead weight —\n // `validate` only warns (ORPHAN_TOPIC); prune actually removes it. Trigger\n // trimming never changes topic references, so this is independent of `live`.\n const referencedTopics = new Set<string>();\n for (const lesson of Object.values(graph.lessons)) {\n for (const topic of lesson.topics) referencedTopics.add(topic);\n }\n const removedTopicIds = Object.keys(graph.topics)\n .filter((t) => !referencedTopics.has(t))\n .sort();\n\n return { removedTriggerIds, removedTopicIds, trimmedLessons, removedDeadGlobs, unreachableLessons, cap };\n}\n\n/** Apply a {@link planPrune} result to a loaded graph in place. */\nexport function applyPruneToGraph(graph: LessonsGraph, plan: PrunePlan): void {\n // 1. Detach per-lesson triggers (cap trims + dead-glob GC). A removed trigger\n // may survive in the table when another active lesson still references it,\n // so this only edits the lesson; the table GC in step 3 cleans up orphans.\n for (const trim of [...plan.trimmedLessons, ...(plan.removedDeadGlobs ?? [])]) {\n const lesson = graph.lessons[trim.id];\n if (lesson === undefined) continue;\n const drop = new Set(trim.removedTriggers);\n graph.lessons[trim.id] = { ...lesson, triggers: lesson.triggers.filter((t) => !drop.has(t)) };\n }\n\n // 2. Drop orphan topics (referenced by zero lessons). Independent of trigger\n // pruning, so it runs unconditionally.\n for (const topicId of plan.removedTopicIds) delete graph.topics[topicId];\n\n // 3. Remove dead triggers from the table and strip every remaining reference\n // (incl. superseded/deprecated lessons) so no dangling reference survives.\n const dead = new Set(plan.removedTriggerIds);\n if (dead.size === 0) return;\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.triggers.some((t) => dead.has(t))) {\n graph.lessons[id] = { ...lesson, triggers: lesson.triggers.filter((t) => !dead.has(t)) };\n }\n }\n for (const t of dead) delete graph.triggers[t];\n}\n\n/** True when a plan would change nothing (unreachable lessons are report-only). */\nexport function isEmptyPrunePlan(plan: PrunePlan): boolean {\n return (\n plan.removedTriggerIds.length === 0 &&\n plan.removedTopicIds.length === 0 &&\n plan.trimmedLessons.length === 0 &&\n plan.removedDeadGlobs.length === 0\n );\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { tryLoadLessonsGraph } from './graph-store.js';\nimport { mutateLessonsGraph } from './mutate.js';\nimport { lessonsPaths } from './paths.js';\nimport { applyPruneToGraph, isEmptyPrunePlan, planPrune } from './prune.js';\n\n/**\n * Opt-in automatic graph hygiene. When `.agentsmesh/lessons/config.json` carries\n * `\"autoPrune\": true`, the capture path runs the GC-only subset of `prune` after\n * a successful add — orphan triggers/topics removed and non-stranding dead globs\n * detached, NEVER an active lesson dropped or a within-cap lesson trimmed. It is\n * the safe half of `lessons prune`, so it can run unattended: every change is\n * git-reversible (lessons.json is the committed source of truth) and a lesson is\n * never made unrecallable.\n *\n * Off by default — the manual `lessons prune` (with over-cap trimming) stays the\n * deliberate, reviewed curation path.\n */\n\n/** True when the project config opts into automatic GC-only pruning. */\nexport function isAutoPruneEnabled(projectRoot: string): boolean {\n const path = lessonsPaths(projectRoot).config;\n if (!existsSync(path)) return false;\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (typeof parsed !== 'object' || parsed === null) return false;\n return (parsed as Record<string, unknown>).autoPrune === true;\n } catch {\n return false;\n }\n}\n\nexport interface AutoPruneSummary {\n readonly removedTriggers: number;\n readonly removedTopics: number;\n readonly detachedDeadGlobs: number;\n}\n\n/**\n * Run the GC-only prune when enabled; a no-op (returns `null`) when disabled or\n * when there is nothing to clean. `knownPaths` (the working-tree file list the\n * capture path already computed) enables dead-glob detachment; omit it to GC\n * orphans only. Best-effort: a corrupt/absent graph yields `null`, never a throw,\n * so auto-prune can never break the capture it follows.\n */\nexport async function maybeAutoPrune(\n projectRoot: string,\n knownPaths: ReadonlySet<string> | undefined,\n): Promise<AutoPruneSummary | null> {\n if (!isAutoPruneEnabled(projectRoot)) return null;\n // Cheap unlocked pre-check so we never open a transaction (and rewrite the\n // file) when there is nothing to prune — the common case after an add.\n const preview = tryLoadLessonsGraph(projectRoot);\n if (preview === null) return null;\n if (isEmptyPrunePlan(planPrune(preview, { trimOverCap: false, knownPaths }))) return null;\n\n let summary: AutoPruneSummary = { removedTriggers: 0, removedTopics: 0, detachedDeadGlobs: 0 };\n await mutateLessonsGraph(projectRoot, (graph) => {\n // Re-plan under the lock (the graph may have moved since the pre-check).\n const plan = planPrune(graph, { trimOverCap: false, knownPaths });\n if (isEmptyPrunePlan(plan)) return;\n applyPruneToGraph(graph, plan);\n summary = {\n removedTriggers: plan.removedTriggerIds.length,\n removedTopics: plan.removedTopicIds.length,\n detachedDeadGlobs: plan.removedDeadGlobs.reduce((n, t) => n + t.removedTriggers.length, 0),\n };\n });\n const total = summary.removedTriggers + summary.removedTopics + summary.detachedDeadGlobs;\n return total > 0 ? summary : null;\n}\n","import {\n appendFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname } from 'node:path';\n\n/**\n * Generic append-only JSONL log primitive shared by the recall- and\n * capture-telemetry modules. One JSON object per line; readers skip torn lines\n * (a crash mid-append or a hand-edit) so a diagnostic log can never crash stats.\n *\n * Bounded by a byte-size trigger on append (cheap `statSync`, full rewrite only\n * when it grows past the trigger) plus an atomic last-N truncation, so a\n * committed `.agentsmesh/` never accumulates an unbounded diagnostic file. The\n * caller owns the on/off gate (telemetry env) and the path — this module is pure\n * filesystem plumbing.\n */\n\n/** True when a log file exists — distinguishes \"never recorded\" from \"empty\". */\nexport function logExists(path: string): boolean {\n return existsSync(path);\n}\n\nexport interface JsonlAppendOptions {\n /** Keep at most this many records; older ones drop on truncation. */\n readonly maxRecords: number;\n /** Byte size past which the log self-truncates to {@link JsonlAppendOptions.maxRecords}. */\n readonly trimTriggerBytes: number;\n}\n\n/** Append one record, creating parent dirs; truncate when past the byte trigger. */\nexport function appendJsonl(path: string, record: unknown, opts: JsonlAppendOptions): void {\n mkdirSync(dirname(path), { recursive: true });\n appendFileSync(path, `${JSON.stringify(record)}\\n`, 'utf8');\n if (statSync(path).size > opts.trimTriggerBytes) capJsonl(path, opts.maxRecords);\n}\n\n/**\n * Truncate the log to its last `maxRecords` records. No-op when absent or\n * already within the cap. Rewrites atomically (temp + rename) so a reader never\n * sees a torn file. Idempotent and safe to call from any append path.\n */\nexport function capJsonl(path: string, maxRecords: number): void {\n if (!existsSync(path)) return;\n const lines = readFileSync(path, 'utf8')\n .split('\\n')\n .filter((l) => l.trim().length > 0);\n if (lines.length <= maxRecords) return;\n const kept = lines.slice(lines.length - maxRecords);\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, `${kept.join('\\n')}\\n`, 'utf8');\n renameSync(tmp, path);\n}\n\n/** Read every record, skipping any malformed line. Returns [] when absent. */\nexport function readJsonl<T>(path: string): T[] {\n if (!existsSync(path)) return [];\n const out: T[] = [];\n for (const line of readFileSync(path, 'utf8').split('\\n')) {\n if (line.trim().length === 0) continue;\n try {\n out.push(JSON.parse(line) as T);\n } catch {\n // A torn final line (crash mid-append) or hand-edit — skip it, don't fail stats.\n }\n }\n return out;\n}\n","import { join } from 'node:path';\nimport { appendJsonl, capJsonl, logExists, readJsonl } from './jsonl-log.js';\nimport { lessonsPaths } from './paths.js';\n\n/** Keep at most this many recall records; older ones are dropped on truncation. */\nexport const MAX_RECALL_LOG_RECORDS = 5000;\n\n/**\n * Byte size past which {@link appendRecallRecord} truncates the log. Generous\n * headroom over {@link MAX_RECALL_LOG_RECORDS} worth of records so trimming is\n * rare (each append pays only a cheap `statSync`, never a full read).\n */\nconst RECALL_LOG_TRIM_TRIGGER_BYTES = 2_000_000;\n\n/**\n * Opt-in recall telemetry. Mandatory recall runs before every edit/command, so\n * its *frequency* — not its per-call payload — is the real token cost. This log\n * captures one append-only record per recall so `lessons stats` can answer \"is\n * per-action recall token-justified versus loading the whole active set once?\".\n *\n * OFF by default: a no-op unless {@link TELEMETRY_ENV} === '1'. Records carry\n * field-PRESENCE booleans only — never the raw file / command / keyword text —\n * so the log stays small and leaks no source content.\n */\n\nexport const TELEMETRY_ENV = 'AGENTSMESH_LESSONS_TELEMETRY';\n\n/**\n * Optional session correlator. When the harness exports a stable id per agent\n * session, `stats` groups recalls by it for an honest per-session preload\n * comparison; absent it, `stats` falls back to time-gap clustering.\n */\nexport const SESSION_ENV = 'AGENTSMESH_SESSION_ID';\n\n/** The session id for this process, or undefined when unset/blank. */\nexport function sessionId(env: NodeJS.ProcessEnv = process.env): string | undefined {\n const raw = env[SESSION_ENV];\n return raw !== undefined && raw.trim().length > 0 ? raw : undefined;\n}\n\n/** Per-recall telemetry row. One JSON object per line in {@link recallLogPath}. */\nexport interface RecallTelemetryRecord {\n /** ISO-8601 timestamp supplied by the caller. */\n readonly ts: string;\n readonly hasFile: boolean;\n readonly hasCommand: boolean;\n readonly hasKeyword: boolean;\n /** Active lessons that matched before ranking/cap. */\n readonly totalMatches: number;\n /** Lessons actually returned after limit + token budget. */\n readonly returnedCount: number;\n /** Estimated cumulative rule-token cost of the returned lessons. */\n readonly returnedTokens: number;\n /** True when caps hid matches (`totalMatches > returnedCount`). */\n readonly truncated: boolean;\n /** Matched lessons attributable to each trigger kind (overlaps allowed). */\n readonly matchedByKind: {\n readonly file: number;\n readonly command: number;\n readonly keyword: number;\n };\n /**\n * Session correlator from {@link SESSION_ENV}, when set. Lets `stats` group\n * recalls into sessions for the per-session preload comparison. Optional —\n * records predating this field, or made without the env, simply lack it and\n * `stats` clusters them by time gap instead.\n */\n readonly session?: string;\n /**\n * Ids of the lessons actually returned (post-cap). Lets `stats` measure\n * intra-session repeat-delivery (the dedup opportunity) without storing rule\n * text. Optional for backward compatibility with pre-field records.\n */\n readonly lessonIds?: readonly string[];\n /**\n * True when the recall ran with caps OFF (`--all`) — a diagnostic dump, not a\n * mandatory recall. `stats` excludes these from the mandatory-cost figure so a\n * few `--all` calls don't inflate the break-even against recall. Optional;\n * absent ⇒ treated as a normal (non-bypassed) recall.\n */\n readonly bypassed?: boolean;\n}\n\n/** Append-only JSONL recall log. Sibling of the canonical graph, never the graph. */\nexport function recallLogPath(projectRoot: string): string {\n return join(lessonsPaths(projectRoot).base, 'recall-log.jsonl');\n}\n\nexport function isTelemetryEnabled(env: NodeJS.ProcessEnv = process.env): boolean {\n return env[TELEMETRY_ENV] === '1';\n}\n\n/**\n * Append one record to the recall log — a no-op unless telemetry is enabled, so\n * the recall hot path pays nothing in the default configuration.\n */\nexport function appendRecallRecord(\n projectRoot: string,\n record: RecallTelemetryRecord,\n env: NodeJS.ProcessEnv = process.env,\n): void {\n if (!isTelemetryEnabled(env)) return;\n appendJsonl(recallLogPath(projectRoot), record, {\n maxRecords: MAX_RECALL_LOG_RECORDS,\n trimTriggerBytes: RECALL_LOG_TRIM_TRIGGER_BYTES,\n });\n}\n\n/**\n * Truncate the recall log to its last {@link MAX_RECALL_LOG_RECORDS} records\n * (or `maxRecords` when given). No-op when absent or already within the cap.\n */\nexport function capRecallLog(projectRoot: string, maxRecords = MAX_RECALL_LOG_RECORDS): void {\n capJsonl(recallLogPath(projectRoot), maxRecords);\n}\n\n/** True when a recall log exists — distinguishes \"never recorded\" from \"empty\". */\nexport function recallLogExists(projectRoot: string): boolean {\n return logExists(recallLogPath(projectRoot));\n}\n\n/** Read the recall log, skipping any malformed line. Returns [] when absent. */\nexport function readRecallLog(projectRoot: string): RecallTelemetryRecord[] {\n return readJsonl<RecallTelemetryRecord>(recallLogPath(projectRoot));\n}\n","import { join } from 'node:path';\nimport type { AddLessonResult } from './add.js';\nimport { appendJsonl, logExists, readJsonl } from './jsonl-log.js';\nimport { lessonsPaths } from './paths.js';\nimport { isTelemetryEnabled, sessionId } from './telemetry.js';\n\n/**\n * Opt-in capture telemetry — the symmetric counterpart to recall telemetry.\n *\n * Recall has a `PostToolUse` hook + telemetry + `stats`; capture had nothing, so\n * a maintainer could not tell whether lessons were being captured or silently\n * skipped/blocked. This log mirrors the recall log: one append-only record per\n * `lessons add` (CLI or MCP), gated on the SAME `AGENTSMESH_LESSONS_TELEMETRY=1`\n * env, recording presence/counts ONLY (never the rule text) so it leaks no\n * source content and stays small.\n */\n\n/** Keep at most this many capture records; older ones drop on truncation. */\nexport const MAX_CAPTURE_LOG_RECORDS = 5000;\n\n/** Byte size past which the capture log self-truncates (mirrors the recall log). */\nconst CAPTURE_LOG_TRIM_TRIGGER_BYTES = 2_000_000;\n\n/** Per-capture telemetry row. One JSON object per line in {@link captureLogPath}. */\nexport interface CaptureTelemetryRecord {\n /** ISO-8601 timestamp supplied by the recorder. */\n readonly ts: string;\n /** True for a brand-new lesson; false for an upsert onto an existing rule. */\n readonly isNewLesson: boolean;\n /** True when this capture also created the topic. */\n readonly isNewTopic: boolean;\n /** New trigger nodes this capture added to the graph. */\n readonly newTriggerCount: number;\n /** Trigger kinds PASSED to this capture (from the input — known even when blocked). */\n readonly triggerKinds: {\n readonly file: number;\n readonly command: number;\n readonly keyword: number;\n };\n /** True when the capture was REJECTED (no effective trigger, unknown topic, write-barrier, …). */\n readonly blocked: boolean;\n /** Non-blocking guardrail codes on the resulting lesson (empty when blocked). */\n readonly warningCodes: readonly string[];\n /** Session correlator from `AGENTSMESH_SESSION_ID`, when set. */\n readonly session?: string;\n /** Id of the resulting lesson — absent on a blocked capture. */\n readonly lessonId?: string;\n}\n\n/** Counts of triggers passed to a capture, by kind. */\nexport interface CaptureTriggerKinds {\n readonly file: number;\n readonly command: number;\n readonly keyword: number;\n}\n\n/** Append-only JSONL capture log. Sibling of the recall log and the graph. */\nexport function captureLogPath(projectRoot: string): string {\n return join(lessonsPaths(projectRoot).base, 'capture-log.jsonl');\n}\n\n/** Append one capture record — a no-op unless telemetry is enabled. */\nexport function appendCaptureRecord(\n projectRoot: string,\n record: CaptureTelemetryRecord,\n env: NodeJS.ProcessEnv = process.env,\n): void {\n if (!isTelemetryEnabled(env)) return;\n appendJsonl(captureLogPath(projectRoot), record, {\n maxRecords: MAX_CAPTURE_LOG_RECORDS,\n trimTriggerBytes: CAPTURE_LOG_TRIM_TRIGGER_BYTES,\n });\n}\n\n/** True when a capture log exists — distinguishes \"never recorded\" from \"empty\". */\nexport function captureLogExists(projectRoot: string): boolean {\n return logExists(captureLogPath(projectRoot));\n}\n\n/** Read the capture log, skipping any malformed line. Returns [] when absent. */\nexport function readCaptureLog(projectRoot: string): CaptureTelemetryRecord[] {\n return readJsonl<CaptureTelemetryRecord>(captureLogPath(projectRoot));\n}\n\n/**\n * Build and append a capture record from the (possibly null) result. Pass\n * `result = null` to record a BLOCKED capture — the kinds attempted are still\n * known from the input, so a rejected capture stays visible to `stats`. Gated,\n * so the capture path computes nothing in the default-off config.\n */\nexport function recordCapture(\n projectRoot: string,\n triggerKinds: CaptureTriggerKinds,\n result: AddLessonResult | null,\n env: NodeJS.ProcessEnv = process.env,\n): void {\n if (!isTelemetryEnabled(env)) return;\n const session = sessionId(env);\n appendCaptureRecord(\n projectRoot,\n {\n ts: new Date().toISOString(),\n isNewLesson: result?.isNewLesson ?? false,\n isNewTopic: result?.isNewTopic ?? false,\n newTriggerCount: result?.newTriggerIds.length ?? 0,\n triggerKinds,\n blocked: result === null,\n warningCodes: result?.warnings.map((w) => w.code) ?? [],\n ...(session !== undefined ? { session } : {}),\n ...(result !== null ? { lessonId: result.id } : {}),\n },\n env,\n );\n}\n","import { realpathSync } from 'node:fs';\nimport { basename, dirname, relative, resolve } from 'node:path';\n\n/**\n * Normalize a recall `--file` path to the project-relative, forward-slash form\n * that lesson `file_glob` patterns are authored against.\n *\n * Recall callers routinely pass shapes a project-relative glob will NOT match:\n * an absolute path (the agent harness often has only that), a `./`-prefixed\n * path, or a Windows backslash path. Without normalization picomatch silently\n * returns no match, so mandatory recall yields zero lessons — a false negative\n * on the most-used recall input. Globs are always project-relative, so the\n * correct, lossless fix is to relativize the input against the project root.\n *\n * A path outside the project root is returned as a `../`-prefixed relative path\n * (still forward-slashed); project globs legitimately will not match it.\n */\nexport function normalizeRecallFile(file: string, projectRoot: string): string {\n const forward = file.replaceAll('\\\\', '/');\n const direct = relativize(projectRoot, forward);\n // A `..`-escaping result is EITHER a genuine outside-the-root path OR a\n // symlink mismatch: the CLI derives projectRoot from process.cwd() (the\n // PHYSICAL path, e.g. /private/tmp/x) while a harness passes a LOGICAL\n // absolute path through a symlink (/tmp/x, macOS /tmp -> /private/tmp).\n // Realpath both sides and retry before concluding the file is outside the\n // project; prefer the caller-shaped result so the common path skips all I/O.\n if (!direct.startsWith('../')) return direct;\n const viaReal = relativize(safeRealpath(projectRoot), safeRealpath(resolve(projectRoot, forward)));\n return viaReal.startsWith('../') ? direct : viaReal;\n}\n\n/** Relativize `forward` against `root`, forward-slashed; the root path itself\n * yields '' from `relative`, so fall back to the input rather than emit ''. */\nfunction relativize(root: string, forward: string): string {\n const rel = relative(root, resolve(root, forward)).replaceAll('\\\\', '/');\n return rel === '' ? forward.replaceAll('\\\\', '/') : rel;\n}\n\n/**\n * Resolve symlinks on the longest EXISTING prefix of `path`, re-attaching any\n * not-yet-existing tail. Plain `realpathSync` throws on a path whose final\n * segments do not exist yet (a capture target about to be written), so walk up\n * to the nearest real ancestor and rejoin the remainder.\n */\nfunction safeRealpath(path: string): string {\n try {\n return realpathSync(path);\n } catch {\n const parent = dirname(path);\n if (parent === path) return path; // reached the filesystem root unresolved\n return resolve(safeRealpath(parent), basename(path));\n }\n}\n","import { readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { toRelPath } from './paths.js';\n\n/**\n * Directories never worth walking for the trigger-liveness file list: the huge,\n * non-source ones. Note `dist`/`coverage`/build outputs are deliberately KEPT —\n * \"dead\" means a glob matches NO file on disk (a rename casualty), so a glob over\n * a present-but-gitignored build artifact must read as LIVE, not dead.\n */\nconst SKIP_DIRS = new Set(['.git', 'node_modules']);\n\n/** Safety bound on the walk so a pathological tree can't run away. */\nconst MAX_FILES = 200_000;\n\n/**\n * The on-disk file list (project-relative, forward-slash) used by the\n * dead-`file_glob` liveness check — or `null` when it cannot be read, so the\n * caller SKIPS the check rather than flagging every glob dead.\n *\n * Liveness is \"matches a file that exists\", so this walks the working tree by\n * existence (NOT by git tracking): a glob over a present-but-gitignored file\n * (e.g. a build output) is live, and only a path that no longer exists on disk\n * — a rename casualty — is dead. Skips `.git`/`node_modules` for sanity. Never\n * throws. Not on the recall hot path (only `validate`/`lint`/`prune` call it).\n */\nexport function listProjectFiles(projectRoot: string): Set<string> | null {\n const out = new Set<string>();\n try {\n const stack = [projectRoot];\n while (stack.length > 0) {\n const dir = stack.pop()!;\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (!SKIP_DIRS.has(entry.name)) stack.push(join(dir, entry.name));\n } else if (entry.isFile()) {\n out.add(toRelPath(projectRoot, join(dir, entry.name)));\n if (out.size > MAX_FILES) return out;\n }\n }\n }\n } catch {\n return null;\n }\n return out;\n}\n","import type { LessonsQuery } from './query.js';\nimport { tokenize } from './ranking-text.js';\n\n/**\n * Keyword-trigger matching. Mandatory recall fires on `--file`/`--cmd`, but a\n * `keyword` trigger historically only tested the explicit `--keyword` — so a\n * keyword-only (conceptual) lesson never surfaced unless the agent hand-crafted\n * `--keyword`, the least reliable input. This closes that gap WITHOUT touching\n * the graph: a keyword trigger also matches when its tokens appear as a\n * contiguous run in the file-path + command tokens the recall already carries.\n *\n * Matching is on token boundaries — NOT substring — so \"cat\" cannot fire on\n * \"category\" and a multi-word pattern must appear adjacently. The PATTERN is run\n * through the shared {@link tokenize} (lowercase, split on non-alphanumerics,\n * drop <2-char tokens and stopwords), so a degenerate pattern like \"a\" or \"the\"\n * tokenizes to nothing and never matches. The HAYSTACK is split but NOT filtered,\n * so its stopwords still separate words — \"read only\" must not match the\n * non-adjacent \"read the only\".\n */\n\n/** Lowercase alphanumeric tokens, order-preserving and UNFILTERED (keeps stopwords). */\nfunction splitTokens(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 0);\n}\n\n/** Tokens implied by the current edit/command — the recall's task context. */\nfunction deriveHaystackTokens(query: LessonsQuery): string[] {\n const parts: string[] = [];\n if (query.file !== undefined) parts.push(query.file);\n if (query.command !== undefined) parts.push(query.command);\n return parts.length === 0 ? [] : splitTokens(parts.join(' '));\n}\n\n/** True when `needle` appears as a contiguous run inside `hay`. */\nfunction containsRun(needle: readonly string[], hay: readonly string[]): boolean {\n if (needle.length === 0) return false; // empty needle must never match\n for (let i = 0; i + needle.length <= hay.length; i += 1) {\n let hit = true;\n for (let j = 0; j < needle.length; j += 1) {\n if (hay[i + j] !== needle[j]) {\n hit = false;\n break;\n }\n }\n if (hit) return true;\n }\n return false;\n}\n\nexport function keywordMatches(pattern: string, query: LessonsQuery): boolean {\n // 1. Explicit --keyword: byte-identical to the original substring behavior.\n if (query.keyword !== undefined && query.keyword.toLowerCase().includes(pattern.toLowerCase())) {\n return true;\n }\n // 2. Derived from file + command, on token boundaries.\n return containsRun(tokenize(pattern), deriveHaystackTokens(query));\n}\n","import picomatch from 'picomatch';\nimport type { Lesson, LessonsGraph, Trigger } from './graph-schema.js';\nimport { keywordMatches } from './keyword-match.js';\nimport { getCommandMatcher } from './regex-safety.js';\nimport type { WorkBudget } from './regex-linear/index.js';\n\n/**\n * Query-wide budget for command_pattern matching (NFA state-visits). ONE budget\n * is shared across every trigger in a single recall, so total matching work is\n * bounded regardless of how many near-cap patterns the graph holds — not just\n * per pattern. ~5M state-visits ≈ a few hundred ms worst case; a normal query\n * uses a tiny fraction. When exhausted, remaining command patterns are treated\n * as non-matches (safe degradation, never a false positive).\n */\nconst COMMAND_MATCH_BUDGET = 5_000_000;\n\nexport interface LessonsQuery {\n /** Project-relative path of the file about to be edited. */\n readonly file?: string;\n /** Shell command about to be executed. */\n readonly command?: string;\n /** Free-form text describing the current task. */\n readonly keyword?: string;\n}\n\nexport interface MatchedLesson {\n readonly id: string;\n readonly lesson: Lesson;\n}\n\n/**\n * Recall primitive — returns every active lesson whose triggers match any of\n * the supplied query fields. The query fields combine as OR across triggers:\n * a lesson matches if ANY of its triggers match ANY supplied field.\n * Deprecated and superseded lessons are excluded.\n */\nexport function queryLessons(graph: LessonsGraph, query: LessonsQuery): MatchedLesson[] {\n if (query.file === undefined && query.command === undefined && query.keyword === undefined) {\n return [];\n }\n\n const matchedTriggerIds = collectMatchedTriggerIds(graph, query);\n\n const matched: MatchedLesson[] = [];\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n if (lesson.triggers.some((t) => matchedTriggerIds.has(t))) {\n matched.push({ id, lesson });\n }\n }\n\n matched.sort((a, b) => (a.id < b.id ? -1 : 1));\n return matched;\n}\n\n/** Matched trigger ids split by kind — drives recall telemetry provenance. */\nexport interface MatchedTriggersByKind {\n readonly file_glob: Set<string>;\n readonly command_pattern: Set<string>;\n readonly keyword: Set<string>;\n}\n\n/**\n * Partition the query's matched trigger ids by kind in a single pass. The flat\n * {@link collectMatchedTriggerIds} delegates here so matching logic and the\n * shared command-pattern budget live in exactly one place.\n */\nexport function collectMatchedTriggersByKind(\n graph: LessonsGraph,\n query: LessonsQuery,\n): MatchedTriggersByKind {\n const byKind: MatchedTriggersByKind = {\n file_glob: new Set(),\n command_pattern: new Set(),\n keyword: new Set(),\n };\n // One budget shared across ALL command_pattern triggers in this query.\n const budget: WorkBudget = { remaining: COMMAND_MATCH_BUDGET };\n for (const [id, trigger] of Object.entries(graph.triggers)) {\n if (triggerMatches(trigger, query, budget)) byKind[trigger.kind].add(id);\n }\n return byKind;\n}\n\n/** The set of trigger ids that match the query — shared by recall and ranking. */\nexport function collectMatchedTriggerIds(graph: LessonsGraph, query: LessonsQuery): Set<string> {\n const { file_glob, command_pattern, keyword } = collectMatchedTriggersByKind(graph, query);\n return new Set([...file_glob, ...command_pattern, ...keyword]);\n}\n\nfunction triggerMatches(trigger: Trigger, query: LessonsQuery, budget: WorkBudget): boolean {\n switch (trigger.kind) {\n case 'file_glob':\n if (query.file === undefined) return false;\n return picomatch(trigger.pattern, { dot: true })(query.file);\n case 'command_pattern': {\n if (query.command === undefined) return false;\n // Match via the non-backtracking linear engine — recall must never run a\n // backtracking regex on the hot path (see regex-safety.ts). null = the\n // pattern is unsupported/over-long; treat as a non-match (fail closed).\n // The shared budget bounds total command-matching work query-wide.\n const matcher = getCommandMatcher(trigger.pattern);\n return matcher !== null && matcher.test(query.command, budget);\n }\n case 'keyword':\n // Matches the explicit --keyword (substring) OR the file/command tokens, so\n // keyword-only conceptual lessons surface on mandatory --file/--cmd recall.\n return keywordMatches(trigger.pattern, query);\n }\n}\n","import type { Lesson, LessonsGraph } from './graph-schema.js';\nimport { collectMatchedTriggerIds, type LessonsQuery, type MatchedLesson } from './query.js';\nimport { buildFanout, buildTopicCoherence } from './ranking-signals.js';\nimport { bm25, buildCorpus, queryTerms } from './ranking-text.js';\n\nexport interface RankReason {\n readonly matchedTriggers: string[];\n readonly bm25: number;\n readonly specificity: number;\n readonly topicCoherence: number;\n}\n\nexport interface RankedLesson {\n readonly id: string;\n readonly lesson: Lesson;\n readonly score: number;\n readonly reason: RankReason;\n}\n\nexport interface RankOptions {\n /** Keep at most this many results (after ranking). */\n readonly limit?: number;\n /**\n * Best-effort token budget: keep results while their cumulative estimated\n * rule-token cost fits. The single most-relevant result is ALWAYS returned\n * even if it alone exceeds the budget — an empty recall for a matched query is\n * worse for the agent than one slightly-over-budget rule.\n */\n readonly maxTokens?: number;\n}\n\n/** Default recall cap: a broad trigger match returns the most-relevant few, not the whole topic. */\nexport const DEFAULT_RECALL_LIMIT = 10;\n\n/**\n * Default recall token budget applied by the application APIs (CLI `query`, MCP\n * `lessons_query`, {@link recallLessons}) when the caller does not specify one.\n * Mandatory recall runs before every edit/command, so its payload must stay\n * lean; without a budget a broad match can return ~450+ rule-tokens. `--all`\n * (CLI) bypasses both caps. The top result is always kept (see RankOptions).\n */\nexport const DEFAULT_RECALL_MAX_TOKENS = 400;\n\nconst RRF_K = 60;\n\n/**\n * RRF signal weights. Mandatory recall fires on `--file`/`--cmd`, where the\n * discriminating signal is WHICH trigger matched and how specific it is — rule\n * prose rarely contains a file path, so raw BM25 is the noisiest signal. So\n * specificity dominates, topic coherence (a graph signal) sits in the middle,\n * and rule-text BM25 only breaks ties the structural signals cannot.\n */\nconst SPECIFICITY_WEIGHT = 3;\nconst TOPIC_COHERENCE_WEIGHT = 2;\nconst BM25_WEIGHT = 1;\n\n/**\n * Competition ranking (1,1,3,…): equal values share a rank so a signal that\n * cannot distinguish two lessons contributes equally to both — otherwise an\n * arbitrary id tie-break in one signal would silently cancel a real lead in the\n * other under RRF.\n */\nfunction rankMap(items: { id: string; value: number }[]): Map<string, number> {\n const sorted = [...items].sort((a, b) =>\n b.value !== a.value ? b.value - a.value : a.id < b.id ? -1 : 1,\n );\n const ranks = new Map<string, number>();\n let prevValue: number | null = null;\n let prevRank = 0;\n sorted.forEach((item, i) => {\n const rank = prevValue !== null && item.value === prevValue ? prevRank : i + 1;\n ranks.set(item.id, rank);\n prevValue = item.value;\n prevRank = rank;\n });\n return ranks;\n}\n\n/** Crude rule-token estimate (≈4 chars/token) — shared by recall caps and stats. */\nexport function estTokens(rule: string): number {\n return Math.ceil(rule.length / 4);\n}\n\n/**\n * Rank matched lessons by relevance and apply optional caps. Three lightweight\n * signals are weighted-reciprocal-rank-fused (RRF): trigger specificity (inverse\n * fanout — a discriminating trigger beats a topic-wide one; highest weight),\n * per-query topic coherence (a lesson in the topic that dominates this query's\n * matched set is boosted; middle weight), and BM25 over the rule text (so the\n * lesson whose wording best fits breaks ties the structural signals cannot;\n * lowest weight). Ties break by recency (createdAt) then id. No embeddings, no\n * I/O — pure and sub-millisecond.\n */\nexport function rankLessons(\n graph: LessonsGraph,\n query: LessonsQuery,\n matches: readonly MatchedLesson[],\n options: RankOptions = {},\n): RankedLesson[] {\n if (matches.length === 0) return [];\n\n const terms = queryTerms(query);\n const corpus = buildCorpus(graph);\n const fanout = buildFanout(graph);\n const coherence = buildTopicCoherence(matches);\n const matchedTriggerIds = collectMatchedTriggerIds(graph, query);\n\n const scored = matches.map(({ id, lesson }) => {\n const hitTriggers = lesson.triggers.filter((t) => matchedTriggerIds.has(t));\n let specificity = 0;\n // Each hit trigger belongs to this active, matched lesson, so fanout has it.\n for (const t of hitTriggers) specificity = Math.max(specificity, 1 / fanout.get(t)!);\n return {\n id,\n lesson,\n bm25: bm25(terms, lesson.rule, corpus),\n specificity,\n // `id` is a matched lesson, and buildTopicCoherence keys every matched id.\n topicCoherence: coherence.get(id)!,\n matchedTriggers: hitTriggers,\n };\n });\n\n const bm25Ranks = rankMap(scored.map((s) => ({ id: s.id, value: s.bm25 })));\n const specRanks = rankMap(scored.map((s) => ({ id: s.id, value: s.specificity })));\n const topicRanks = rankMap(scored.map((s) => ({ id: s.id, value: s.topicCoherence })));\n\n const ranked: RankedLesson[] = scored\n .map((s) => ({\n id: s.id,\n lesson: s.lesson,\n score:\n SPECIFICITY_WEIGHT / (RRF_K + specRanks.get(s.id)!) +\n TOPIC_COHERENCE_WEIGHT / (RRF_K + topicRanks.get(s.id)!) +\n BM25_WEIGHT / (RRF_K + bm25Ranks.get(s.id)!),\n reason: {\n matchedTriggers: s.matchedTriggers,\n bm25: s.bm25,\n specificity: s.specificity,\n topicCoherence: s.topicCoherence,\n },\n }))\n .sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n const ca = a.lesson.createdAt;\n const cb = b.lesson.createdAt;\n if (ca !== cb) return ca < cb ? 1 : -1; // newer first\n return a.id < b.id ? -1 : 1;\n });\n\n return applyCaps(ranked, options);\n}\n\nfunction applyCaps(ranked: RankedLesson[], options: RankOptions): RankedLesson[] {\n let out = ranked;\n if (options.limit !== undefined && options.limit >= 0) out = out.slice(0, options.limit);\n if (options.maxTokens !== undefined && out.length > 0) {\n const budgeted: RankedLesson[] = [out[0]!]; // always keep the top result\n let used = estTokens(out[0]!.lesson.rule);\n for (const row of out.slice(1)) {\n const cost = estTokens(row.lesson.rule);\n if (used + cost > options.maxTokens) break;\n used += cost;\n budgeted.push(row);\n }\n out = budgeted;\n }\n return out;\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { lessonsPaths } from './paths.js';\nimport { DEFAULT_RECALL_LIMIT, DEFAULT_RECALL_MAX_TOKENS } from './ranking.js';\n\n/**\n * Optional per-project recall tuning, read from `.agentsmesh/lessons/config.json`:\n *\n * { \"recallLimit\": 5, \"recallMaxTokens\": 250 }\n *\n * Both fields are optional and independently fall back to the built-in defaults.\n * Lowering them keeps mandatory `--file`/`--cmd` recall lean on a large, high-fanout\n * graph (where recall otherwise returns many lessons per call); per-invocation\n * `--top`/`--all`/`--max-tokens` flags still override these.\n *\n * Recall is a BLOCKING hot path, so loading never throws: a missing/malformed\n * file or an invalid field silently uses the default for that field.\n */\n\nexport interface RecallConfig {\n readonly limit: number;\n readonly maxTokens: number;\n}\n\n/** Every tunable field with its default — the shape `init --lessons` writes out. */\nexport interface LessonsConfigFile {\n readonly recallLimit: number;\n readonly recallMaxTokens: number;\n readonly autoPrune: boolean;\n}\n\n/**\n * The full default lessons config, materialized by `init --lessons` so every\n * tunable is discoverable and editable in one place (JSON has no comments). Built\n * from the same constants the readers fall back to, so writing it out is purely a\n * no-op for behaviour — only the file becomes visible. `autoPrune` is `false` to\n * mirror its off-by-default in `auto-prune.ts` (kept a literal here so the recall\n * hot path's config module never imports the prune machinery).\n */\nexport function defaultLessonsConfig(): LessonsConfigFile {\n return {\n recallLimit: DEFAULT_RECALL_LIMIT,\n recallMaxTokens: DEFAULT_RECALL_MAX_TOKENS,\n autoPrune: false,\n };\n}\n\nfunction positiveInt(value: unknown): number | null {\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : null;\n}\n\n/**\n * Diagnose a present-but-broken `config.json` for a user-facing warning, WITHOUT\n * changing the silent hot-path fallback in {@link loadRecallConfig}. Returns a\n * message when the file exists but is unparseable JSON or carries an invalid\n * recall field (so a typo'd `recallLimit` does not silently revert to the default\n * with no signal); null when the file is absent or valid. Callers surface it on\n * stderr — the recall path itself stays non-throwing.\n */\nexport function lessonsConfigWarning(projectRoot: string): string | null {\n const path = lessonsPaths(projectRoot).config;\n if (!existsSync(path)) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(path, 'utf8'));\n } catch {\n return `lessons config.json is not valid JSON — using built-in recall defaults. Fix or delete .agentsmesh/lessons/config.json.`;\n }\n if (typeof parsed !== 'object' || parsed === null) {\n return `lessons config.json is not a JSON object — using built-in recall defaults.`;\n }\n const cfg = parsed as Record<string, unknown>;\n const bad: string[] = [];\n if ('recallLimit' in cfg && positiveInt(cfg.recallLimit) === null) bad.push('recallLimit');\n if ('recallMaxTokens' in cfg && positiveInt(cfg.recallMaxTokens) === null) {\n bad.push('recallMaxTokens');\n }\n if (bad.length > 0) {\n return `lessons config.json has invalid ${bad.join(' and ')} (expected a positive integer) — using the default for ${bad.length === 1 ? 'it' : 'them'}.`;\n }\n return null;\n}\n\nexport function loadRecallConfig(projectRoot: string): RecallConfig {\n const fallback: RecallConfig = {\n limit: DEFAULT_RECALL_LIMIT,\n maxTokens: DEFAULT_RECALL_MAX_TOKENS,\n };\n const path = lessonsPaths(projectRoot).config;\n if (!existsSync(path)) return fallback;\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (typeof parsed !== 'object' || parsed === null) return fallback;\n const cfg = parsed as Record<string, unknown>;\n return {\n limit: positiveInt(cfg.recallLimit) ?? fallback.limit,\n maxTokens: positiveInt(cfg.recallMaxTokens) ?? fallback.maxTokens,\n };\n } catch {\n return fallback;\n }\n}\n","import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport type { MatchedLesson } from './query.js';\nimport { sessionId as envSessionId } from './telemetry.js';\n\n/**\n * Session-scoped recall dedup. Recall is stateless and deterministic, so the\n * same `--file` returns the identical rules every time — N recalls touching one\n * area re-deliver the same ~280 tokens N times. When a session correlator is\n * present (`AGENTSMESH_SESSION_ID` or an explicit `--session`), this suppresses\n * lessons already delivered earlier in the session so each recall carries only\n * what is NEW. Opt-in: with no correlator the recall path is untouched.\n *\n * The per-session set of delivered lesson ids lives in the OS temp dir (not the\n * project tree), so it never dirties `.agentsmesh/` and the OS reclaims it.\n */\n\nconst SEEN_DIR = 'agentsmesh-lessons-seen';\n\nexport interface SessionDedup {\n readonly sessionId: string;\n readonly seen: ReadonlySet<string>;\n readonly path: string;\n}\n\nexport interface OpenDedupOptions {\n /** Explicit session id (CLI `--session`); wins over the environment. */\n readonly explicit?: string;\n /** Force dedup off (CLI `--no-dedup`) even when a correlator is present. */\n readonly disabled?: boolean;\n readonly env?: NodeJS.ProcessEnv;\n}\n\n/**\n * Open the dedup state for the current session, or `null` when dedup is off —\n * no correlator set, or explicitly disabled. `null` is the default, fully\n * stateless path, so existing behavior is unchanged unless a session is named.\n */\nexport function openSessionDedup(options: OpenDedupOptions = {}): SessionDedup | null {\n if (options.disabled === true) return null;\n const id =\n options.explicit !== undefined && options.explicit.trim().length > 0\n ? options.explicit.trim()\n : envSessionId(options.env);\n if (id === undefined) return null;\n const path = seenPath(id);\n return { sessionId: id, seen: loadSeen(path), path };\n}\n\nfunction seenPath(id: string): string {\n const safe = id.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 200);\n return join(tmpdir(), SEEN_DIR, `${safe}.json`);\n}\n\nfunction loadSeen(path: string): Set<string> {\n if (!existsSync(path)) return new Set();\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (!Array.isArray(parsed)) return new Set();\n return new Set(parsed.filter((x): x is string => typeof x === 'string'));\n } catch {\n return new Set();\n }\n}\n\n/**\n * Drop matches already delivered this session BEFORE ranking, so the limit +\n * token budget fill with FRESH lessons rather than wasting slots on repeats.\n */\nexport function filterUnseen(\n dedup: SessionDedup,\n matches: readonly MatchedLesson[],\n): MatchedLesson[] {\n return matches.filter((m) => !dedup.seen.has(m.id));\n}\n\n/**\n * Record the ids actually returned so a later recall this session suppresses\n * them. Best-effort and atomic (temp + rename); a write failure is swallowed —\n * dedup is an optimization and must never break the blocking recall path.\n */\nexport function commitSeen(dedup: SessionDedup, returnedIds: readonly string[]): void {\n if (returnedIds.length === 0) return;\n const union = new Set(dedup.seen);\n for (const id of returnedIds) union.add(id);\n if (union.size === dedup.seen.size) return;\n try {\n mkdirSync(dirname(dedup.path), { recursive: true });\n const tmp = `${dedup.path}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify([...union]), 'utf8');\n renameSync(tmp, dedup.path);\n } catch {\n // Optimization only — never fail recall because the seen cache could not be written.\n }\n}\n","import {\n addLesson,\n type AddLessonInput,\n type AddLessonOptions,\n type AddLessonResult,\n} from './add.js';\nimport { maybeAutoMigrateLessons } from './auto-migrate.js';\nimport { maybeAutoPrune } from './auto-prune.js';\nimport { recordCapture } from './capture-telemetry.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { loadLessonsGraphResilient } from './graph-store.js';\nimport { normalizeRecallFile } from './normalize-query-file.js';\nimport { listProjectFiles } from './project-files.js';\nimport {\n collectMatchedTriggersByKind,\n queryLessons,\n type LessonsQuery,\n type MatchedLesson,\n} from './query.js';\nimport {\n estTokens,\n rankLessons,\n type RankedLesson,\n} from './ranking.js';\nimport { loadRecallConfig } from './recall-config.js';\nimport { commitSeen, filterUnseen, openSessionDedup } from './seen-cache.js';\nimport { appendRecallRecord, isTelemetryEnabled, sessionId } from './telemetry.js';\n\n/**\n * Migration-aware application APIs for the lessons subsystem.\n *\n * The WRITE path migrates automatically: `mutateLessonsGraph` (and everything\n * built on it — `addLesson`, `mergeLessons`, deprecate, strip-markers) runs the\n * legacy→JSON migration before mutating, so even a first raw write can never\n * create an empty `lessons.json` over an unmigrated `index.yaml`. (The migrator\n * and scaffolding use the internal `mutateLessonsGraphLocked` to avoid\n * recursing.)\n *\n * The low-level READ primitives (`tryLoadLessonsGraph`, `loadLessonsGraph`,\n * `queryLessons`) do NOT migrate — a first read through them on a legacy project\n * would see no graph. `recallLessons` closes that: it migrates first, then\n * loads + ranks. `captureLesson` is the symmetric capture entry point. Prefer\n * these application APIs; reach for the read primitives only post-migration.\n */\n\nexport interface RecallOptions {\n /** Max ranked lessons to return. Defaults to {@link DEFAULT_RECALL_LIMIT}. */\n readonly limit?: number;\n /**\n * Cumulative rule-token budget. Defaults to {@link DEFAULT_RECALL_MAX_TOKENS};\n * pass `null` to disable the budget (return up to `limit` results).\n */\n readonly maxTokens?: number | null;\n /**\n * Session correlator for recall dedup. Defaults to `AGENTSMESH_SESSION_ID`;\n * when set, lessons already delivered this session are suppressed.\n */\n readonly sessionId?: string;\n /** Force dedup off even when a session correlator is present. */\n readonly noDedup?: boolean;\n}\n\nexport interface RecallResult {\n /** Relevance-ranked, capped lessons (compact metadata lives on each entry). */\n readonly lessons: RankedLesson[];\n /** How many active lessons matched the query before the caps were applied. */\n readonly totalMatches: number;\n /**\n * True when the canonical graph existed but could not be read (corrupt JSON /\n * schema drift). Recall degrades to empty instead of throwing; callers surface\n * this so a corrupt graph is a visible warning, not silent zero recall.\n */\n readonly corrupt?: boolean;\n /**\n * Set to the on-disk schema version when the graph is newer than this build\n * understands. Recall degrades to empty (like `corrupt`) but callers surface\n * an upgrade hint rather than a \"corrupt\" warning.\n */\n readonly newerVersion?: number;\n /**\n * Count of matched lessons suppressed because they were already delivered\n * earlier in this session (dedup). 0 when dedup is off or nothing repeated.\n */\n readonly suppressed: number;\n}\n\n/**\n * Recall primitive for applications: migrate if needed, then return the active\n * lessons matching `query`, relevance-ranked and capped by limit + token budget.\n */\nexport async function recallLessons(\n projectRoot: string,\n query: LessonsQuery,\n options: RecallOptions = {},\n): Promise<RecallResult> {\n // Recall is a blocking dependency and must never crash: a corrupt LEGACY\n // store (malformed index.yaml) fails migration here, so degrade to whatever\n // graph state exists (usually absent → empty recall) and leave the legacy\n // files intact for an explicit `lessons import-md` to surface the error.\n // WRITE paths keep failing loudly so a fresh graph never strands the legacy.\n try {\n await maybeAutoMigrateLessons(projectRoot);\n } catch {\n // Degrade; see above.\n }\n const load = loadLessonsGraphResilient(projectRoot);\n if (load.status === 'corrupt') {\n return { lessons: [], totalMatches: 0, suppressed: 0, corrupt: true };\n }\n if (load.status === 'newer-version') {\n return { lessons: [], totalMatches: 0, suppressed: 0, newerVersion: load.version };\n }\n if (load.status === 'absent') return { lessons: [], totalMatches: 0, suppressed: 0 };\n const graph = load.graph;\n // Normalize the file path so a project-relative glob matches regardless of the\n // shape the caller passed (absolute / ./-prefixed / backslash).\n const matchQuery: LessonsQuery =\n query.file === undefined\n ? query\n : { ...query, file: normalizeRecallFile(query.file, projectRoot) };\n const matches = queryLessons(graph, matchQuery);\n // Dedup BEFORE ranking so the caps fill with fresh lessons (see seen-cache).\n const dedup = openSessionDedup({ explicit: options.sessionId, disabled: options.noDedup });\n const forRank = dedup === null ? matches : filterUnseen(dedup, matches);\n // Per-project recall tuning is the fallback for unset options; explicit\n // options (and `maxTokens: null` to disable the budget) still win.\n const cfg = loadRecallConfig(projectRoot);\n const lessons = rankLessons(graph, matchQuery, forRank, {\n limit: options.limit ?? cfg.limit,\n maxTokens: options.maxTokens === null ? undefined : (options.maxTokens ?? cfg.maxTokens),\n });\n if (dedup !== null) commitSeen(dedup, lessons.map((l) => l.id));\n // The application/MCP path has no `--all`; recall here is always a mandatory,\n // capped call, so it is never a bypass.\n recordRecallTelemetry(projectRoot, graph, matchQuery, matches, lessons, { bypassed: false });\n return { lessons, totalMatches: matches.length, suppressed: matches.length - forRank.length };\n}\n\n/**\n * Append one telemetry record for this recall — gated, so the hot path computes\n * nothing (no provenance pass, no timestamp, no I/O) in the default-off config.\n *\n * Exported so the CLI `lessons query` handler records identically to this\n * (MCP) path; both query entry points MUST share this single recorder, or\n * shell-driven recall would be invisible to `lessons stats`.\n */\nexport function recordRecallTelemetry(\n projectRoot: string,\n graph: LessonsGraph,\n query: LessonsQuery,\n matches: readonly MatchedLesson[],\n lessons: readonly RankedLesson[],\n options: { readonly bypassed?: boolean } = {},\n): void {\n if (!isTelemetryEnabled()) return;\n const byKind = collectMatchedTriggersByKind(graph, query);\n const countVia = (set: Set<string>): number =>\n matches.filter(({ lesson }) => lesson.triggers.some((t) => set.has(t))).length;\n const session = sessionId();\n appendRecallRecord(projectRoot, {\n ts: new Date().toISOString(),\n hasFile: query.file !== undefined,\n hasCommand: query.command !== undefined,\n hasKeyword: query.keyword !== undefined,\n totalMatches: matches.length,\n returnedCount: lessons.length,\n returnedTokens: lessons.reduce((sum, l) => sum + estTokens(l.lesson.rule), 0),\n truncated: matches.length > lessons.length,\n matchedByKind: {\n file: countVia(byKind.file_glob),\n command: countVia(byKind.command_pattern),\n keyword: countVia(byKind.keyword),\n },\n lessonIds: lessons.map((l) => l.id),\n bypassed: options.bypassed === true,\n ...(session !== undefined ? { session } : {}),\n });\n}\n\n/**\n * Capture primitive for applications: migrate if needed, then add the lesson\n * through the transactional write path. Idempotent on repeat (same rule+topic).\n *\n * Both CLI `lessons add` and MCP `lessons_add` route through here, so capture\n * telemetry is recorded once at this single entry point (mirroring how every\n * recall records through `recallLessons`). Every rejection — a dead trigger, an\n * unknown topic, a write-barrier failure — is recorded as a BLOCKED capture\n * before being rethrown, so `stats` never undercounts blocks.\n */\nexport async function captureLesson(\n projectRoot: string,\n input: AddLessonInput,\n options: AddLessonOptions = {},\n): Promise<AddLessonResult> {\n await maybeAutoMigrateLessons(projectRoot);\n const triggerKinds = {\n file: input.triggers.files?.length ?? 0,\n command: input.triggers.commands?.length ?? 0,\n keyword: input.triggers.keywords?.length ?? 0,\n };\n // Supply the working-tree file list so capture can warn on a dead glob (a typo\n // or stale path) at the best moment to fix it. null (no walk possible) → the\n // DEAD_GLOB check is skipped, never a false positive. Caller-provided\n // knownPaths (e.g. legacy merge) still wins.\n const knownPaths = options.knownPaths ?? listProjectFiles(projectRoot) ?? undefined;\n try {\n const result = await addLesson(projectRoot, input, { ...options, knownPaths });\n recordCapture(projectRoot, triggerKinds, result);\n // Opt-in auto-prune: GC structural cruft right after the graph changed,\n // reusing the working-tree walk we already did. No-op unless config enables\n // it; never throws, so it can't break a successful capture.\n const autoPruned = await maybeAutoPrune(projectRoot, knownPaths);\n return autoPruned === null ? result : { ...result, autoPruned };\n } catch (err) {\n recordCapture(projectRoot, triggerKinds, null);\n throw err;\n }\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport { mutateLessonsGraph } from './mutate.js';\n\nexport interface MergeLessonsResult {\n readonly loserId: string;\n readonly keeperId: string;\n}\n\nexport interface MergeLessonsOptions {\n readonly retries?: number;\n}\n\n/**\n * Fold a duplicate lesson (`loserId`) into its canonical twin (`keeperId`):\n * union the loser's triggers, topics, and evidence onto the keeper, then mark\n * the loser `superseded` with `supersededBy` pointing at the keeper.\n *\n * Unioning reachability BEFORE superseding is the whole point — a raw\n * supersede would silently drop the keeper out of recall for queries that only\n * matched the loser's (often different-topic) triggers.\n */\nexport async function mergeLessons(\n projectRoot: string,\n loserId: string,\n keeperId: string,\n options: MergeLessonsOptions = {},\n): Promise<MergeLessonsResult> {\n return mutateLessonsGraph(projectRoot, (graph) => mergeInto(graph, loserId, keeperId), {\n retries: options.retries,\n });\n}\n\nfunction mergeInto(graph: LessonsGraph, loserId: string, keeperId: string): MergeLessonsResult {\n if (loserId === keeperId) {\n throw new Error(`mergeLessons: cannot merge lesson \"${loserId}\" into itself.`);\n }\n const loser = graph.lessons[loserId];\n if (loser === undefined) throw new Error(`mergeLessons: unknown lesson \"${loserId}\".`);\n const keeper = graph.lessons[keeperId];\n if (keeper === undefined) throw new Error(`mergeLessons: unknown lesson \"${keeperId}\".`);\n\n if (keeper.status !== 'active') {\n throw new Error(`mergeLessons: keeper \"${keeperId}\" is not active (status: ${keeper.status}).`);\n }\n if (loser.status !== 'active') {\n throw new Error(\n `mergeLessons: loser \"${loserId}\" is already ${loser.status}; nothing to merge.`,\n );\n }\n\n graph.lessons[keeperId] = {\n ...keeper,\n triggers: union(keeper.triggers, loser.triggers),\n topics: union(keeper.topics, loser.topics),\n evidence: union(keeper.evidence, loser.evidence),\n };\n graph.lessons[loserId] = { ...loser, status: 'superseded', supersededBy: keeperId };\n return { loserId, keeperId };\n}\n\nfunction union(base: readonly string[], extra: readonly string[]): string[] {\n const out = [...base];\n for (const item of extra) {\n if (!out.includes(item)) out.push(item);\n }\n return out;\n}\n\nexport type { LessonsGraph };\n","import { maybeAutoMigrateLessons } from './auto-migrate.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { tryLoadLessonsGraph } from './graph-store.js';\nimport { mutateLessonsGraph } from './mutate.js';\n\nexport interface StripMarkersReport {\n readonly changedIds: string[];\n readonly changedCount: number;\n}\n\nexport interface StripMarkersOptions {\n readonly dryRun?: boolean;\n}\n\n/** One or more `L\\d+` line refs, optionally comma-separated: `L92`, `L92, L163`. */\nconst LINE_REFS = String.raw`L\\d+(?:\\s*,\\s*L\\d+)*`;\n\n/**\n * Line-ref markers. Each carries a leading `\\s*` so it absorbs the single space\n * that precedes it; removing the whole match (replacing with the empty string)\n * leaves surrounding prose spacing intact, whether the marker sits at the end\n * of a clause (\"Do X. See L1\") or mid-sentence (\"First clause (L1, L2), then\").\n */\nconst LINE_REF_PATTERNS: readonly RegExp[] = [\n new RegExp(String.raw`\\s*\\bSee\\s+${LINE_REFS}\\.?`, 'g'), // \" See L128.\" / \" See L140, L149\"\n new RegExp(String.raw`\\s*\\((?:${LINE_REFS})\\)\\.?`, 'g'), // \" (L174)\" / \" (L92, L163)\"\n new RegExp(String.raw`\\s*\\[(?:${LINE_REFS})\\]\\.?`, 'g'), // \" [L161, L208]\"\n];\n\n/**\n * The \"(also relevant …)\" cross-reference phrase. Replaced with a single space\n * (not empty) so a mid-sentence occurrence does not glue its neighbours\n * together; a leading/trailing occurrence is cleaned up by the final trim.\n */\nconst ALSO_RELEVANT_PATTERN = /\\s*\\(also relevant[^)]*\\)\\s*/g;\n\n/**\n * Strip dead legacy provenance markers from a lesson's prose. The migration\n * from the line-numbered Markdown store left inline `See L\\d+`, `(L\\d+)`,\n * `[L\\d+]`, and \"(also relevant …)\" pointers that no longer resolve to\n * anything. Real provenance lives in the `evidence` array, not the rule text.\n *\n * Strictly conservative: ONLY the four marker shapes are touched. Legitimate\n * parentheticals like `(CWE-78)`, ellipses inside code spans, block-comment\n * fences, and shell punctuation (`exit 1 ;;`) are left byte-for-byte intact.\n * Idempotent.\n */\nexport function stripLegacyMarkers(rule: string): string {\n let out = rule;\n for (const pattern of LINE_REF_PATTERNS) out = out.replace(pattern, '');\n out = out.replace(ALSO_RELEVANT_PATTERN, ' ');\n return out.trim();\n}\n\n/** Strip markers from every lesson in `graph` in place; returns changed ids (sorted). */\nfunction applyStrip(graph: LessonsGraph): string[] {\n const changedIds: string[] = [];\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n const stripped = stripLegacyMarkers(lesson.rule);\n // Never blank a rule: if a rule were entirely markers, keep the original\n // (the schema forbids empty rules, and a blank rule carries no knowledge).\n if (stripped === lesson.rule || stripped.length === 0) continue;\n changedIds.push(id);\n graph.lessons[id] = { ...lesson, rule: stripped };\n }\n return changedIds.sort();\n}\n\n/**\n * Apply {@link stripLegacyMarkers} to every lesson. With `dryRun`, computes the\n * change set without persisting; otherwise writes through the transactional\n * path (locked + validated + atomic). A legacy-only store is migrated first (the\n * universal first-access upgrade) so its lessons are stripped rather than\n * silently ignored. No-op (and no file creation) when neither graph nor legacy\n * store exists.\n */\nexport async function stripMarkersInGraph(\n projectRoot: string,\n options: StripMarkersOptions = {},\n): Promise<StripMarkersReport> {\n // Migrate a legacy-only store first; otherwise tryLoadLessonsGraph returns null\n // and a real legacy store would be silently skipped.\n await maybeAutoMigrateLessons(projectRoot);\n const existing = tryLoadLessonsGraph(projectRoot);\n if (existing === null) return { changedIds: [], changedCount: 0 };\n\n if (options.dryRun === true) {\n const changedIds = applyStrip(existing); // mutates the throwaway in-memory copy only\n return { changedIds, changedCount: changedIds.length };\n }\n\n let changedIds: string[] = [];\n await mutateLessonsGraph(projectRoot, (graph) => {\n changedIds = applyStrip(graph);\n });\n return { changedIds, changedCount: changedIds.length };\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parseDocument, YAMLMap, YAMLSeq } from 'yaml';\n\n/**\n * Auto-wire hook-mode recall: inject a `PostToolUse` hook that runs\n * `agentsmesh lessons hook` into canonical `.agentsmesh/hooks.yaml`, so `generate`\n * projects it to every hook-capable target and recall becomes deterministic there\n * (no extra model turn, no compliance dependence). Targets without hook support\n * have no hooks generator, so they simply keep relying on the always-on lessons\n * paragraph in their root instruction — the universal fallback.\n *\n * Idempotent by COMMAND value (re-running scaffold never duplicates the entry),\n * and edited via the YAML Document API so the file's `# yaml-language-server`\n * schema directive and example comments survive — a parse()→stringify() round-trip\n * would silently drop them.\n *\n * Only injects into an EXISTING `hooks.yaml` — it never force-creates one, so a\n * project that does not use hooks is left untouched (and `init` always scaffolds\n * `hooks.yaml` before this runs, so the `init --lessons` flow is covered).\n */\n\nexport const RECALL_HOOK_COMMAND = 'agentsmesh lessons hook';\nconst RECALL_HOOK_MATCHER = 'Edit|Write|Bash';\n\n/** Returns true when the hook was added; false when already present or no hooks.yaml. */\nexport function injectRecallHook(projectRoot: string): boolean {\n const path = join(projectRoot, '.agentsmesh', 'hooks.yaml');\n if (!existsSync(path)) return false;\n\n // Document API (not parse→stringify) so the schema directive + comments survive.\n const doc = parseDocument(readFileSync(path, 'utf8'));\n const existing = doc.get('PostToolUse');\n const post = existing instanceof YAMLSeq ? existing : new YAMLSeq();\n const present = post.items.some(\n (item) => item instanceof YAMLMap && item.get('command') === RECALL_HOOK_COMMAND,\n );\n if (present) return false;\n\n post.add(\n doc.createNode({ matcher: RECALL_HOOK_MATCHER, type: 'command', command: RECALL_HOOK_COMMAND }),\n );\n doc.set('PostToolUse', post);\n writeFileSync(path, String(doc), 'utf8');\n return true;\n}\n","/**\n * Text-encoding helpers for atomic writes: line-ending normalization,\n * UTF-8 BOM constant, and executable-mode inference for shell scripts.\n *\n * Separated from `fs.ts` to keep that module under the project's\n * 200-line file budget (CLAUDE.md).\n */\nimport { basename, extname } from 'node:path';\n\nexport const UTF8_BOM = '';\n\n/**\n * Text-like extensions whose payload must use LF line endings on disk so\n * generated artifacts are byte-stable across Windows/Linux/macOS hosts.\n * Anything outside this set is treated as opaque.\n */\nconst TEXT_EXTENSIONS = new Set<string>([\n '.md',\n '.mdc',\n '.mdx',\n '.markdown',\n '.txt',\n '.json',\n '.jsonc',\n '.yaml',\n '.yml',\n '.toml',\n '.ini',\n '.sh',\n '.bash',\n '.zsh',\n '.ps1',\n '.js',\n '.mjs',\n '.cjs',\n '.ts',\n '.tsx',\n '.html',\n '.css',\n]);\n\n/** Dotfile basenames (no extension) that contain text and should be LF-normalized. */\nconst TEXT_DOTFILES = new Set<string>([\n '.gitignore',\n '.cursorignore',\n '.cursorindexingignore',\n '.aiignore',\n '.agentignore',\n '.clineignore',\n '.geminiignore',\n '.codeiumignore',\n '.continueignore',\n '.copilotignore',\n '.windsurfignore',\n '.junieignore',\n '.kiroignore',\n '.rooignore',\n '.antigravityignore',\n]);\n\nexport function shouldNormalizeLineEndings(path: string): boolean {\n const ext = extname(path).toLowerCase();\n if (ext.length > 0) return TEXT_EXTENSIONS.has(ext);\n const base = basename(path).toLowerCase();\n return TEXT_DOTFILES.has(base);\n}\n\nexport function normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n?/g, '\\n');\n}\n\n/** Shell-script extensions whose generated files must carry an executable bit. */\nconst EXECUTABLE_SCRIPT_EXTENSIONS = new Set<string>(['.sh', '.bash', '.zsh']);\n\n/**\n * Resolve the POSIX mode for a generated path. Returns `0o755` for shell\n * scripts so hooks emitted to disk are exec'able by the harness; returns\n * `undefined` for everything else, letting Node fall back to the default\n * write mode (umask-applied 0o644).\n */\nexport function executableModeFor(path: string): number | undefined {\n return EXECUTABLE_SCRIPT_EXTENSIONS.has(extname(path).toLowerCase()) ? 0o755 : undefined;\n}\n","/**\n * File system helpers for agentsmesh: atomic write/read/exists/mkdirp.\n * Traversal helpers live in `fs-traverse.ts`; text-encoding helpers in\n * `fs-text-encoding.ts`. Re-exports keep the public API stable.\n */\n\nimport {\n readFile,\n writeFile,\n access,\n chmod,\n mkdir,\n rename,\n rm,\n unlink,\n lstat,\n} from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { constants } from 'node:fs';\nimport { FileSystemError } from '../../core/errors.js';\nimport {\n UTF8_BOM,\n executableModeFor,\n normalizeLineEndings,\n shouldNormalizeLineEndings,\n} from './fs-text-encoding.js';\n\nexport {\n copyDir,\n ensureCacheSymlink,\n readDirRecursive,\n readDirRecursiveNoSymlinks,\n} from './fs-traverse.js';\nexport { executableModeFor } from './fs-text-encoding.js';\nexport { renameWithRetry, type RenameRetryOptions } from './rename-retry.js';\n\ninterface ErrnoLike {\n code?: string;\n message: string;\n}\n\n/**\n * Read file as utf-8 string. Strips BOM. Returns null on ENOENT.\n * @param path - Absolute or relative file path\n * @returns File content or null if not found\n */\nexport async function readFileSafe(path: string): Promise<string | null> {\n try {\n const data = await readFile(path, 'utf-8');\n return data.startsWith(UTF8_BOM) ? data.slice(UTF8_BOM.length) : data;\n } catch (err) {\n const e = err as ErrnoLike;\n if (e.code === 'ENOENT') return null;\n throw new FileSystemError(\n path,\n `Failed to read ${path}: ${e.message}. Ensure the file exists and is readable.`,\n { cause: err, errnoCode: e.code },\n );\n }\n}\n\n/**\n * Write content atomically (write to .tmp, then rename).\n * Creates parent directories.\n *\n * Symlink safety: refuses to follow a pre-existing symlink at `path`. Without\n * this guard, an attacker with write access to the parent directory could swap\n * `path` for a symlink between the lstat check and the rename, redirecting the\n * write to an arbitrary destination (e.g. `~/.ssh/authorized_keys`). On detect,\n * the existing symlink is unlinked so the new file lands at the intended path.\n *\n * @param path - Target file path\n * @param content - Content to write\n * @param options - Optional `mode` (POSIX permission bits). When omitted, the\n * mode is inferred from the path extension via `executableModeFor`; passing\n * an explicit value overrides that inference.\n */\nexport async function writeFileAtomic(\n path: string,\n content: string,\n options?: { mode?: number },\n): Promise<void> {\n const dir = dirname(path);\n await mkdir(dir, { recursive: true });\n try {\n const info = await lstat(path);\n if (info.isDirectory()) {\n throw new FileSystemError(\n path,\n `Failed to write ${path}: target exists and is a directory. Remove it or choose a different path.`,\n { errnoCode: 'EISDIR' },\n );\n }\n if (info.isSymbolicLink()) {\n // Drop the symlink so the rename below lands at `path` itself, not at the\n // link target. Closes a TOCTOU window where a symlink could be swapped in\n // between guard and rename to redirect writes outside the tree.\n await unlink(path).catch((e: unknown) => {\n if ((e as ErrnoLike).code !== 'ENOENT') throw e;\n });\n }\n } catch (err) {\n if (err instanceof FileSystemError) throw err;\n const e = err as ErrnoLike;\n if (e.code !== 'ENOENT') throw err;\n }\n const tmpPath = `${path}.tmp`;\n const payload = shouldNormalizeLineEndings(path) ? normalizeLineEndings(content) : content;\n const mode = options?.mode ?? executableModeFor(path);\n try {\n try {\n const tmpInfo = await lstat(tmpPath);\n if (tmpInfo.isSymbolicLink()) {\n await unlink(tmpPath);\n }\n } catch (tmpErr) {\n if ((tmpErr as ErrnoLike).code !== 'ENOENT') throw tmpErr;\n }\n const writeOpts: NonNullable<Parameters<typeof writeFile>[2]> = {\n encoding: 'utf-8',\n flag: 'w',\n };\n if (mode !== undefined) (writeOpts as { mode?: number }).mode = mode;\n await writeFile(tmpPath, payload, writeOpts);\n await rename(tmpPath, path);\n if (mode !== undefined) {\n // `writeFile`'s mode only applies on initial create; if tmp already\n // existed (or umask masked some bits) we'd silently drop the executable\n // bit. chmod after rename guarantees the final inode carries the mode.\n await chmod(path, mode);\n }\n } catch (err) {\n await rm(tmpPath, { force: true }).catch(() => {});\n const e = err as ErrnoLike;\n throw new FileSystemError(\n path,\n `Failed to write ${path}: ${e.message}. Check permissions and disk space.`,\n { cause: err, errnoCode: e.code },\n );\n }\n}\n\n/** Check if path exists. */\nexport async function exists(path: string): Promise<boolean> {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Create directory recursively. No-op if already exists. */\nexport async function mkdirp(path: string): Promise<void> {\n await mkdir(path, { recursive: true });\n}\n","import { join } from 'node:path';\nimport { readFileSafe, writeFileAtomic } from './fs.js';\n\n/**\n * Append entries to a project's `.gitignore` unless an existing line already\n * covers them. Returns true when the file was modified, false when every entry\n * was already present (or covered). Idempotent: safe to call on each re-run.\n *\n * Coverage rules: an existing line covers a candidate when it is the same\n * string (after trim) or a broader pattern that ignores the candidate's parent\n * directory (e.g. `.agentsmesh/` covers `.agentsmesh/lessons/recall-log.jsonl`).\n * This keeps redundant child entries out when users already gitignore the whole\n * canonical tree. Comment and blank lines are ignored when matching.\n */\nexport async function ensureGitignoreEntries(\n projectRoot: string,\n entries: readonly string[],\n): Promise<boolean> {\n const gitignorePath = join(projectRoot, '.gitignore');\n const current = (await readFileSafe(gitignorePath)) ?? '';\n const existing = new Set(\n current\n .split('\\n')\n .map((s) => s.trim())\n .filter((s) => s.length > 0 && !s.startsWith('#')),\n );\n const toAdd = entries.filter((e) => !isCoveredByExisting(e, existing));\n if (toAdd.length === 0) return false;\n const suffix = current.endsWith('\\n') || current === '' ? '' : '\\n';\n await writeFileAtomic(gitignorePath, current + suffix + toAdd.join('\\n') + '\\n');\n return true;\n}\n\n/**\n * True when `existing` already ignores `candidate` — either the exact line or a\n * broader ancestor-directory pattern (`.agentsmesh`, `.agentsmesh/`, or\n * `.agentsmesh/**`).\n */\nfunction isCoveredByExisting(candidate: string, existing: ReadonlySet<string>): boolean {\n if (existing.has(candidate)) return true;\n let parent = candidate.replace(/\\/$/, '');\n while (parent.includes('/')) {\n parent = parent.slice(0, parent.lastIndexOf('/'));\n if (parent === '') break;\n if (existing.has(parent) || existing.has(`${parent}/`) || existing.has(`${parent}/**`)) {\n return true;\n }\n }\n return false;\n}\n","import { basename, join } from 'node:path';\nimport type { CanonicalRule } from '../../core/types.js';\n\nexport const ROOT_CONTRACT_START = '<!-- agentsmesh:root-generation-contract:start -->';\nexport const ROOT_CONTRACT_END = '<!-- agentsmesh:root-generation-contract:end -->';\nexport const LESSONS_CONTRACT_START = '<!-- agentsmesh:lessons-contract:start -->';\nexport const LESSONS_CONTRACT_END = '<!-- agentsmesh:lessons-contract:end -->';\nexport const EMBEDDED_RULES_START = '<!-- agentsmesh:embedded-rules:start -->';\nexport const EMBEDDED_RULES_END = '<!-- agentsmesh:embedded-rules:end -->';\nexport const EMBEDDED_RULE_END = '<!-- agentsmesh:embedded-rule:end -->';\n\nconst EMBEDDED_RULE_START_PREFIX = '<!-- agentsmesh:embedded-rule:start ';\nconst EMBEDDED_RULE_START_SUFFIX = ' -->';\n\ninterface EmbeddedRuleMarker {\n source: string;\n description: string;\n globs: string[];\n targets: string[];\n}\n\nexport interface ExtractedEmbeddedRule {\n source: string;\n description: string;\n globs: string[];\n targets: string[];\n body: string;\n}\n\nexport interface ExtractedEmbeddedRules {\n rootContent: string;\n rules: ExtractedEmbeddedRule[];\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction managedBlockPattern(start: string, end: string): RegExp {\n return new RegExp(`${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}`, 'g');\n}\n\nexport function replaceManagedBlock(\n content: string,\n start: string,\n end: string,\n block: string,\n): string {\n const pattern = managedBlockPattern(start, end);\n if (pattern.test(content)) {\n return content.replace(pattern, block).trim();\n }\n const trimmed = content.trim();\n return trimmed ? `${trimmed}\\n\\n${block}` : block;\n}\n\nexport function stripManagedBlock(content: string, start: string, end: string): string {\n return content.replace(managedBlockPattern(start, end), '').trim();\n}\n\n/**\n * Split a leading `---…---` frontmatter block from the body without parsing the\n * YAML, so the prefix can be re-emitted byte-for-byte. Returns an empty prefix\n * when there is no frontmatter.\n */\nfunction splitFrontmatterPrefix(content: string): { prefix: string; body: string } {\n if (content.indexOf('---') !== 0) return { prefix: '', body: content.trim() };\n const close = content.indexOf('---', 3);\n if (close === -1) return { prefix: '', body: content.trim() };\n return { prefix: content.slice(0, close + 3), body: content.slice(close + 3).trim() };\n}\n\n/**\n * Place `block` at the top of the document body, keeping any leading\n * frontmatter first. Used to inject the generation-contract and lessons blocks\n * at the beginning of a target's primary root instruction rather than the end.\n */\nexport function insertAtBodyTop(content: string, block: string): string {\n const { prefix, body } = splitFrontmatterPrefix(content);\n const placed = body ? `${block}\\n\\n${body}` : block;\n return prefix ? `${prefix}\\n\\n${placed}` : placed;\n}\n\nfunction ruleSource(source: string): string {\n const normalized = source.replace(/\\\\/g, '/');\n const meshIndex = normalized.lastIndexOf('.agentsmesh/');\n if (meshIndex >= 0) return normalized.slice(meshIndex + '.agentsmesh/'.length);\n if (normalized.startsWith('rules/')) return normalized;\n return join('rules', basename(normalized)).replace(/\\\\/g, '/');\n}\n\nfunction markerForRule(rule: CanonicalRule): EmbeddedRuleMarker {\n return {\n source: ruleSource(rule.source),\n description: rule.description,\n globs: rule.globs,\n targets: rule.targets,\n };\n}\n\nfunction embeddedRuleStart(rule: CanonicalRule): string {\n return `${EMBEDDED_RULE_START_PREFIX}${JSON.stringify(markerForRule(rule))}${EMBEDDED_RULE_START_SUFFIX}`;\n}\n\nfunction renderRule(rule: CanonicalRule): string {\n const parts = [embeddedRuleStart(rule)];\n if (rule.description.trim()) {\n parts.push(`## ${rule.description.trim()}`, '');\n }\n parts.push(rule.body.trim(), EMBEDDED_RULE_END);\n return parts.filter((part) => part.length > 0).join('\\n');\n}\n\nexport function renderEmbeddedRulesBlock(rules: readonly CanonicalRule[]): string {\n if (rules.length === 0) return '';\n return [EMBEDDED_RULES_START, ...rules.map(renderRule), EMBEDDED_RULES_END].join('\\n');\n}\n\nexport function appendEmbeddedRulesBlock(content: string, rules: readonly CanonicalRule[]): string {\n const block = renderEmbeddedRulesBlock(rules);\n const withoutExisting = stripManagedBlock(content, EMBEDDED_RULES_START, EMBEDDED_RULES_END);\n if (!block) return withoutExisting;\n return withoutExisting ? `${withoutExisting}\\n\\n${block}` : block;\n}\n\nfunction toStringArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((entry): entry is string => typeof entry === 'string')\n : [];\n}\n\nfunction parseMarker(value: string): EmbeddedRuleMarker | null {\n try {\n const parsed: unknown = JSON.parse(value);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;\n const record = parsed as Record<string, unknown>;\n if (typeof record.source !== 'string' || !record.source.startsWith('rules/')) return null;\n return {\n source: record.source,\n description: typeof record.description === 'string' ? record.description : '',\n globs: toStringArray(record.globs),\n targets: toStringArray(record.targets),\n };\n } catch {\n return null;\n }\n}\n\nfunction stripGeneratedHeading(body: string, description: string): string {\n const trimmed = body.trim();\n if (!description.trim()) return trimmed;\n const heading = `## ${description.trim()}`;\n return trimmed.startsWith(heading) ? trimmed.slice(heading.length).trim() : trimmed;\n}\n\nexport function extractEmbeddedRules(content: string): ExtractedEmbeddedRules {\n const rules: ExtractedEmbeddedRule[] = [];\n const outerPattern = managedBlockPattern(EMBEDDED_RULES_START, EMBEDDED_RULES_END);\n const rootContent = content.replace(outerPattern, (block) => {\n const inner = block.replace(EMBEDDED_RULES_START, '').replace(EMBEDDED_RULES_END, '').trim();\n const entryPattern = new RegExp(\n `${escapeRegExp(EMBEDDED_RULE_START_PREFIX)}([\\\\s\\\\S]*?)${escapeRegExp(EMBEDDED_RULE_START_SUFFIX)}([\\\\s\\\\S]*?)${escapeRegExp(EMBEDDED_RULE_END)}`,\n 'g',\n );\n for (const match of inner.matchAll(entryPattern)) {\n const markerText = match[1];\n const body = match[2];\n if (markerText === undefined || body === undefined) continue;\n const marker = parseMarker(markerText);\n if (!marker) continue;\n rules.push({\n ...marker,\n body: stripGeneratedHeading(body, marker.description),\n });\n }\n return '';\n });\n return { rootContent: rootContent.trim(), rules };\n}\n","import { LESSONS_PROCEDURAL_RULE } from '../../lessons/paths.js';\nimport {\n insertAtBodyTop,\n LESSONS_CONTRACT_END,\n LESSONS_CONTRACT_START,\n stripManagedBlock,\n} from './managed-blocks.js';\n\n/**\n * The lessons recall/capture ritual, wrapped in managed-block sentinels.\n *\n * Unlike the generation contract, this block IS canonical content: `init\n * --lessons` writes it into `.agentsmesh/rules/_root.md` (see `scaffoldLessons`),\n * so it reaches every target through ordinary canonical rule generation — even\n * rules-directory targets the generation-contract decorator skips. The sentinels\n * keep the block an identifiable unit so round-trip is byte-stable and wording\n * updates propagate from the `LESSONS_PROCEDURAL_RULE` constant the next time\n * scaffold runs.\n */\nexport const LESSONS_PARAGRAPH_BLOCK = `${LESSONS_CONTRACT_START}\n${LESSONS_PROCEDURAL_RULE}\n${LESSONS_CONTRACT_END}`;\n\n/**\n * Place the lessons ritual at the TOP of the document body, after any leading\n * frontmatter (so `_root.md`'s `---…---` stays first). Strips any prior block\n * first, so an existing block appended at the end migrates to the top on the\n * next scaffold.\n */\nexport function appendLessonsParagraph(content: string): string {\n const withoutPrior = stripLessonsParagraph(content);\n return insertAtBodyTop(withoutPrior, LESSONS_PARAGRAPH_BLOCK);\n}\n\nexport function stripLessonsParagraph(content: string): string {\n const withoutBlock = stripManagedBlock(content, LESSONS_CONTRACT_START, LESSONS_CONTRACT_END);\n return stripRawProceduralRule(withoutBlock).trim();\n}\n\n/**\n * Defensive strip of a SENTINEL-LESS copy of the current procedural rule, so a\n * hand-pasted or merge-mangled raw paragraph de-duplicates on the next scaffold\n * instead of leaving a second copy beside the managed block. The lessons feature\n * is unreleased, so there is no prior-wording migration ladder to carry — only\n * the current wording is recognised.\n */\nfunction stripRawProceduralRule(content: string): string {\n return content\n .replace(`\\n\\n${LESSONS_PROCEDURAL_RULE}`, '')\n .replace(LESSONS_PROCEDURAL_RULE, '');\n}\n","// Frontmatter parsing\n\nimport { parse as yamlParse, stringify as yamlStringify } from 'yaml';\n\n/**\n * Parse YAML frontmatter and body from markdown/MDC content.\n * @param content - Raw content with optional --- delimited frontmatter\n * @returns Parsed frontmatter object and trimmed body\n */\nexport function parseFrontmatter(content: string): {\n frontmatter: Record<string, unknown>;\n body: string;\n} {\n const open = content.indexOf('---');\n if (open !== 0) {\n return { frontmatter: {}, body: content.trim() };\n }\n const close = content.indexOf('---', 3);\n if (close === -1) {\n return { frontmatter: {}, body: content.trim() };\n }\n const yamlStr = content.slice(3, close).trim();\n const body = content.slice(close + 3).trim();\n const frontmatter = yamlStr === '' ? {} : ((yamlParse(yamlStr) as Record<string, unknown>) ?? {});\n return { frontmatter, body };\n}\n\nexport type FrontmatterParseResult =\n | { ok: true; value: ReturnType<typeof parseFrontmatter> }\n | { ok: false; error: Error; bodyFallback: string };\n\n/**\n * Split frontmatter block from body without parsing the YAML. Used by the\n * lenient path so a YAML-parse failure can still return a clean body.\n */\nfunction extractBody(content: string): string {\n if (content.indexOf('---') !== 0) return content.trim();\n const close = content.indexOf('---', 3);\n if (close === -1) return content.trim();\n return content.slice(close + 3).trim();\n}\n\n/**\n * Lenient frontmatter parser. Returns a result object instead of throwing.\n * On failure, `bodyFallback` carries the markdown body after the closing `---`\n * so callers can still proceed with body-only content if they choose.\n */\nexport function tryParseFrontmatter(content: string, filePath: string): FrontmatterParseResult {\n try {\n return { ok: true, value: parseFrontmatter(content) };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const wrapped = new Error(`Failed to parse frontmatter in ${filePath}: ${message}`, {\n cause: err,\n });\n return { ok: false, error: wrapped, bodyFallback: extractBody(content) };\n }\n}\n\n/**\n * Parse frontmatter for a file, attributing errors to the path.\n *\n * Default (no `onError`): throws on YAML parse failure — the strict mode used\n * by `generate`/`lint`/`check` for user-authored canonical content.\n *\n * With `onError`: swallows the parse error, invokes the callback, and returns\n * an empty-frontmatter result so the caller can continue with the body. Used\n * by the install path to skip individual broken third-party files instead of\n * aborting the whole run.\n */\nexport function parseFrontmatterForPath(\n content: string,\n filePath: string,\n onError?: (err: Error, filePath: string) => void,\n): ReturnType<typeof parseFrontmatter> {\n const result = tryParseFrontmatter(content, filePath);\n if (result.ok) return result.value;\n if (onError) {\n onError(result.error, filePath);\n return { frontmatter: {}, body: result.bodyFallback };\n }\n throw result.error;\n}\n\n/**\n * Parse-or-skip helper shared by every canonical entity parser. Centralises\n * the install-vs-strict branching so the parsers stay declarative.\n *\n * - Strict (no `onParseError`): re-throws the wrapped error verbatim, matching\n * the long-standing `parseFrontmatterForPath` contract.\n * - Lenient (`onParseError` provided): invokes the callback and returns\n * `null`, signalling to the caller that this file should be skipped.\n */\nexport function parseOrSkipFrontmatter(\n content: string,\n filePath: string,\n onParseError: ((err: Error, filePath: string) => void) | undefined,\n): ReturnType<typeof parseFrontmatter> | null {\n const result = tryParseFrontmatter(content, filePath);\n if (result.ok) return result.value;\n if (onParseError) {\n onParseError(result.error, filePath);\n return null;\n }\n throw result.error;\n}\n\n/**\n * Serialize frontmatter and body back to string.\n * @param frontmatter - Key-value pairs for YAML\n * @param body - Markdown body content\n * @returns Full content with --- delimiters when frontmatter has keys\n */\nexport function serializeFrontmatter(frontmatter: Record<string, unknown>, body: string): string {\n const keys = Object.keys(frontmatter);\n if (keys.length === 0) return body;\n const yamlStr = yamlStringify(frontmatter, { lineWidth: 0 }).trimEnd();\n return `---\\n${yamlStr}\\n---\\n\\n${body}`;\n}\n","import { serializeFrontmatter } from '../utils/text/markdown.js';\n\n/**\n * Tier 2 of the lessons contract: the on-demand operating manual.\n *\n * The always-on trigger lives in the root instruction (`LESSONS_PROCEDURAL_RULE`,\n * injected into `.agentsmesh/rules/_root.md`). That block is deliberately minimal\n * — it carries only the binding essentials. This skill holds the expansive how-to\n * (full command set, topic workflow, trigger-flag mechanics, the complete\n * rejected-excuses enumeration, the MCP fallback) so the manual can grow without\n * bloating every target's always-on context.\n *\n * Borrowed from the superpowers pattern (minimal always-on bootstrap + a\n * progressive-disclosure skill manual), but realized with agentsmesh's NATIVE\n * primitives: the trigger rides canonical rules (native on every target) and the\n * manual rides a canonical skill (native on every skill-supporting target),\n * rather than a SessionStart hook (not a canonical event; unsupported on most\n * targets). A target without skills still gets the trigger — graceful fallback.\n */\nexport const LESSONS_SKILL_NAME = 'lessons';\n\nexport const LESSONS_SKILL_DESCRIPTION =\n 'Full operating manual for the agentsmesh lessons system (recall + capture). ' +\n 'Consult when running any `agentsmesh lessons` subcommand (query, add, topics, ' +\n 'show, deprecate, merge, untrigger, strip-markers, journal, validate, stats, ' +\n 'prune, import-md), choosing a topic or trigger flags, using the lessons MCP ' +\n 'tools, or when unsure how to phrase or capture a lesson.';\n\nexport const LESSONS_SKILL_BODY = `# Lessons — operating manual\n\nTwo commands: **Recall** before you act, **Capture** after any failure. The graph\n\\`.agentsmesh/lessons/lessons.json\\` is canonical — never hand-edit.\n\n## Recall — before each file edit and each state-changing command\n\n\\`agentsmesh lessons query --file <path> --cmd <command>\\` (add \\`--keyword <text>\\` to\nmatch by task), then apply every rule returned. Scope is MUTATING actions: file edits\nand state-changing commands (build/test/install/migrate/git-write). Pure-read commands\n(cat/ls/grep/git-log; read-only) and the recall query itself are **exempt** — no\ninfinite regress. A predicate-less query is rejected; **keyword-only recall is the\nanti-pattern** — most lessons are keyed to a \\`file_glob\\`/\\`command_pattern\\` and won't\nsurface (the CLI warns). Excuses (\"small edit\", \"I already know this\", \"later\") all\nmean: query first — skipping recall on a mutating action is a process violation, and\nthe user will check.\n\n## Capture — immediately after any failure\n\nAny failure counts, not just red tests: a failing test/CI/lint/typecheck, a code\nreview, a user correction, a regression, or a wrong assumption — yours or anyone's.\n\n\\`agentsmesh lessons add \"<imperative rule>\" --topic <id> --trigger-file <glob> --evidence <sha|lesson-id>\\`\n\n- **At least one _effective_ trigger is required.** A capture is rejected\n (\\`UNRECALLABLE_LESSON\\`) when EVERY trigger is dead on the mandatory \\`--file\\`/\\`--cmd\\`\n recall path — a stopword-only keyword (\"state of the art\"), or an invalid/ReDoS\n command regex — because the lesson could never be recalled there. Prefer\n \\`--trigger-file\\`: the most reliable trigger, it fires on \\`--file\\` recall. A keyword\n alone is discouraged (\\`KEYWORD_ONLY_LESSON\\`); paraphrasing an existing rule warns\n (\\`NEAR_DUPLICATE_LESSON\\` — update that lesson instead).\n- **One imperative sentence.** A rule over 2000 chars is rejected (\\`OVERSIZED_RULE\\`) —\n trim it or split into separate lessons; don't paste a log/diff.\n- Widen with \\`--trigger-cmd <regex>\\` / \\`--trigger-kw <text>\\`. New area:\n \\`--new-topic --topic-summary \"<line>\"\\` (list ids with \\`agentsmesh lessons topics\\`).\n\n## No shell? — MCP tools\n\n\\`lessons_query\\`, \\`lessons_add\\`, \\`lessons_topics\\`, \\`lessons_show\\` (inspect a topic),\n\\`lessons_deprecate\\` (retire). validate / prune / merge / import-md are CLI-only.\n\n## Other subcommands\n\n\\`agentsmesh lessons <cmd>\\`: \\`show\\` · \\`deprecate\\` (\\`--superseded-by\\`) · \\`merge\\` ·\n\\`untrigger\\` · \\`strip-markers\\` · \\`prune\\` (\\`--apply\\`; trims over-cap triggers, GCs\norphan triggers/topics) · \\`journal\\` · \\`validate\\` · \\`stats\\` · \\`import-md\\`. Full\nhelp: \\`agentsmesh lessons --help\\`.\n\n## Config (\\`.agentsmesh/lessons/config.json\\`)\n\n\\`recallLimit\\` / \\`recallMaxTokens\\` (canonical recall caps; per-call overrides\n\\`--top\\` / \\`--max-tokens\\`). \\`recallMaxTokens\\` is approximate — \\`rule.length / 4\\`,\nnot a real tokenizer. \\`autoPrune: true\\` (default off) auto-GCs structural cruft\nafter each capture — orphan triggers/topics + non-stranding dead globs, the safe\nhalf of \\`prune\\`; never trims/strands an active lesson, git-reversible.\n\n## Dedup (opt-in)\n\nSet \\`--session <id>\\` (or \\`AGENTSMESH_SESSION_ID\\`) and lessons already delivered this\nsession are suppressed, so each recall carries only what is new (\\`--no-dedup\\` opts\nout). With no session id, recall is fully stateless — unchanged.`;\n\n/** Serialized canonical \\`SKILL.md\\` content for the lessons manual. */\nexport const LESSONS_SKILL_FILE = serializeFrontmatter(\n { name: LESSONS_SKILL_NAME, description: LESSONS_SKILL_DESCRIPTION },\n LESSONS_SKILL_BODY,\n);\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { maybeAutoMigrateLessons } from './auto-migrate.js';\nimport { captureLogPath } from './capture-telemetry.js';\nimport { mutateLessonsGraphLocked } from './mutate.js';\nimport { lessonsPaths, toRelPath } from './paths.js';\nimport { defaultLessonsConfig } from './recall-config.js';\nimport { injectRecallHook } from './recall-hook-scaffold.js';\nimport { recallLogPath } from './telemetry.js';\nimport { ensureGitignoreEntries } from '../utils/filesystem/gitignore.js';\nimport {\n appendLessonsParagraph,\n LESSONS_PARAGRAPH_BLOCK,\n} from '../targets/projection/lessons-paragraph.js';\nimport { LESSONS_SKILL_FILE, LESSONS_SKILL_NAME } from './skill.js';\n\nexport interface ScaffoldLessonsResult {\n readonly created: string[];\n /** Managed artifacts rewritten to the current wording (e.g. a stale skill). */\n readonly updated: string[];\n readonly skipped: string[];\n readonly rootRuleUpdated: boolean;\n /** True when the recall-log gitignore entry was added to `.gitignore`. */\n readonly gitignoreUpdated: boolean;\n /** True when the PostToolUse recall hook was injected into `hooks.yaml`. */\n readonly recallHookInjected: boolean;\n}\n\n/**\n * Idempotent scaffolder for the lessons subsystem. Backs `agentsmesh init\n * --lessons`, the lessons-only retrofit, and the import safety net.\n *\n * - Creates `.agentsmesh/lessons/lessons.json` (an empty graph) if missing.\n * - Injects the lessons ritual (Tier 1 — the always-on trigger) into\n * `.agentsmesh/rules/_root.md` as a managed block\n * (`<!-- agentsmesh:lessons-contract:start -->` … `:end -->`). The block is\n * canonical content so it reaches every target — including rules-directory\n * targets the generation-contract decorator skips — while the sentinels keep\n * the block an identifiable unit for clean round-trip and let re-running\n * scaffold refresh the wording from one constant.\n * - Writes `.agentsmesh/skills/lessons/SKILL.md` (Tier 2 — the on-demand manual).\n * Like the Tier-1 paragraph, this is a MANAGED artifact: every run rewrites it\n * to the current manual so an upgraded agentsmesh propagates the new wording\n * (reported as `updated` when it changed, `skipped` when already current).\n * The graph, by contrast, is user data and stays create-if-missing. Targets\n * without skills still get Tier 1.\n */\nexport async function scaffoldLessons(projectRoot: string): Promise<ScaffoldLessonsResult> {\n const paths = lessonsPaths(projectRoot);\n const created: string[] = [];\n const updated: string[] = [];\n const skipped: string[] = [];\n\n mkdirSync(paths.base, { recursive: true });\n // Migrate a legacy store before scaffolding so a retrofit does not create an\n // empty graph over still-unmigrated lessons (which would strand them forever).\n await maybeAutoMigrateLessons(projectRoot);\n if (existsSync(paths.graph)) {\n skipped.push(paths.graph);\n } else {\n // Create the empty graph through the transactional path so even the initial\n // write holds the lock and re-reads under it — it cannot clobber a graph a\n // concurrent writer just created.\n await mutateLessonsGraphLocked(projectRoot, () => {});\n created.push(paths.graph);\n }\n\n seedLessonsConfig(projectRoot, created, skipped);\n seedLessonsSkill(projectRoot, created, updated, skipped);\n\n const rootRuleUpdated = injectProceduralBlock(projectRoot);\n // Auto-wire deterministic hook-mode recall for hook-capable targets; non-hook\n // targets keep the always-on paragraph injected above as their fallback.\n const recallHookInjected = injectRecallHook(projectRoot);\n // Keep BOTH opt-in telemetry logs (recall + capture) out of git. Entries are\n // derived from the telemetry modules so the paths stay single-sourced; the\n // append is idempotent and coverage-aware, so re-running scaffold (init is\n // documented as safe to repeat) and an existing broader `.agentsmesh/` ignore\n // are both no-ops.\n const gitignoreUpdated = await ensureGitignoreEntries(projectRoot, [\n toRelPath(projectRoot, recallLogPath(projectRoot)),\n toRelPath(projectRoot, captureLogPath(projectRoot)),\n ]);\n return { created, updated, skipped, rootRuleUpdated, gitignoreUpdated, recallHookInjected };\n}\n\n/**\n * Write the Tier-2 lessons manual at `.agentsmesh/skills/lessons/SKILL.md`.\n * Managed (not user-owned), mirroring the Tier-1 paragraph: every run rewrites\n * it to {@link LESSONS_SKILL_FILE}, so a re-run after an agentsmesh upgrade\n * refreshes a stale manual. Records the path in `created` (new), `updated`\n * (rewritten because it drifted), or `skipped` (already current).\n */\nfunction seedLessonsSkill(\n projectRoot: string,\n created: string[],\n updated: string[],\n skipped: string[],\n): void {\n const skillPath = join(projectRoot, '.agentsmesh/skills', LESSONS_SKILL_NAME, 'SKILL.md');\n const desired = `${LESSONS_SKILL_FILE}\\n`;\n if (!existsSync(skillPath)) {\n mkdirSync(dirname(skillPath), { recursive: true });\n writeFileSync(skillPath, desired, 'utf8');\n created.push(skillPath);\n return;\n }\n if (readFileSync(skillPath, 'utf8') === desired) {\n skipped.push(skillPath);\n return;\n }\n writeFileSync(skillPath, desired, 'utf8');\n updated.push(skillPath);\n}\n\n/**\n * Write `.agentsmesh/lessons/config.json` with every tunable at its default, so\n * the recall caps and `autoPrune` are discoverable and editable without reading\n * the docs. User data, NOT a managed artifact: create-if-missing only — an\n * existing config (with the user's edits) is left untouched and reported skipped.\n */\nfunction seedLessonsConfig(projectRoot: string, created: string[], skipped: string[]): void {\n const configPath = lessonsPaths(projectRoot).config;\n if (existsSync(configPath)) {\n skipped.push(configPath);\n return;\n }\n mkdirSync(dirname(configPath), { recursive: true });\n writeFileSync(configPath, `${JSON.stringify(defaultLessonsConfig(), null, 2)}\\n`, 'utf8');\n created.push(configPath);\n}\n\nfunction injectProceduralBlock(projectRoot: string): boolean {\n const rootRule = join(projectRoot, '.agentsmesh/rules/_root.md');\n if (!existsSync(rootRule)) {\n mkdirSync(dirname(rootRule), { recursive: true });\n const seeded = `---\\nroot: true\\ndescription: \"\"\\n---\\n\\n${LESSONS_PARAGRAPH_BLOCK}\\n\\n# Operational Guidelines\\n`;\n writeFileSync(rootRule, seeded, 'utf8');\n return true;\n }\n const current = readFileSync(rootRule, 'utf8');\n const desired = `${appendLessonsParagraph(current)}\\n`;\n if (desired === current) return false;\n writeFileSync(rootRule, desired, 'utf8');\n return true;\n}\n"]}