agentsmesh 0.40.0 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +75 -0
- package/README.md +1 -1
- package/dist/canonical.js +299 -238
- package/dist/canonical.js.map +1 -1
- package/dist/cli.js +271 -332
- package/dist/engine.d.ts +7 -8
- package/dist/engine.js +771 -276
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1733 -521
- package/dist/index.js.map +1 -1
- package/dist/{init-B1qdo3Dl.d.ts → init-DruMEhnc.d.ts} +97 -42
- package/dist/lessons.d.ts +7 -4
- package/dist/lessons.js +2091 -613
- package/dist/lessons.js.map +1 -1
- package/dist/{target-descriptor-CvTJyDxd.d.ts → target-descriptor-CMV6vxVE.d.ts} +7 -0
- package/dist/targets.d.ts +2 -2
- package/dist/targets.js +265 -219
- package/dist/targets.js.map +1 -1
- package/package.json +3 -2
package/dist/lessons.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lessons/graph-schema.ts","../src/lessons/add-helpers.ts","../src/lessons/graph-store.ts","../src/lessons/import-legacy-parse.ts","../src/lessons/add-errors.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/command-pattern-breadth.ts","../src/lessons/ranking-text.ts","../src/lessons/keyword-signal.ts","../src/lessons/trigger-effectiveness.ts","../src/lessons/add-gates.ts","../src/lessons/glob-breadth.ts","../src/lessons/validate-liveness.ts","../src/lessons/capture-guardrails.ts","../src/lessons/capture-near-duplicate.ts","../src/core/errors.ts","../src/utils/filesystem/process-lock.ts","../src/lessons/lessons-lock.ts","../src/lessons/validate-checks.ts","../src/lessons/validate-quality.ts","../src/lessons/validate-keywords.ts","../src/lessons/validate.ts","../src/lessons/mutate.ts","../src/lessons/add.ts","../src/lessons/import-legacy-merge.ts","../src/lessons/paths.ts","../src/lessons/import-legacy.ts","../src/lessons/auto-migrate.ts","../src/lessons/seen-store.ts","../src/lessons/keyword-match.ts","../src/lessons/query.ts","../src/lessons/jsonl-log.ts","../src/lessons/telemetry.ts","../src/lessons/cmd-fastpath.ts","../src/lessons/normalize-query-file.ts","../src/lessons/lexical-retrieval.ts","../src/lessons/ranking-signals.ts","../src/lessons/ranking.ts","../src/lessons/recall-config.ts","../src/lessons/context-key.ts","../src/lessons/recall-telemetry.ts","../src/lessons/outcome-log.ts","../src/lessons/session-window.ts","../src/lessons/seen-cache.ts","../src/lessons/recall.ts","../src/lessons/prune.ts","../src/lessons/auto-prune.ts","../src/lessons/capture-telemetry.ts","../src/lessons/project-files.ts","../src/lessons/capture.ts","../src/lessons/merge.ts","../src/lessons/strip-markers.ts","../src/lessons/recall-hook-scaffold.ts","../src/lessons/merge-driver-setup.ts","../src/utils/filesystem/fs-text-encoding.ts","../src/utils/filesystem/rename-retry.ts","../src/utils/filesystem/fs.ts","../src/utils/filesystem/gitattributes.ts","../src/utils/filesystem/gitignore.ts","../src/utils/text/markdown.ts","../src/targets/projection/managed-blocks.ts","../src/targets/projection/lessons-paragraph.ts","../src/lessons/skill.ts","../src/lessons/init.ts"],"names":["spec","z","makeTriggerId","TRIGGER_PREFIX","createHash","existsSync","hex","basename","dirname","sleep","join","rmSync","resolve","mkdir","existing","readFileSync","parseYaml","mkdirSync","writeFileSync","renameSync","picomatch","tmpdir","statSync","cache","relative","union","changedIds","readFile","lstat","rm","yamlStringify"],"mappings":"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","file":"lessons.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * Schema version this build WRITES. A graph stamped higher is from a newer CLI.\n * v2 adds the optional lesson `scope: 'always'` (always-on lessons). Reads accept\n * v1 (legacy) and v2 — see {@link VersionSchema}; every write stamps this value, so\n * a v1 graph upgrades to v2 on first mutation. An older CLI reading a v2 graph\n * reports `newer-version` (graph-store) and degrades gracefully rather than\n * choking on the unknown `scope` key under its strict v1 schema.\n */\nexport const CURRENT_GRAPH_VERSION = 2;\n\n/** Versions this build can READ (accepts legacy v1 and current v2). */\nconst VersionSchema = z.union([z.literal(1), z.literal(2)]);\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 * `'always'` marks an ALWAYS-ON lesson: a universal standard delivered on\n * every task (via the UserPromptSubmit hook / a `--always` recall) rather than\n * matched by triggers. Such a lesson needs no trigger and is excluded from\n * triggered recall. Absent = a normal triggered lesson.\n */\n scope: z.literal('always').optional(),\n })\n .strict();\n\nexport const LessonsGraphSchema = z\n .object({\n version: VersionSchema,\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\n/** UTC `YYYY-MM-DD`. */\nexport function todayIso(): string {\n return new Date().toISOString().slice(0, 10);\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","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\n/** Thrown when the rule text is empty or whitespace-only — there is nothing to capture. */\nexport class EmptyRuleError extends Error {\n readonly code = 'EMPTY_RULE';\n constructor() {\n super('Lesson rule must not be empty — pass one imperative sentence.');\n this.name = 'EmptyRuleError';\n }\n}\n\n/**\n * Thrown when a `--trigger-cmd` pattern matches the empty string or nearly every\n * command (`.*`, ` `, `\\w`). Such a trigger fires on every recall, so it is a\n * leak that dilutes every command-shaped lesson rather than a trigger.\n */\nexport class BroadCommandPatternError extends Error {\n readonly code = 'BROAD_COMMAND_PATTERN';\n constructor(public readonly pattern: string) {\n super(\n `Command pattern ${JSON.stringify(pattern)} matches nearly every command, so it would fire on ` +\n 'every recall. Key it on the action instead — a word-bounded program + subcommand ' +\n '(e.g. \"\\\\bgit commit\\\\b\", \"\\\\brm\\\\b\").',\n );\n this.name = 'BroadCommandPatternError';\n }\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","/** 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 { getCommandMatcher } from './regex-safety.js';\n\n/**\n * Breadth guardrail for `command_pattern` triggers. A pattern that matches the\n * empty string (`.*`, `^`, `x*`, `(git)?`) or nearly every command (` `, `.`,\n * `\\w`) fires on EVERY recall — it is not a trigger, it is a leak that dilutes\n * every command-shaped lesson. Breadth is probed empirically against a fixed\n * corpus of unrelated commands, so the verdict is deterministic and does not\n * depend on regex-shape heuristics. Invalid or unsafe patterns are never\n * \"broad\": those fall through to the existing INVALID/UNSAFE rejection.\n */\n\n/** Twenty unrelated commands; a pattern hitting most of them is a leak, not a trigger. */\nexport const COMMAND_PROBE_CORPUS: readonly string[] = [\n 'git status',\n 'git commit -m \"wip\"',\n 'pnpm test',\n 'npx vitest run src/x.test.ts',\n 'ls -la',\n 'cat README.md',\n 'rm -rf dist',\n 'mkdir -p build/out',\n 'node scripts/build.js',\n 'docker compose up -d',\n 'curl -s https://example.com',\n 'echo hello > out.txt',\n \"sed -i 's/a/b/' file.txt\",\n 'pnpm lint --fix',\n 'python3 -m pytest',\n 'cargo build --release',\n 'make',\n 'npm install --global typescript',\n 'cp a.txt b.txt',\n 'grep -rn TODO src',\n];\n\n/** Broad when the pattern hits MORE than this share of the probe corpus. */\nconst BROAD_HIT_RATIO = 0.5;\n\n/** Generous per-probe work bound; the corpus is tiny, so this never trips a real pattern. */\nconst PROBE_BUDGET = 100_000;\n\n/** True when `pattern` matches the empty string or most of the probe corpus. */\nexport function isBroadCommandPattern(pattern: string): boolean {\n const matcher = getCommandMatcher(pattern);\n if (matcher === null) return false;\n if (matcher.test('', { remaining: PROBE_BUDGET })) return true;\n let hits = 0;\n for (const command of COMMAND_PROBE_CORPUS) {\n if (matcher.test(command, { remaining: PROBE_BUDGET })) hits += 1;\n }\n return hits > COMMAND_PROBE_CORPUS.length * BROAD_HIT_RATIO;\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 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/**\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 {\n BroadCommandPatternError,\n EmptyRuleError,\n NoTriggerError,\n RuleTooLongError,\n UnrecallableLessonError,\n} from './add-errors.js';\nimport type { AddLessonInput, AddLessonOptions } from './add.js';\nimport { isBroadCommandPattern } from './command-pattern-breadth.js';\nimport { MAX_RULE_LENGTH, type LessonsGraph } from './graph-schema.js';\nimport { blockingDeadTriggers } from './trigger-effectiveness.js';\n\n/**\n * Blocking capture gates for {@link addLessonInto}. Each throws a dedicated\n * rejection error BEFORE the transactional write barrier, so a rejected capture\n * persists nothing and surfaces a precise, actionable reason (CLI exit 2 with\n * the add hint; MCP VALIDATION_FAILED with the machine code).\n */\n\n/** Trim the rule, rejecting an empty or over-long one (a malformed capture). */\nexport function assertRuleShape(rule: string): string {\n const trimmed = rule.trim();\n if (trimmed.length === 0) throw new EmptyRuleError();\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 (trimmed.length > MAX_RULE_LENGTH) throw new RuleTooLongError(trimmed.length, MAX_RULE_LENGTH);\n return trimmed;\n}\n\n/**\n * An ALWAYS-ON lesson (scope:'always') is delivered on every task, not matched\n * by triggers, so it needs none — the trigger gates are skipped for it (as\n * legacy-merge recovery also does).\n */\nexport function skipsTriggerGates(input: AddLessonInput, options: AddLessonOptions): boolean {\n return options.allowNoTrigger === true || input.scope === 'always';\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\n/**\n * Gates on the INPUT triggers, before any trigger node is created.\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).\n * - A command pattern that matches nearly every command is a leak, not a\n * trigger. Legacy-merge recovery folds historical lessons as-is (`validate`\n * surfaces them as BROAD_COMMAND_PATTERN).\n */\nexport function assertTriggerInputs(\n input: AddLessonInput,\n options: AddLessonOptions,\n existingTriggerCount: number,\n): void {\n if (\n !skipsTriggerGates(input, options) &&\n countInputTriggers(input.triggers) === 0 &&\n existingTriggerCount === 0\n ) {\n throw new NoTriggerError();\n }\n if (options.allowNoTrigger !== true) {\n const broad = (input.triggers.commands ?? []).find(isBroadCommandPattern);\n if (broad !== undefined) throw new BroadCommandPatternError(broad);\n }\n}\n\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. A throw here aborts the\n * transactional write, so nothing is persisted.\n */\nexport function assertRecallable(graph: LessonsGraph, resultingTriggers: readonly string[]): void {\n const blockingDead = blockingDeadTriggers(graph, resultingTriggers);\n if (resultingTriggers.length > 0 && blockingDead.length === resultingTriggers.length) {\n throw new UnrecallableLessonError(blockingDead);\n }\n}\n","/**\n * How narrow a `file_glob` trigger is.\n *\n * Trigger ids are content-addressed, so two lessons never share a pattern and\n * the fanout signal alone cannot tell `src/lessons/recall.ts` from\n * `src/lessons/**` — both are referenced once and both score maximum\n * specificity. Recall then delivers a subsystem-wide rule ahead of the one rule\n * written about the file being edited, and the token budget drops the rest.\n *\n * Narrowness is the share of path segments the pattern pins down literally. A\n * `**` counts as no literal segment AND widens the denominator, because it can\n * span any depth.\n */\n\nconst WILDCARD = /[*?[\\]]/;\n\n/** Narrowness in [0,1]: 1 = an exact path, 0 = matches the whole tree. */\nexport function globNarrowness(pattern: string): number {\n const segments = pattern\n .replaceAll('\\\\', '/')\n .split('/')\n .filter((segment) => segment !== '' && segment !== '.');\n if (segments.length === 0) return 0;\n let literal = 0;\n let globstars = 0;\n for (const segment of segments) {\n if (segment === '**') globstars += 1;\n else if (!WILDCARD.test(segment)) literal += 1;\n }\n return literal / (segments.length + globstars);\n}\n\n/**\n * Broad enough that recall would fire it on most of the repo. Advisory only:\n * a deliberate file-CLASS trigger such as a per-target `index.ts` pattern is the\n * documented way to write a rule about general behaviour, so this never blocks\n * a capture.\n */\nexport const BROAD_GLOB_NARROWNESS = 0.34;\n\nexport function isBroadFileGlob(pattern: string): boolean {\n return globNarrowness(pattern) < BROAD_GLOB_NARROWNESS;\n}\n","import { isBroadFileGlob } from './glob-breadth.js';\nimport picomatch from 'picomatch';\nimport { isBroadCommandPattern } from './command-pattern-breadth.js';\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\nexport function 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(graph: LessonsGraph, knownPaths: ReadonlySet<string>): 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/** How many working-tree paths a `file_glob` pattern matches — for the breadth guardrail. */\nexport function fileGlobMatchCount(pattern: string, knownPaths: ReadonlySet<string>): number {\n const isMatch = picomatch(pattern, { dot: true });\n let n = 0;\n for (const p of knownPaths) if (isMatch(p)) n += 1;\n return 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\n/**\n * A `command_pattern` on an active lesson that matches the empty string or most\n * unrelated commands fires on every recall. `add` rejects a new one\n * (BROAD_COMMAND_PATTERN, exit 2); this is the `validate` counterpart for a\n * graph built before that guardrail existed (or a hand-edit). Warn-only.\n */\n/**\n * A `file_glob` that covers most of the tree fires on nearly every edit, so it\n * crowds out the rule written about the file actually being touched once the\n * recall token budget bites. Warn-only and never blocking: a deliberate\n * file-CLASS trigger is the documented way to state general behaviour, and only\n * genuinely repo-wide patterns are reported.\n */\nexport function collectBroadFileGlobs(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const active = activeTriggerIds(graph);\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'file_glob') continue;\n if (!active.has(triggerId)) continue;\n if (!isBroadFileGlob(trigger.pattern)) continue;\n findings.push({\n level: 'warning',\n code: 'BROAD_FILE_GLOB',\n message: `file_glob trigger \"${triggerId}\" (${trigger.pattern}) matches most of the repository, so it outranks nothing and crowds the recall budget. Narrow it to the directory or file class the rule is really about, or detach it with \\`lessons untrigger\\`.`,\n triggerId,\n });\n }\n}\n\nexport function collectBroadCommandPatterns(\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 (!isBroadCommandPattern(trigger.pattern)) continue;\n findings.push({\n level: 'warning',\n code: 'BROAD_COMMAND_PATTERN',\n message: `command_pattern trigger \"${triggerId}\" (${trigger.pattern}) matches nearly every command, so the lesson fires on every recall. Key it on the action (e.g. \\`\\\\bgit commit\\\\b\\`), or detach it with \\`lessons untrigger\\`.`,\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 { deadFileGlobIds, fileGlobMatchCount } 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 | 'WIDE_GLOB_MATCH'\n | 'KEYWORD_ONLY_LESSON'\n | 'LOW_SIGNAL_KEYWORD'\n | 'STOPWORD_KEYWORD'\n | 'DEAD_GLOB'\n | 'NEAR_DUPLICATE_LESSON';\n\n/**\n * A `file_glob` matching more working-tree files than this is too wide for one\n * lesson — it will fire on many unrelated edits and dilute recall. Complements the\n * STRUCTURAL {@link isBroadGlob} check: catches a globstar with a CONCRETE basename\n * (an `index.ts` at any depth) or a single-directory wildcard (`src/lib/*.ts`) —\n * not structurally broad, yet still matching a large swath of the actual tree.\n */\nexport const WIDE_GLOB_MATCH_COUNT = 40;\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. Exported so capture-time trigger repair narrows on the SAME\n * predicate this guardrail warns on.\n */\nexport function 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 contiguous token-run in --keyword or 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 // File-COUNT breadth (complements the structural isBroadGlob check): a glob that\n // is not structurally broad but still matches a large swath of the real tree.\n const wide = triggers\n .filter((t) => t.kind === 'file_glob' && !isBroadGlob(t.pattern))\n .filter((t) => fileGlobMatchCount(t.pattern, knownPaths) > WIDE_GLOB_MATCH_COUNT)\n .map((t) => t.pattern);\n if (wide.length > 0) {\n warnings.push({\n code: 'WIDE_GLOB_MATCH',\n message: `Lesson \"${lessonId}\" has file glob(s) (${wide.join(', ')}) matching more than ${WIDE_GLOB_MATCH_COUNT} files in the working tree; narrow to the file-CLASS where the rule actually applies so it does not fire on unrelated edits.`,\n });\n }\n }\n\n return warnings;\n}\n","import type { GuardrailWarning } from './capture-guardrails.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { tokenize } from './ranking-text.js';\n\n/**\n * Near-duplicate detection for capture — split from capture-guardrails.ts (the\n * trigger-hygiene warnings) so each stays within the 200-line limit and owns one\n * responsibility: this module answers \"does this new rule paraphrase an existing\n * one?\", the other \"are this lesson's triggers reachable and precise?\".\n */\n\n/** Token-Jaccard similarity at/above which a new lesson is flagged a near-duplicate. */\nexport const NEAR_DUPLICATE_THRESHOLD = 0.6;\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","/**\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_IMPORT_FAILED'\n | 'AM_GENERATION_FAILED'\n | 'AM_REMOTE_FETCH_FAILED'\n | 'AM_LOCK_ACQUISITION_FAILED'\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\n/** A user-authored canonical file (mcp.json, permissions.yaml, hooks.yaml) has a syntax error. */\nexport class CanonicalParseError extends AgentsMeshError {\n readonly path: string;\n\n constructor(path: string, cause: unknown) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(\n 'AM_CONFIG_INVALID',\n `Invalid canonical file ${path}: ${detail}. Fix the syntax and try again.`,\n {\n cause,\n },\n );\n this.name = 'CanonicalParseError';\n this.path = path;\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 * Stale recovery: the holder writes its PID and start timestamp into the lock\n * dir. A dead same-host holder is evicted at once. A live or remote holder is\n * evicted only past `staleMs` — an hours-long bound that catches a hung\n * process or a recycled PID, never a slow but healthy run.\n */\n\nimport { setTimeout as sleep } from 'node:timers/promises';\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 = 6 * 60 * 60 * 1000;\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 /**\n * Secondary age bound (default 6h): a lock older than this is evicted even\n * when its holder PID is still alive or cannot be probed (other host).\n */\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 });\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 try {\n await writeFile(metadataPath, JSON.stringify(metadata), 'utf-8');\n } catch (error) {\n await rm(lockPath, { recursive: true, force: true }).catch(() => {});\n throw error;\n }\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 sameHost = !meta.hostname || meta.hostname === getHostname();\n if (sameHost && !isProcessAlive(meta.pid)) return true;\n return Date.now() - meta.started > staleMs;\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","/**\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","import { normalizeRule } from './add-helpers.js';\nimport type { LessonsGraph } from './graph-schema.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 * Recall delivers a handful of matches per call, so a trigger set shared by more\n * lessons than that is a tie the ranker cannot break: identical triggers score\n * identically on specificity, and the choice falls to topic coherence and rule\n * text. Which lessons an agent actually sees becomes close to arbitrary.\n *\n * Derived from the graph alone, so it works without telemetry.\n */\nconst TIED_TRIGGER_SET_THRESHOLD = 5;\n\nexport function collectTriggerSetCollisions(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n): void {\n const bySet = new Map<string, string[]>();\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n const key = [...lesson.triggers].sort().join(',');\n if (key === '') continue;\n const group = bySet.get(key);\n if (group === undefined) bySet.set(key, [id]);\n else group.push(id);\n }\n\n const contested = [...bySet.values()].filter((ids) => ids.length > TIED_TRIGGER_SET_THRESHOLD);\n if (contested.length === 0) return;\n\n const largest = contested.reduce((a, b) => (b.length > a.length ? b : a));\n const affected = contested.reduce((n, ids) => n + ids.length, 0);\n findings.push({\n level: 'warning',\n code: 'TIED_TRIGGER_SETS',\n message:\n `${contested.length} trigger set(s) are each shared by more than ${TIED_TRIGGER_SET_THRESHOLD} ` +\n `active lessons (largest ${largest.length}, ${affected} lessons in total). Identical triggers ` +\n 'score identically on specificity, so recall picks among them by weaker signals — split the ' +\n 'triggers so the lesson that matters for a given file can win.',\n lessonIds: largest.sort(),\n });\n}\n","import { activeTriggerIds } from './validate-liveness.js';\nimport 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 type { ValidationFinding } from './validate.js';\n\n/**\n * `validate` checks on `keyword` triggers — the curation counterparts to the\n * capture-time LOW_SIGNAL_KEYWORD / STOPWORD_KEYWORD guardrails, so a graph\n * built before those existed still surfaces its structurally-dead keywords.\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 active = activeTriggerIds(graph);\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'keyword') continue;\n if (!active.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 contiguous token-run in --keyword or 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(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const active = activeTriggerIds(graph);\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'keyword') continue;\n if (!active.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","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 collectTriggerSetCollisions,\n collectInvalidTriggerPatterns,\n} from './validate-quality.js';\nimport { collectLowSignalKeywords, collectStopwordKeywords } from './validate-keywords.js';\nimport {\n collectBroadCommandPatterns,\n collectBroadFileGlobs,\n collectDeadFileGlobs,\n collectRunnerAnchoredPatterns,\n} 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 /** Every lesson one aggregate finding covers (machine-readable; the message names a few). */\n readonly lessonIds?: readonly 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 collectTriggerSetCollisions(graph, findings);\n collectLowSignalKeywords(graph, findings);\n collectStopwordKeywords(graph, findings);\n collectRunnerAnchoredPatterns(graph, findings);\n collectBroadCommandPatterns(graph, findings);\n collectBroadFileGlobs(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 { CURRENT_GRAPH_VERSION, type LessonsGraph } from './graph-schema.js';\nimport { saveLessonsGraph, tryLoadLessonsGraph } from './graph-store.js';\nimport { acquireLessonsLock } from './lessons-lock.js';\nimport { validateLessonsGraph, type ValidationFinding, type ValidationReport } from './validate.js';\n\nexport interface MutateOptions {\n readonly retries?: number;\n}\n\nfunction emptyGraph(): LessonsGraph {\n return { version: CURRENT_GRAPH_VERSION, lessons: {}, topics: {}, triggers: {} };\n}\n\n/**\n * Stable identity of a finding, independent of its (churn-prone) message. Keyed on\n * code + the node it points at; findings carry a triggerId OR a lessonId (never a\n * topicId), so those two suffice to tell a pre-existing finding from a new one.\n */\nfunction findingKey(f: ValidationFinding): string {\n return `${f.code}|${f.triggerId ?? ''}|${f.lessonId ?? ''}`;\n}\n\nfunction errorSignatures(report: ValidationReport): Set<string> {\n return new Set(report.findings.filter((f) => f.level === 'error').map(findingKey));\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 // Snapshot pre-existing error findings BEFORE applying the mutation. We only\n // block on errors this mutation INTRODUCES — a single pre-existing invalid\n // trigger (from a merge/hand-edit) must not permanently poison every future\n // capture. recall already skips invalid triggers safely at runtime.\n const baseline = errorSignatures(validateLessonsGraph(graph));\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 const introduced = report.findings.filter(\n (f) => f.level === 'error' && !baseline.has(findingKey(f)),\n );\n if (introduced.length > 0) {\n const errors = introduced.map((f) => `${f.code}: ${f.message}`).join('; ');\n throw new Error(\n `mutateLessonsGraph: refusing to write — this change introduces ${errors}. ` +\n '(Pre-existing graph issues are not blocking; run `agentsmesh lessons validate` to ' +\n 'review and `lessons untrigger`/`prune` to repair them.)',\n );\n }\n\n // Upgrade-on-write: every persisted graph is stamped at the current version,\n // so a loaded legacy v1 graph migrates to v2 the first time it is mutated.\n graph.version = CURRENT_GRAPH_VERSION;\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 { makeLessonId, mergeTriggers, normalizeRule, todayIso, union } from './add-helpers.js';\nimport { UnknownTopicError } from './add-errors.js';\nimport {\n assertRecallable,\n assertRuleShape,\n assertTriggerInputs,\n skipsTriggerGates,\n} from './add-gates.js';\nimport type { AutoPruneSummary } from './auto-prune.js';\nimport { type GuardrailWarning, inspectCapturedLesson } from './capture-guardrails.js';\nimport { nearDuplicateWarning } from './capture-near-duplicate.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { mutateLessonsGraph } from './mutate.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 BroadCommandPatternError,\n EmptyRuleError,\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 /** `'always'` = a universal always-on lesson (no trigger needed; gates skipped). */\n readonly scope?: 'always';\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\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 = assertRuleShape(input.rule);\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 gates 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 // Gates (see add-gates.ts): a throw aborts the transactional write.\n const existing = existingId !== null ? graph.lessons[existingId] : undefined;\n assertTriggerInputs(input, options, existing?.triggers.length ?? 0);\n const { triggerIds, newTriggerIds } = mergeTriggers(graph, input.triggers);\n if (!skipsTriggerGates(input, options)) {\n assertRecallable(\n graph,\n existing === undefined ? triggerIds : union(existing.triggers, triggerIds),\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 // Re-capturing a rule with --scope always promotes it to always-on.\n ...(input.scope === 'always' ? { scope: 'always' as const } : {}),\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 ...(input.scope === 'always' ? { scope: 'always' as const } : {}),\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","/**\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)\n\nGraph \\`.agentsmesh/lessons/lessons.json\\` is canonical; never hand-edit it. Manual: \\`lessons\\` skill.\n\n**Recall:** before every file edit or state-changing command, MUST run \\`agentsmesh lessons query --file <path> --cmd <command> --session auto\\` and obey matches; at task start, ALSO run \\`agentsmesh lessons query --keyword \"<task terms>\" --always --session auto\\` for conceptual + universal rules no path/command names. Pure-read commands and recall itself are exempt.\n\n**Capture:** after any failure, user correction, regression, wrong assumption, useful surprise, repeated friction, or non-obvious fix, MUST self-critique and run \\`agentsmesh lessons add \"<imperative rule>\" --topic <id> --trigger-file <glob> --evidence <sha|lesson-id>\\`.\n\n**Before final:** report \\`Lesson: captured <id>\\` or \\`Lesson: none\\`. No recall/capture gate = task incomplete. No shell: use \\`lessons_query\\` / \\`lessons_add\\`.`;\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 { CURRENT_GRAPH_VERSION, type Lesson, type Topic, type 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 = CURRENT_GRAPH_VERSION;\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 { todayIso } from './add-helpers.js';\nimport { existsSync } from 'node:fs';\nimport { graphFilePath } from './graph-store.js';\nimport { importLegacyLessons, LessonsGraphExistsError } from './import-legacy.js';\nimport { lessonsPaths } from './paths.js';\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","import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\n\n/**\n * File-IO half of session dedup, split from seen-cache.ts for the 200-line\n * limit. Two on-disk shapes coexist: the legacy flat array of delivered ids\n * (untimed sessions — harness/hook and explicit ids), and a v2 object\n * `{ v: 2, seen: { id: deliveredAtMs } }` for TTL sessions (the `--session\n * auto` day bucket), whose entries expire so a later same-day session is not\n * starved. Every operation is best-effort — dedup is an optimization and must\n * never break the blocking recall path.\n */\n\nconst SEEN_DIR = 'agentsmesh-lessons-seen';\n\n/** Short, stable, dependency-free hash (djb2) of a string, base-36. */\nexport function shortHash(value: string): string {\n let h = 5381;\n for (let i = 0; i < value.length; i += 1) h = ((h << 5) + h + value.charCodeAt(i)) >>> 0;\n return h.toString(36);\n}\n\n/**\n * Store location. `projectRoot` namespaces by a hash of the resolved root, so\n * two projects sharing one session id keep SEPARATE dedup state. Omitted → the\n * legacy flat path.\n */\nexport function seenStorePath(id: string, projectRoot?: string): string {\n const safe = id.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 200);\n const scoped = projectRoot === undefined ? safe : `${safe}__${shortHash(resolve(projectRoot))}`;\n return join(tmpdir(), SEEN_DIR, `${scoped}.json`);\n}\n\n/** Parsed store: v2 carries per-id delivery stamps; legacy arrays carry ids only. */\nexport interface StoredSeen {\n readonly ids: ReadonlySet<string>;\n /** null for a legacy array store (no timestamps recorded). */\n readonly stamps: ReadonlyMap<string, number> | null;\n /**\n * Last time this session did ANYTHING (v2 only; absent on stores written\n * before the field existed). Distinct from the delivery stamps: a recall that\n * delivered nothing still counts as activity — see session-window.ts.\n */\n readonly lastAt?: number;\n}\n\n/** Read a store, tolerating both shapes; anything unreadable is an empty store. */\nexport function readSeenStore(path: string): StoredSeen {\n if (!existsSync(path)) return { ids: new Set(), stamps: null };\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (Array.isArray(parsed)) {\n const ids = new Set(parsed.filter((x): x is string => typeof x === 'string'));\n return { ids, stamps: null };\n }\n if (typeof parsed === 'object' && parsed !== null) {\n const seen = (parsed as Record<string, unknown>).seen;\n if (typeof seen === 'object' && seen !== null) {\n const stamps = new Map<string, number>();\n for (const [id, ms] of Object.entries(seen)) {\n if (typeof ms === 'number') stamps.set(id, ms);\n }\n const lastAt = (parsed as Record<string, unknown>).lastAt;\n return {\n ids: new Set(stamps.keys()),\n stamps,\n ...(typeof lastAt === 'number' ? { lastAt } : {}),\n };\n }\n }\n return { ids: new Set(), stamps: null };\n } catch {\n return { ids: new Set(), stamps: null };\n }\n}\n\n/** Atomic best-effort write; an array writes the legacy shape, a map writes v2. */\nexport function writeSeenStore(\n path: string,\n data: readonly string[] | ReadonlyMap<string, number>,\n lastAt?: number,\n): void {\n try {\n mkdirSync(dirname(path), { recursive: true });\n const body =\n data instanceof Map\n ? JSON.stringify({ v: 2, lastAt: lastAt ?? Date.now(), seen: Object.fromEntries(data) })\n : JSON.stringify(data);\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, body, 'utf8');\n renameSync(tmp, path);\n } catch {\n // Optimization only — never fail recall because the seen store could not be written.\n }\n}\n\n/** Best-effort removal (context reset). */\nexport function removeSeenStore(path: string): void {\n try {\n rmSync(path, { force: true });\n } catch {\n // Never let a dedup-reset failure break the blocking recall path.\n }\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 — on BOTH paths, so \"cat\"\n * cannot fire on \"category\", \"art\" cannot fire on \"start\", and a multi-word\n * 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/**\n * Tokens implied by the current edit/command — the recall's task context.\n *\n * Each identifier contributes BOTH its whole lowercased form AND its camelCase /\n * acronym sub-words. Retaining the whole token keeps this fully backward\n * compatible — every keyword trigger that matched before still matches — while the\n * sub-words give conceptual reach a compressed file path otherwise hides: `guard`\n * now reaches `useLeaveGuard`, `selector` reaches `InvoiceCompanySelector`. A\n * sub-word run follows its whole token, so a multi-word needle (`company selector`)\n * still matches as a contiguous run. UNFILTERED (stopwords kept) so \"read only\"\n * cannot match the non-adjacent \"read the only\".\n */\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 if (parts.length === 0) return [];\n const out: string[] = [];\n for (const raw of splitTokens(parts.join(' '))) {\n out.push(raw.toLowerCase());\n const sub = raw\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2') // camelCase / digit→Upper boundary\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2') // ACRONYM→Word boundary\n .toLowerCase()\n .split(' ')\n .filter((t) => t.length > 0);\n if (sub.length > 1) out.push(...sub);\n }\n return out;\n}\n\n/** Split on non-alphanumerics, keeping every word (stopwords included). Not lowercased. */\nfunction splitTokens(text: string): string[] {\n return text.split(/[^A-Za-z0-9]+/).filter((t) => t.length > 0);\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 const needle = tokenize(pattern);\n // 1. Explicit --keyword, as a contiguous token-run (never a mid-word substring).\n if (\n query.keyword !== undefined &&\n containsRun(needle, splitTokens(query.keyword.toLowerCase()))\n ) {\n return true;\n }\n // 2. Derived from file + command, on token boundaries.\n return containsRun(needle, 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 /** Set when the lesson was reached by its wording, not a trigger (lexical retrieval). */\n readonly lexical?: true;\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 // Always-on lessons are delivered on every task (see collectAlwaysLessons),\n // not via triggers — exclude them here so triggered recall never double-injects.\n if (lesson.scope === 'always') 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/**\n * Active always-on lessons (`scope: 'always'`) — universal standards delivered on\n * every task rather than matched by triggers. Sorted newest-first (then id) so a\n * token cap keeps the most recent; the caller bounds the set.\n */\nexport function collectAlwaysLessons(graph: LessonsGraph): MatchedLesson[] {\n const out: MatchedLesson[] = [];\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status === 'active' && lesson.scope === 'always') out.push({ id, lesson });\n }\n out.sort((a, b) =>\n a.lesson.createdAt !== b.lesson.createdAt\n ? a.lesson.createdAt < b.lesson.createdAt\n ? 1\n : -1\n : a.id < b.id\n ? -1\n : 1,\n );\n return out;\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\n/**\n * Fast-path parity probe: could a command-only query match ANY of these\n * patterns? MUST mirror {@link queryLessons}'s trigger matching exactly (same\n * linear engine, same budget seed, same keyword semantics) — a false \"cannot\n * match\" here would silently skip a mandatory recall. Consumed by\n * cmd-fastpath.ts against its precomputed active-trigger pattern lists.\n */\nexport function commandCouldMatch(\n commandPatterns: readonly string[],\n keywordPatterns: readonly string[],\n command: string,\n): boolean {\n const budget: WorkBudget = { remaining: COMMAND_MATCH_BUDGET };\n const query: LessonsQuery = { command };\n return (\n commandPatterns.some((p) => {\n const matcher = getCommandMatcher(p);\n return matcher !== null && matcher.test(command, budget);\n }) || keywordPatterns.some((p) => keywordMatches(p, query))\n );\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 { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { appendJsonl, 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. Opt in per project with `\"telemetry\": true` in\n * `.agentsmesh/lessons/config.json`, or per process with {@link TELEMETRY_ENV}\n * (`1` forces on, `0` forces off). The config path exists because the hooks are\n * the most important writer and a hook spawned by a desktop app inherits none of\n * the user's shell exports: an env-only gate left every hook blind for weeks\n * while the CLI in a terminal kept logging. Records carry field-PRESENCE\n * booleans only — never the raw file / command / keyword text — so the log stays\n * 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 /**\n * The normalized action this recall was for (`file:src/x.ts`, `cmd:git commit`,\n * or `none` for a keyword-only query) — the SAME key the outcome log uses, so\n * this stores no content the logs did not already hold.\n *\n * Without it the log proves a recall happened but not for which action, so\n * occurrences per action cannot be counted and no before/after effectiveness\n * claim is computable. Optional because records written before this existed\n * have no key.\n */\n readonly contextKey?: string;\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 /** Candidates reached by rule wording (lexical retrieval). Absent on older rows. */\n readonly text?: 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\n/** True when the project's lessons config opts in. Never throws: a broken file is \"off\". */\nfunction configTelemetry(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 return (\n typeof parsed === 'object' &&\n parsed !== null &&\n (parsed as Record<string, unknown>).telemetry === true\n );\n } catch {\n return false;\n }\n}\n\n/**\n * The env var wins in both directions (`1` on, `0` off); otherwise the project\n * config decides when a root is known. Writers pass their project root so a\n * hook process with an empty environment still honours the project's opt-in.\n */\nexport function isTelemetryEnabled(\n env: NodeJS.ProcessEnv = process.env,\n projectRoot?: string,\n): boolean {\n const raw = env[TELEMETRY_ENV];\n if (raw === '1') return true;\n if (raw === '0') return false;\n return projectRoot !== undefined && configTelemetry(projectRoot);\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, projectRoot)) return;\n appendJsonl(recallLogPath(projectRoot), record, {\n maxRecords: MAX_RECALL_LOG_RECORDS,\n trimTriggerBytes: RECALL_LOG_TRIM_TRIGGER_BYTES,\n });\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 { shortHash } from './seen-store.js';\nimport { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { graphFilePath } from './graph-store.js';\nimport { commandCouldMatch } from './query.js';\nimport { appendRecallRecord, sessionId as envSessionId } from './telemetry.js';\n\n/**\n * Command-recall fast path. The hook recalls on EVERY shell command, but a\n * graph holds few command_pattern/keyword triggers relative to the command\n * firehose, so most command-only recalls provably match nothing yet still pay\n * a full graph parse + outcome-log read (field-measured at >80% no-match). This\n * caches the active command-reachable trigger patterns in the OS temp dir\n * (never the project tree), stamped with the graph file's (mtimeMs, size):\n * a stale or missing or corrupt cache ALWAYS falls back to the full path, so\n * the worst failure mode is \"no speedup\", never a skipped match. Matching\n * reuses `commandCouldMatch` — the exact engine `queryLessons` runs — so the\n * fast \"cannot match\" verdict and the full path agree by construction.\n */\n\nconst FASTPATH_DIR = 'agentsmesh-lessons-cmdidx';\n\ninterface FastpathCache {\n readonly stamp: { readonly mtimeMs: number; readonly size: number };\n readonly commandPatterns: readonly string[];\n readonly keywordPatterns: readonly string[];\n}\n\n/** Short, stable, dependency-free hash (djb2) of a string, base-36. */\n/** Cache location (per project, in the OS temp dir). Exported for tests. */\nexport function commandFastpathCachePath(projectRoot: string): string {\n return join(tmpdir(), FASTPATH_DIR, `${shortHash(resolve(projectRoot))}.json`);\n}\n\n/**\n * The graph file's freshness stamp RIGHT NOW. Callers that go on to read the\n * graph must take this BEFORE the read and hand it to\n * {@link refreshCommandFastpath} — stamping after the read races a concurrent\n * atomic graph write (stale patterns under a fresh stamp = a poisoned cache\n * that produces false \"cannot match\" verdicts until the next write).\n */\nexport function currentGraphStamp(projectRoot: string): { mtimeMs: number; size: number } | null {\n try {\n const s = statSync(graphFilePath(projectRoot));\n return { mtimeMs: s.mtimeMs, size: s.size };\n } catch {\n return null;\n }\n}\n\nfunction isStringArray(v: unknown): v is readonly string[] {\n return Array.isArray(v) && v.every((x) => typeof x === 'string');\n}\n\nfunction readCache(path: string): FastpathCache | null {\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (typeof parsed !== 'object' || parsed === null) return null;\n const c = parsed as Record<string, unknown>;\n const stamp = c.stamp as Record<string, unknown> | undefined;\n if (\n typeof stamp?.mtimeMs !== 'number' ||\n typeof stamp.size !== 'number' ||\n !isStringArray(c.commandPatterns) ||\n !isStringArray(c.keywordPatterns)\n ) {\n return null;\n }\n return {\n stamp: { mtimeMs: stamp.mtimeMs, size: stamp.size },\n commandPatterns: c.commandPatterns,\n keywordPatterns: c.keywordPatterns,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Write (or freshen) the cache from a loaded graph. Best-effort: any failure is\n * swallowed — the cache is an optimization, never a dependency. Extraction\n * mirrors `queryLessons`'s lesson filter: triggers reachable via ACTIVE,\n * non-always lessons only (always-on lessons are delivered, not matched).\n *\n * `preReadStamp` is the stamp the caller took BEFORE reading `graph`\n * ({@link currentGraphStamp}). The write happens only when the file still\n * carries that exact stamp: a mismatch means an atomic write landed inside the\n * read window and `graph` no longer describes the file — caching it under the\n * new stamp would be a self-perpetuating false \"cannot match\". Skipping is\n * safe: the next recall re-reads and re-tries.\n */\nexport function refreshCommandFastpath(\n projectRoot: string,\n graph: LessonsGraph,\n preReadStamp: { mtimeMs: number; size: number } | null,\n): void {\n try {\n if (preReadStamp === null) return;\n const stamp = currentGraphStamp(projectRoot);\n if (stamp === null) return;\n if (stamp.mtimeMs !== preReadStamp.mtimeMs || stamp.size !== preReadStamp.size) return;\n const path = commandFastpathCachePath(projectRoot);\n const existing = readCache(path);\n if (\n existing !== null &&\n existing.stamp.mtimeMs === stamp.mtimeMs &&\n existing.stamp.size === stamp.size\n ) {\n return;\n }\n const reachable = new Set<string>();\n for (const lesson of Object.values(graph.lessons)) {\n if (lesson.status !== 'active' || lesson.scope === 'always') continue;\n for (const t of lesson.triggers) reachable.add(t);\n }\n const commandPatterns: string[] = [];\n const keywordPatterns: string[] = [];\n for (const [id, trigger] of Object.entries(graph.triggers)) {\n if (!reachable.has(id)) continue;\n if (trigger.kind === 'command_pattern') commandPatterns.push(trigger.pattern);\n else if (trigger.kind === 'keyword') keywordPatterns.push(trigger.pattern);\n }\n const cache: FastpathCache = { stamp, commandPatterns, keywordPatterns };\n mkdirSync(dirname(path), { recursive: true });\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify(cache), 'utf8');\n renameSync(tmp, path);\n } catch {\n // Optimization only — never let a cache write break recall.\n }\n}\n\n/**\n * True ONLY when a fresh cache proves no active trigger can match `command`.\n * Every uncertain condition (no cache, stale stamp, corrupt file, fs error)\n * returns false, sending the caller down the full recall path.\n */\nexport function commandDefinitelyUnmatched(projectRoot: string, command: string): boolean {\n try {\n const stamp = currentGraphStamp(projectRoot);\n if (stamp === null) return false;\n const cache = readCache(commandFastpathCachePath(projectRoot));\n if (cache === null) return false;\n if (cache.stamp.mtimeMs !== stamp.mtimeMs || cache.stamp.size !== stamp.size) return false;\n return !commandCouldMatch(cache.commandPatterns, cache.keywordPatterns, command);\n } catch {\n return false;\n }\n}\n\n/**\n * Telemetry parity for a fast-path exit: the full path writes a no-match recall\n * record, so the fast path must too or `stats` silently loses its no-match\n * volume. Gated on the same telemetry env inside appendRecallRecord.\n */\nexport function recordFastpathNoMatch(projectRoot: string, session?: string): void {\n const sess = session ?? envSessionId();\n appendRecallRecord(projectRoot, {\n ts: new Date().toISOString(),\n hasFile: false,\n hasCommand: true,\n hasKeyword: false,\n totalMatches: 0,\n returnedCount: 0,\n returnedTokens: 0,\n truncated: false,\n matchedByKind: { file: 0, command: 0, keyword: 0 },\n lessonIds: [],\n bypassed: false,\n ...(sess !== undefined ? { session: sess } : {}),\n });\n}\n\n/**\n * Hook-facing composite: true (after recording no-match telemetry) when this\n * tool call is a command-only recall that provably matches nothing. False for\n * anything uncertain or out of scope (file present, diff keyword present),\n * sending the hook down the full recall path.\n */\nexport function hookCommandFastpath(\n projectRoot: string,\n input: { file?: string; command?: string; keyword: string; sessionId?: string },\n): boolean {\n if (input.file !== undefined || input.command === undefined || input.keyword.length > 0) {\n return false;\n }\n if (!commandDefinitelyUnmatched(projectRoot, input.command)) return false;\n recordFastpathNoMatch(projectRoot, input.sessionId);\n return true;\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 type { LessonsGraph } from './graph-schema.js';\nimport { queryLessons, type LessonsQuery, type MatchedLesson } from './query.js';\nimport { bm25, buildCorpus, tokenize } from './ranking-text.js';\n\n/**\n * Lexical retrieval: reach a lesson by the wording of its rule, not only by a\n * trigger. Trigger recall is exact and cheap, but a conceptual lesson fires only\n * when its keyword trigger happens to appear in the task text; phrased another\n * way, it is silent. Scoring the task text against every active rule with the\n * BM25 the ranker already owns closes most of that gap for zero dependencies.\n *\n * Runs ONLY for keyword-only queries — the prompt-submit hook and the task-start\n * `lessons query --keyword` — never for a file/command query, where a wording\n * match would be weaker evidence than the trigger that fired and precision is\n * what matters. Candidates carry `lexical: true`; they match no trigger, so the\n * ranker's specificity puts them below any triggered lesson.\n */\n\n/** Most wording matches added per recall; the caps still apply after ranking. */\nexport const LEXICAL_LIMIT = 3;\n/** Distinct query terms a rule must contain; one shared word is coincidence. */\nexport const LEXICAL_MIN_TERMS = 2;\n\n/**\n * Words too generic to count toward the gate. The ranker's stoplist is tiny on\n * purpose (BM25 weighs the rest by rarity), but the gate is a yes/no: \"top\" and\n * \"left\" once qualified a merge-conflict-marker rule for an SVG prompt. BM25\n * still scores these; they just cannot be the reason a rule qualifies.\n */\nconst GENERIC = new Set(\n (\n 'top left right bottom before after first last next new old use used using run make keep set ' +\n 'get add all any each every not no never always only one two more less same other than then ' +\n 'into from over under out up down off via per so if else when where which what who how why ' +\n 'do does did done can could should would will may might has have had are was were been being ' +\n 'also still just even very both either such these those they them their we you your our he ' +\n 'she his her my me our us own same here there now then again once about above below between ' +\n 'during through until while because but by need needs needed way ways thing things'\n ).split(' '),\n);\n\nexport function isKeywordOnlyQuery(query: LessonsQuery): boolean {\n return query.keyword !== undefined && query.file === undefined && query.command === undefined;\n}\n\nexport interface MatchResult {\n /** Trigger matches first, then wording matches (each flagged `lexical`). */\n readonly matches: MatchedLesson[];\n /** How many of `matches` came from wording, for telemetry. */\n readonly lexicalCount: number;\n}\n\n/** The one candidate step every recall entry point shares (CLI, MCP, hook). */\nexport function matchLessons(graph: LessonsGraph, query: LessonsQuery): MatchResult {\n const triggered = queryLessons(graph, query);\n const lexical =\n isKeywordOnlyQuery(query) && query.keyword !== undefined\n ? lexicalCandidates(\n graph,\n query.keyword,\n triggered.map((m) => m.id),\n )\n : [];\n return { matches: [...triggered, ...lexical], lexicalCount: lexical.length };\n}\n\n/**\n * Active, non-always lessons whose rule shares at least {@link LEXICAL_MIN_TERMS}\n * distinct terms with `keyword`, best BM25 first, capped at {@link LEXICAL_LIMIT}.\n * `excludeIds` are the lessons a trigger already matched.\n */\nexport function lexicalCandidates(\n graph: LessonsGraph,\n keyword: string,\n excludeIds: readonly string[],\n): MatchedLesson[] {\n const terms = [...new Set(tokenize(keyword))];\n if (terms.length < LEXICAL_MIN_TERMS) return [];\n const excluded = new Set(excludeIds);\n const corpus = buildCorpus(graph);\n const scored: { id: string; lesson: LessonsGraph['lessons'][string]; score: number }[] = [];\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status !== 'active' || lesson.scope === 'always' || excluded.has(id)) continue;\n const ruleTerms = new Set(tokenize(lesson.rule));\n let shared = 0;\n for (const t of terms) if (!GENERIC.has(t) && ruleTerms.has(t)) shared += 1;\n if (shared < LEXICAL_MIN_TERMS) continue;\n scored.push({ id, lesson, score: bm25(terms, lesson.rule, corpus) });\n }\n scored.sort((a, b) => (b.score !== a.score ? b.score - a.score : a.id < b.id ? -1 : 1));\n return scored.slice(0, LEXICAL_LIMIT).map(({ id, lesson }) => ({ id, lesson, lexical: true }));\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport { globNarrowness } from './glob-breadth.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 * A keyword can match a `--file` query incidentally, because recall also tests\n * the path's own tokens: \"lessons recall\" hits `src/lessons/recall.ts`. That is\n * weaker evidence than any glob deliberately written about the path, so it\n * ranks below every such glob and above only a repo-wide one. In a keyword\n * query every match is a keyword, so they all tie here and the ordering is the\n * one this signal never touched.\n */\nconst KEYWORD_NARROWNESS = 0.4;\n\n/**\n * Narrowness per trigger id, in [0,1]. A `file_glob` scores by how much of the\n * path it pins down; a keyword scores the constant above; a command pattern is\n * neutral, since it can only match a command query where every rival is also a\n * command pattern.\n */\nexport function buildNarrowness(graph: LessonsGraph): Map<string, number> {\n const narrowness = new Map<string, number>();\n for (const [id, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind === 'file_glob') narrowness.set(id, globNarrowness(trigger.pattern));\n else narrowness.set(id, trigger.kind === 'keyword' ? KEYWORD_NARROWNESS : 1);\n }\n return narrowness;\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 type { Lesson, LessonsGraph } from './graph-schema.js';\nimport { collectMatchedTriggerIds, type LessonsQuery, type MatchedLesson } from './query.js';\nimport { buildFanout, buildNarrowness, 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 /** Reached by rule wording rather than a trigger (see lexical-retrieval.ts). */\n readonly lexical?: true;\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 * Per-lesson effectiveness score in [0,1] from the outcome log (1 = always\n * helped; absent = neutral). Fed as a LOW-weight RRF signal so a proven\n * fire-but-fail lesson sinks below an equally-matched effective one — a\n * corrective nudge, never a driver. Empty/absent ⇒ every lesson ties on this\n * signal ⇒ ordering is unchanged from the pre-effectiveness ranker.\n */\n readonly effectiveness?: ReadonlyMap<string, 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 = 1200;\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 */\n// Strictly greater than TOPIC_COHERENCE + BM25 + EFFECTIVENESS, so a lesson\n// that wins specificity cannot be outvoted by a clean sweep of the weaker\n// signals. Mandatory recall fires on --file/--cmd, where \"which trigger matched\n// and how precisely\" is the evidence; the rest only order what specificity ties.\nconst SPECIFICITY_WEIGHT = 5;\nconst TOPIC_COHERENCE_WEIGHT = 2;\nconst BM25_WEIGHT = 1;\n// Effectiveness (outcome-log) is a corrective nudge, not a driver — the same low\n// weight as BM25, so it only sinks a proven fire-but-fail lesson below an\n// equally-matched sibling and never overrides a specificity lead. Neutral (every\n// lesson equal) when the log carries no signal, so ranking is then unchanged.\nconst EFFECTIVENESS_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 narrowness = buildNarrowness(graph);\n const coherence = buildTopicCoherence(matches);\n const matchedTriggerIds = collectMatchedTriggerIds(graph, query);\n\n const scored = matches.map(({ id, lesson, lexical }) => {\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 // Fanout alone cannot separate a pinpoint glob from a subtree glob (trigger\n // ids are content-addressed, so both are referenced once); narrowness does.\n for (const t of hitTriggers) {\n specificity = Math.max(specificity, (narrowness.get(t) ?? 1) / fanout.get(t)!);\n }\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 // Absent from the log ⇒ neutral 1, so a lesson with no outcome data never\n // sinks below one that has merely been recorded.\n effectiveness: options.effectiveness?.get(id) ?? 1,\n lexical,\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 const effRanks = rankMap(scored.map((s) => ({ id: s.id, value: s.effectiveness })));\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 EFFECTIVENESS_WEIGHT / (RRF_K + effRanks.get(s.id)!),\n reason: {\n matchedTriggers: s.matchedTriggers,\n bm25: s.bm25,\n specificity: s.specificity,\n topicCoherence: s.topicCoherence,\n ...(s.lexical === true ? { lexical: true as const } : {}),\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 /** Opt into the recall/capture/outcome logs that `stats`, effectiveness ranking and the health view read. */\n readonly telemetry: 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 telemetry: 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 { normalizeRecallFile } from './normalize-query-file.js';\n\n/**\n * A `contextKey` binds an outcome (a lesson delivered, or a failure observed) to\n * the concrete ACTION about to happen — the file being edited or the command\n * class being run. A delivery and a later failure on the SAME action share this\n * key, which is how effectiveness attributes a recurrence to the lesson meant to\n * prevent it. It is the action ONLY — the error class is recorded separately and\n * is never folded in here, because the `delivered` event is emitted before any\n * error exists, so an error-bearing key could never match its later `failure`.\n */\n\n/**\n * Reduce a shell command to a stable class — the program plus optional\n * subcommand — so outcomes bind to the action, not its varying arguments:\n * \"git commit -m 'wip'\" → \"git commit\"; \"tsc --noEmit src/x.ts\" → \"tsc\".\n * A subcommand is the bare word DIRECTLY after the program; past a flag, a bare\n * word is an operand (\"rm -rf build\" → \"rm\"), so it never fragments the class.\n */\nexport function normalizeCommand(command: string): string {\n const words = command.trim().split(/\\s+/);\n // Drop leading `VAR=val` env assignments so `FOO=1 npm test` and `npm test` share a class.\n let start = 0;\n while (start < words.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(words[start]!)) start += 1;\n const rest = words.slice(start);\n const programIdx = rest.findIndex(isBareWord);\n // A command that is ONLY env assignments (`FOO=bar` — no program) has no class,\n // so it collapses to '' rather than echoing the assignment; a path-shaped\n // program (`./run.sh`) keeps its first token.\n if (programIdx === -1) return rest[0] ?? '';\n const program = rest[programIdx]!;\n const next = rest[programIdx + 1];\n return next !== undefined && isBareWord(next) ? `${program} ${next}` : program;\n}\n\n/** Not a flag, not path-like, not a quoted fragment. */\nfunction isBareWord(w: string): boolean {\n return w.length > 0 && !w.startsWith('-') && !w.includes('/') && !/^[\"'`]/.test(w);\n}\n\n/** Deterministic action key. File takes precedence (the tighter signal). Never raw text. */\nexport function contextKey(\n input: { file?: string; command?: string },\n projectRoot: string,\n): string {\n if (input.file !== undefined && input.file.length > 0) {\n return `file:${normalizeRecallFile(input.file, projectRoot)}`;\n }\n if (input.command !== undefined && input.command.length > 0) {\n return `cmd:${normalizeCommand(input.command)}`;\n }\n return 'none';\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport { collectMatchedTriggersByKind, type LessonsQuery, type MatchedLesson } from './query.js';\nimport { estTokens, type RankedLesson } from './ranking.js';\nimport { appendRecallRecord, isTelemetryEnabled, sessionId } from './telemetry.js';\nimport { contextKey } from './context-key.js';\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: {\n readonly bypassed?: boolean;\n readonly session?: string;\n /** Candidates that came from rule wording, not a trigger (lexical retrieval). */\n readonly lexical?: number;\n } = {},\n): void {\n if (!isTelemetryEnabled(process.env, projectRoot)) 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 // Explicit caller session (hook stdin / --session) wins; env is the fallback.\n const session = options.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 contextKey: contextKey({ file: query.file, command: query.command }, projectRoot),\n matchedByKind: {\n file: countVia(byKind.file_glob),\n command: countVia(byKind.command_pattern),\n keyword: countVia(byKind.keyword),\n ...(options.lexical !== undefined ? { text: options.lexical } : {}),\n },\n lessonIds: lessons.map((l) => l.id),\n bypassed: options.bypassed === true,\n ...(session !== undefined ? { session } : {}),\n });\n}\n","import { join } from 'node:path';\nimport { appendJsonl, logExists, readJsonl } from './jsonl-log.js';\nimport { lessonsPaths } from './paths.js';\nimport { isTelemetryEnabled, sessionId } from './telemetry.js';\n\n/**\n * The lesson-effectiveness substrate (EVALUATE) — the one gap no competitor\n * closes: did a delivered lesson actually prevent the repeat? An append-only\n * side-channel log (NEVER the graph, which is `.strict()` + frozen) records two\n * event kinds, and effectiveness is DERIVED at read time. Gated on the same\n * telemetry env as the recall log, so the default configuration pays nothing.\n */\n\nconst MAX_OUTCOME_LOG_RECORDS = 5000;\nconst OUTCOME_LOG_TRIM_TRIGGER_BYTES = 2_000_000;\n\n/** A lesson injected into agent context for a concrete action. */\nexport interface OutcomeDelivered {\n /** ISO-8601 timestamp supplied by the caller (engine never reads the wall clock). */\n readonly ts: string;\n readonly kind: 'delivered';\n readonly lessonId: string;\n /** Normalized action+error signature — see context-key.ts. Never raw text. */\n readonly contextKey: string;\n readonly session?: string;\n /** 0-based relevance rank within its delivery batch (0 = top-ranked). */\n readonly rank?: number;\n}\n\n/** A failure observed at a decision point (the thing a lesson is meant to prevent). */\nexport interface OutcomeFailure {\n readonly ts: string;\n readonly kind: 'failure';\n readonly contextKey: string;\n /** Coarse class of the error (see error-class.ts) — a hint for STORE, not a key. */\n readonly errorClass?: string;\n readonly session?: string;\n}\n\nexport type OutcomeEvent = OutcomeDelivered | OutcomeFailure;\n\n/** Append-only outcome log, sibling of the graph — never the graph itself. */\nexport function outcomeLogPath(projectRoot: string): string {\n return join(lessonsPaths(projectRoot).base, 'outcome-log.jsonl');\n}\n\n/** Append one event — a no-op unless telemetry is enabled, so recall/capture pay nothing by default. */\nexport function appendOutcomeEvent(\n projectRoot: string,\n event: OutcomeEvent,\n env: NodeJS.ProcessEnv = process.env,\n): void {\n if (!isTelemetryEnabled(env, projectRoot)) return;\n appendJsonl(outcomeLogPath(projectRoot), event, {\n maxRecords: MAX_OUTCOME_LOG_RECORDS,\n trimTriggerBytes: OUTCOME_LOG_TRIM_TRIGGER_BYTES,\n });\n}\n\n/** Read every outcome event, skipping torn lines. Returns [] when absent. */\nexport function readOutcomeLog(projectRoot: string): OutcomeEvent[] {\n return readJsonl<OutcomeEvent>(outcomeLogPath(projectRoot));\n}\n\n/** True when the outcome log file exists — distinguishes \"never recorded\" from \"empty\". */\nexport function outcomeLogExists(projectRoot: string): boolean {\n return logExists(outcomeLogPath(projectRoot));\n}\n\n/**\n * Record that these lessons were injected for `contextKey` (stamps ts + session +\n * per-batch rank; ids MUST arrive relevance-ranked). No-op unless telemetry is on.\n * An explicit `session` (the harness's hook-stdin id) wins over the env fallback —\n * the env var is unset in hook deployments, which left every record session-less.\n */\nexport function recordDelivered(\n projectRoot: string,\n lessonIds: readonly string[],\n contextKey: string,\n env: NodeJS.ProcessEnv = process.env,\n session: string | undefined = sessionId(env),\n): void {\n if (!isTelemetryEnabled(env, projectRoot) || lessonIds.length === 0) return;\n const ts = new Date().toISOString();\n lessonIds.forEach((lessonId, rank) => {\n appendOutcomeEvent(\n projectRoot,\n {\n ts,\n kind: 'delivered',\n lessonId,\n contextKey,\n rank,\n ...(session !== undefined ? { session } : {}),\n },\n env,\n );\n });\n}\n\n/**\n * Record a failure observed for `contextKey` (stamps ts + session). No-op unless\n * telemetry is on. Explicit `session` wins over the env fallback (see above).\n */\nexport function recordFailure(\n projectRoot: string,\n contextKey: string,\n errorClass?: string,\n env: NodeJS.ProcessEnv = process.env,\n session: string | undefined = sessionId(env),\n): void {\n if (!isTelemetryEnabled(env, projectRoot)) return;\n appendOutcomeEvent(\n projectRoot,\n {\n ts: new Date().toISOString(),\n kind: 'failure',\n contextKey,\n ...(errorClass !== undefined ? { errorClass } : {}),\n ...(session !== undefined ? { session } : {}),\n },\n env,\n );\n}\n\n/** How many times `contextKey` has failed, plus the most recent error class. */\nexport interface ContextFailures {\n readonly count: number;\n readonly lastErrorClass?: string;\n}\n\n/**\n * Failure history for one action, for the recurrence-driven capture nudge (STORE).\n * A pure read over the log; `count` counts every failure recorded for `contextKey`\n * across sessions, so a mistake repeating over days is still seen as recurring.\n */\nexport function failuresForContext(projectRoot: string, contextKey: string): ContextFailures {\n let count = 0;\n let lastErrorClass: string | undefined;\n for (const ev of readOutcomeLog(projectRoot)) {\n if (ev.kind !== 'failure' || ev.contextKey !== contextKey) continue;\n count += 1;\n if (ev.errorClass !== undefined) lastErrorClass = ev.errorClass;\n }\n return { count, ...(lastErrorClass !== undefined ? { lastErrorClass } : {}) };\n}\n\n/** The latest error class for an action, and how many times THAT error recurred. */\nexport interface RecurringFailure {\n /** Undefined when the harness reported no error text for any failure. */\n readonly errorClass?: string;\n readonly sameClassCount: number;\n}\n\n/**\n * The most recent error class for this action and its recurrence count.\n *\n * The action key is deliberately coarse (`cat x` and `cat y` share `cmd:cat`),\n * so a plain failure count cannot support the claim that one problem recurred —\n * six unrelated errors under one class look identical to the same error six\n * times. Counting per class is what makes \"this failed before\" mean something.\n */\nexport function recurringFailure(projectRoot: string, contextKey: string): RecurringFailure {\n const perClass = new Map<string, number>();\n let errorClass: string | undefined;\n for (const ev of readOutcomeLog(projectRoot)) {\n if (ev.kind !== 'failure' || ev.contextKey !== contextKey) continue;\n if (ev.errorClass === undefined) continue;\n errorClass = ev.errorClass;\n perClass.set(ev.errorClass, (perClass.get(ev.errorClass) ?? 0) + 1);\n }\n if (errorClass === undefined) return { sameClassCount: 0 };\n return { errorClass, sameClassCount: perClass.get(errorClass) ?? 0 };\n}\n\n/** Delivered/missed tallies for one lesson, derived from the event stream. */\nexport interface LessonOutcome {\n readonly delivered: number;\n readonly missed: number;\n}\n\n/** Scope by session so a failure only impeaches deliveries within its own session. */\nfunction scopeKey(ev: { session?: string; contextKey: string }): string {\n return `${ev.session ?? ''}\u0000${ev.contextKey}`;\n}\n\n/**\n * Effectiveness substrate: a delivered lesson is a MISS when the same\n * `(session, contextKey)` fails again LATER in the stream — it fired but did not\n * prevent the repeat. Pure and deterministic, O(n): index the last failure per\n * scope, then a delivery positioned before that index is a miss. The signal is\n * deliberately coarse (attribution is noisy) — an honest weak signal, not a fake\n * precise one.\n */\nexport function effectiveness(events: readonly OutcomeEvent[]): Map<string, LessonOutcome> {\n const lastFailure = new Map<string, number>();\n events.forEach((ev, i) => {\n if (ev.kind === 'failure') lastFailure.set(scopeKey(ev), i);\n });\n const out = new Map<string, { delivered: number; missed: number }>();\n events.forEach((ev, i) => {\n if (ev.kind !== 'delivered') return;\n const cur = out.get(ev.lessonId) ?? { delivered: 0, missed: 0 };\n cur.delivered += 1;\n const lf = lastFailure.get(scopeKey(ev));\n if (lf !== undefined && lf > i) cur.missed += 1;\n out.set(ev.lessonId, cur);\n });\n return out;\n}\n\n/** 1 = always helped, 0 = never helped. Undelivered lessons are neutral (1). */\nexport function effectivenessScore(o: LessonOutcome): number {\n return o.delivered === 0 ? 1 : 1 - o.missed / o.delivered;\n}\n\n/**\n * Per-lesson effectiveness score in [0,1] for the recall ranker. Empty when\n * telemetry is off or no lesson has been delivered — in which case ranking is\n * unchanged (every lesson is neutral).\n */\nexport function loadEffectiveness(projectRoot: string): ReadonlyMap<string, number> {\n const map = new Map<string, number>();\n for (const [id, o] of effectiveness(readOutcomeLog(projectRoot))) {\n map.set(id, effectivenessScore(o));\n }\n return map;\n}\n","import { sessionId as envSessionId } from './telemetry.js';\n\n/**\n * When a signal-less recall session begins and ends.\n *\n * A hook is TOLD what happened to the model's context (SessionStart\n * compact/clear/startup), so it can reset dedup exactly. The CLI and the MCP\n * server are told nothing — they are a command someone runs and a process\n * someone keeps alive — so for them \"which chat is this?\" has to be inferred.\n * This module owns that inference: the fallback correlator plus the two windows\n * that bound how wrong it can be. Split from seen-cache.ts (which owns the seen\n * set itself) for the 200-line limit; it imports no dedup state, so the\n * dependency runs one way only.\n */\n\n/**\n * Ceiling for a correlator with no context-reset signal (the `--session auto`\n * day bucket, and the MCP server). It bounds the worst case: a new chat opened\n * with no pause at all inherits the previous chat's suppressions only until this\n * window passes. Kept short deliberately — re-showing a rule costs a few hundred\n * tokens, hiding one from a fresh context costs the whole point of recall.\n */\nexport const AUTO_SESSION_TTL_MS = 60 * 60 * 1000;\n\n/**\n * A quiet gap this long means the previous chat is over, so the WHOLE session\n * resets rather than expiring entry by entry. A new chat usually starts after a\n * pause, so idleness is the best signal available; `lessons stats` groups\n * sessions by the same kind of gap.\n */\nexport const AUTO_SESSION_IDLE_MS = 30 * 60 * 1000;\n\n/**\n * Resolve `--session auto`: the exported `AGENTSMESH_SESSION_ID` when present,\n * else a day-bucket key. Prose-driven (non-hook) recall has no harness stdin to\n * carry a session id, so without this every ritual recall re-delivers the whole\n * matched set all day (field-measured at ~59% repeated rule-tokens). The day key\n * is deliberately coarse — {@link AUTO_SESSION_IDLE_MS} and\n * {@link AUTO_SESSION_TTL_MS} are what keep a new chat from inheriting an old\n * one's suppressions, and `--no-dedup` is the immediate escape.\n */\nexport function autoSessionId(env: NodeJS.ProcessEnv = process.env): string {\n return envSessionId(env) ?? dayBucketId();\n}\n\n/**\n * The env-independent half of {@link autoSessionId}. A reset runs in a DIFFERENT\n * process from the recall it is resetting (the hook is a subprocess; the CLI\n * runs in the agent's shell), and those environments need not match — one may\n * see `AGENTSMESH_SESSION_ID` while the other does not. So a reset clears this\n * key as well, rather than assuming both processes resolved the same one.\n */\nexport function dayBucketId(): string {\n return `auto-${new Date().toISOString().slice(0, 10)}`;\n}\n\n/** Clock jitter between the writing and reading process that is not suspicious. */\nconst FUTURE_TOLERANCE_MS = 60_000;\n\n/**\n * Age of a stamp. A stamp meaningfully in the FUTURE cannot be trusted — a clock\n * jump, or a store copied from a machine ahead of this one — and treating it as\n * fresh would pin both the entry and the whole session forever, which is exactly\n * the \"rule hidden indefinitely\" failure this module exists to prevent. Such a\n * stamp is reported as infinitely old instead, so it expires and its session\n * resets: the cost is one re-delivery, which is always the safe direction.\n */\nexport function stampAgeMs(stamp: number, now: number = Date.now()): number {\n if (stamp - now > FUTURE_TOLERANCE_MS) return Number.POSITIVE_INFINITY;\n return Math.max(0, now - stamp);\n}\n\n/**\n * True when this session's last ACTIVITY predates the idle gap. Activity is not\n * the same as delivery: a recall whose matches were all already suppressed\n * delivers nothing, and treating that as inactivity would re-deliver the whole\n * set every gap even while the agent works steadily. So the store records\n * `lastAt` on every recall and this falls back to the newest delivery stamp only\n * for stores written before that field existed. An unstamped (legacy) or empty\n * store is never \"idle\": there is nothing to reset, and the TTL path already\n * treats it as fully expired.\n */\nexport function isIdleSession(\n stamps: ReadonlyMap<string, number> | null,\n lastAt?: number,\n): boolean {\n if (stamps === null || stamps.size === 0) return false;\n let newest = lastAt ?? 0;\n for (const ms of stamps.values()) if (ms > newest) newest = ms;\n return stampAgeMs(newest) > AUTO_SESSION_IDLE_MS;\n}\n","import type { MatchedLesson } from './query.js';\nimport { readSeenStore, removeSeenStore, seenStorePath, writeSeenStore } from './seen-store.js';\nimport { autoSessionId, dayBucketId, isIdleSession, stampAgeMs } from './session-window.js';\nimport { sessionId as envSessionId } from './telemetry.js';\n\n// The session-window policy (correlator + expiry windows) lives next door;\n// re-exported here so `seen-cache` stays the one import for session dedup.\nexport { AUTO_SESSION_IDLE_MS, AUTO_SESSION_TTL_MS, autoSessionId } from './session-window.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 — see seen-store.ts), so it never dirties `.agentsmesh/` and the\n * OS reclaims it. TTL sessions (the `--session auto` day bucket) stamp each\n * delivery and expire entries after {@link AUTO_SESSION_TTL_MS}, so a fresh\n * agent session later the same day is not starved by the morning's deliveries.\n */\n\nexport interface SessionDedup {\n readonly sessionId: string;\n readonly seen: ReadonlySet<string>;\n readonly path: string;\n /** Per-id delivery stamps from a v2 store; null for legacy array stores. */\n readonly stamps: ReadonlyMap<string, number> | null;\n /** Set for TTL sessions: an entry suppresses only within this window. */\n readonly ttlMs?: number;\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 * Project root. Namespaces the seen file by a hash of the resolved root, so two\n * projects sharing one fixed `AGENTSMESH_SESSION_ID` (e.g. a CI runner that\n * exports it once) keep SEPARATE dedup state — otherwise project B inherits\n * project A's \"seen\" set and suppresses coincidentally-colliding lesson ids.\n * Omitted → the legacy flat path (unchanged behavior).\n */\n readonly projectRoot?: string;\n /**\n * Expire suppressions after this window (TTL sessions — the auto day bucket).\n * A legacy array store has no stamps and is treated as fully expired under a\n * TTL: the safe direction is re-delivery, never over-suppression.\n */\n readonly ttlMs?: number;\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 = seenStorePath(id, options.projectRoot);\n const store = readSeenStore(path);\n // A signal-less session that has gone quiet belonged to a context that is\n // gone: drop the whole set, and drop the stamps too so the next commit cannot\n // resurrect it (see AUTO_SESSION_IDLE_MS).\n const stale = options.ttlMs !== undefined && isIdleSession(store.stamps, store.lastAt);\n const stamps = stale ? null : store.stamps;\n return {\n sessionId: id,\n seen: stale ? new Set<string>() : visibleSeen(store.ids, stamps, options.ttlMs),\n path,\n stamps,\n ...(options.ttlMs !== undefined ? { ttlMs: options.ttlMs } : {}),\n };\n}\n\n/** Under a TTL only stamped-and-fresh entries suppress; untimed stores suppress fully. */\nfunction visibleSeen(\n ids: ReadonlySet<string>,\n stamps: ReadonlyMap<string, number> | null,\n ttlMs: number | undefined,\n): ReadonlySet<string> {\n if (ttlMs === undefined) return ids;\n if (stamps === null) return new Set();\n const now = Date.now();\n const fresh = new Set<string>();\n for (const [id, ms] of stamps) if (stampAgeMs(ms, now) <= ttlMs) fresh.add(id);\n return fresh;\n}\n\n/**\n * Discard the per-session seen set, so subsequent recalls re-inject as if fresh.\n * Called when the model's context was actually reset — a `SessionStart`\n * `compact`/`clear` — so dedup (which assumes a delivered lesson stays in context)\n * does not keep suppressing lessons the summarization dropped. Best-effort: a\n * failed remove just leaves the stale set, degrading to today's behavior.\n */\nexport function clearSeen(sessionId: string, projectRoot?: string): void {\n removeSeenStore(seenStorePath(sessionId, projectRoot));\n}\n\n/**\n * Apply a harness `SessionStart` to dedup state. `resume` is the ONLY source\n * that keeps the sets, because it is the only one where the prior context comes\n * back; `compact`, `clear`, `startup`, and any source this build does not model\n * (or a harness that omits the field) all mean the context those suppressions\n * were based on is gone. Both the harness session store AND the CLI/MCP\n * correlator stores are cleared: they are separate files, and clearing only the\n * first left an agent's own `--session auto` recalls suppressed after a\n * compaction. Re-showing a rule costs tokens; hiding one from a context that\n * never saw it defeats the recall gate, so this errs toward clearing.\n */\nexport function clearSeenForSessionStart(\n source: string | undefined,\n sessionId: string | undefined,\n projectRoot: string,\n): void {\n if (source === 'resume') return;\n if (sessionId !== undefined) clearSeen(sessionId, projectRoot);\n // The CLI/MCP correlators live in other stores, resolved in other processes\n // whose environments need not match this one — clear every key they could\n // have used rather than assuming they agreed with us.\n for (const id of new Set([autoSessionId(), dayBucketId()])) clearSeen(id, projectRoot);\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 (see seen-store).\n *\n * The written SHAPE follows the shape that was read, never the caller's mode:\n * one correlator can be shared by a TTL writer (CLI `--session auto`) and an\n * untimed one (hook/MCP), which happens whenever `AGENTSMESH_SESSION_ID` is\n * exported. An untimed commit that downgraded a stamped store back to the bare\n * array would discard every timestamp, and the next TTL read — which treats an\n * unstamped store as fully expired — would suppress nothing, silently zeroing\n * dedup for the rest of the session. So a stamped store stays stamped; only a\n * session that never saw one keeps writing the legacy array (an older binary\n * must still be able to read what this one writes).\n */\nexport function commitSeen(dedup: SessionDedup, returnedIds: readonly string[]): void {\n // A recall that delivered nothing still proves the session is ALIVE. Record\n // that (cheaply, and only for stamped sessions, which are the ones whose idle\n // gap can reset them) so steady work is not mistaken for an abandoned chat.\n if (returnedIds.length === 0) {\n if (dedup.ttlMs !== undefined && dedup.stamps !== null) {\n writeSeenStore(dedup.path, dedup.stamps);\n }\n return;\n }\n if (dedup.ttlMs !== undefined || dedup.stamps !== null) {\n const now = Date.now();\n const merged = new Map<string, number>();\n // Prune expired siblings only when this session actually has a TTL; an\n // untimed session preserves every stamp it read.\n for (const [id, ms] of dedup.stamps ?? []) {\n if (dedup.ttlMs === undefined || now - ms <= dedup.ttlMs) merged.set(id, ms);\n }\n for (const id of returnedIds) merged.set(id, now);\n writeSeenStore(dedup.path, merged);\n return;\n }\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 writeSeenStore(dedup.path, [...union]);\n}\n","import { maybeAutoMigrateLessons } from './auto-migrate.js';\nimport { currentGraphStamp, refreshCommandFastpath } from './cmd-fastpath.js';\nimport { loadLessonsGraphResilient } from './graph-store.js';\nimport { normalizeRecallFile } from './normalize-query-file.js';\nimport { matchLessons } from './lexical-retrieval.js';\nimport type { LessonsQuery } from './query.js';\nimport { rankLessons, type RankedLesson } from './ranking.js';\nimport { loadRecallConfig } from './recall-config.js';\nimport { recordRecallTelemetry } from './recall-telemetry.js';\nimport { loadEffectiveness } from './outcome-log.js';\nimport { commitSeen, filterUnseen, openSessionDedup } from './seen-cache.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` (capture.ts) is the symmetric capture entry\n * point. Prefer these application APIs; reach for the read primitives only\n * 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 * Expire suppressions this long after delivery. Set by callers that have NO\n * context-reset signal (the MCP server never sees the client compact), so a\n * lesson dropped from a summarized context cannot stay hidden forever. The\n * hook path leaves this unset on purpose: it resets on SessionStart\n * compact/clear, which is the exact signal a wall-clock TTL only approximates.\n */\n readonly ttlMs?: number;\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 // Stamp BEFORE the read: refreshCommandFastpath only writes when the file\n // still carries this stamp, so a graph write landing inside the read window\n // can never be cached under stale patterns (see cmd-fastpath.ts).\n const preReadStamp = currentGraphStamp(projectRoot);\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 // Freshen the command fast-path cache while the graph is in hand (no-op when fresh).\n refreshCommandFastpath(projectRoot, graph, preReadStamp);\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 // Task text (prompt submit, task-start keyword recall) also reaches lessons by\n // their wording; a file/command query never does — see lexical-retrieval.ts.\n const { matches, lexicalCount } = matchLessons(graph, matchQuery);\n // Dedup BEFORE ranking so the caps fill with fresh lessons (see seen-cache).\n const dedup = openSessionDedup({\n explicit: options.sessionId,\n disabled: options.noDedup,\n projectRoot,\n ...(options.ttlMs !== undefined ? { ttlMs: options.ttlMs } : {}),\n });\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 // Down-rank proven fire-but-fail lessons (empty ⇒ neutral, so recall is\n // unchanged until the outcome log has real signal). Read from the side-channel\n // only when something survived matching+dedup — a no-match recall must not pay\n // the (up to 2MB) outcome-log read for a ranking of nothing.\n effectiveness: forRank.length === 0 ? new Map() : loadEffectiveness(projectRoot),\n });\n if (dedup !== null)\n commitSeen(\n dedup,\n lessons.map((l) => l.id),\n );\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, {\n bypassed: false,\n session: options.sessionId,\n lexical: lexicalCount,\n });\n return { lessons, totalMatches: matches.length, suppressed: matches.length - forRank.length };\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 { 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, projectRoot)) 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, projectRoot)) 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 { 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 {\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 { listProjectFiles } from './project-files.js';\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 * The symmetric counterpart of `recallLessons` (recall.ts), split out for the\n * 200-line limit.\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 { union } from './add-helpers.js';\nimport 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\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 * Only the \"See L1.\" sentence form owns its period; a period after \"(L5)\" or\n * \"[L5]\" belongs to the surrounding sentence and is kept.\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 { type Document, parseDocument, YAMLMap, YAMLSeq } from 'yaml';\n\n/**\n * Auto-wire hook-mode recall: inject `agentsmesh lessons hook` into canonical\n * `.agentsmesh/hooks.yaml`, so `generate` projects it to every hook-capable target\n * and recall becomes deterministic (no extra model turn, no compliance dependence):\n *\n * - `PreToolUse` — recall injects BEFORE every mutating tool call. It fires on each\n * call, not only the first touch, so it is the whole tool-call story.\n * - `UserPromptSubmit` — the ONLY event that carries the task text (no `tool_input`),\n * so it is the sole moment a keyword/conceptual (\"general\") lesson can recall\n * against task INTENT rather than a file path / command token. Uses matcher `*`\n * (prompt events have no tool to match).\n *\n * `PostToolUse` is deliberately NOT wired, and a previously scaffolded entry there\n * is removed. Alongside PreToolUse it re-ran recall for the same action after the\n * fact: a second process and a second context block per tool call, carrying\n * advice that could no longer be applied. Field data showed 63% of recalls\n * arriving within 3s of a same-shaped one. No target injects on PostToolUse\n * without also supporting PreToolUse (aider's post-edit keys run plain commands\n * and cannot inject at all), so nothing is lost.\n *\n * Targets that cannot represent an event drop it on generate (per-target hook\n * projection skips unmapped events), so wiring these everywhere is safe; targets\n * without any hook support keep relying on the always-on lessons paragraph in\n * their root instruction — the universal fallback.\n *\n * Idempotent per (event, COMMAND) — re-running never duplicates an entry — and\n * edited via the YAML Document API so the file's `# yaml-language-server` schema\n * directive and example comments survive (a parse()→stringify() round-trip would\n * 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';\n/** Mutating tools the PreToolUse recall guards. */\nconst RECALL_HOOK_TOOL_MATCHER = 'Edit|Write|Bash';\n/**\n * Events the recall hook wires, each with the matcher that event needs. Tool-call\n * events match the mutating tools; `UserPromptSubmit` fires on every prompt (`*`).\n */\nconst RECALL_EVENTS: ReadonlyArray<{ readonly event: string; readonly matcher: string }> = [\n { event: 'PreToolUse', matcher: RECALL_HOOK_TOOL_MATCHER },\n { event: 'UserPromptSubmit', matcher: '*' },\n // Capture-on-failure nudge (see capture-nudge.ts). BEST-EFFORT: only Claude\n // Code's passthrough hooks emit it; whitelist targets drop it without warning\n // (BEST_EFFORT_HOOK_EVENTS). PostToolUse is success-only, so failures need this.\n { event: 'PostToolUseFailure', matcher: '*' },\n // Reset recall dedup after a context compaction/clear (see hook.ts SessionStart).\n // BEST-EFFORT: targets that can't represent SessionStart just keep dedup as-is.\n { event: 'SessionStart', matcher: '*' },\n];\n\n/** Events an older scaffold wired that recall must no longer ride (see above). */\nconst RETIRED_EVENTS: readonly string[] = ['PostToolUse'];\n\n/**\n * Remove the managed recall entry from one event, leaving the user's own hooks\n * there untouched; drop the key when nothing remains. Returns true when changed.\n */\nfunction removeEvent(doc: Document, event: string): boolean {\n const existing = doc.get(event);\n if (!(existing instanceof YAMLSeq)) return false;\n const kept = existing.items.filter(\n (item) => !(item instanceof YAMLMap && item.get('command') === RECALL_HOOK_COMMAND),\n );\n if (kept.length === existing.items.length) return false;\n if (kept.length === 0) doc.delete(event);\n else existing.items = kept;\n return true;\n}\n\n/** Add the recall command to one event's hook list. Returns true when it was added. */\nfunction injectEvent(doc: Document, event: string, matcher: string): boolean {\n const existing = doc.get(event);\n const seq = existing instanceof YAMLSeq ? existing : new YAMLSeq();\n const present = seq.items.some(\n (item) => item instanceof YAMLMap && item.get('command') === RECALL_HOOK_COMMAND,\n );\n if (present) return false;\n seq.add(doc.createNode({ matcher, type: 'command', command: RECALL_HOOK_COMMAND }));\n doc.set(event, seq);\n return true;\n}\n\n/** Returns true when a hook was added to any event; 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 let changed = false;\n for (const { event, matcher } of RECALL_EVENTS) {\n if (injectEvent(doc, event, matcher)) changed = true;\n }\n for (const event of RETIRED_EVENTS) {\n if (removeEvent(doc, event)) changed = true;\n }\n if (changed) writeFileSync(path, String(doc), 'utf8');\n return changed;\n}\n","/**\n * Setup facts for the lessons.json git merge driver (see\n * lessons-merge-driver-handler.ts), shared by `init` (which writes the committable\n * half) and the init renderer (which prints the per-clone half).\n *\n * A merge driver has two halves: a COMMITTABLE `.gitattributes` line that binds\n * lessons.json to the driver — one dev commits it, the whole team inherits it —\n * and a PER-CLONE `git config` pair that git cannot auto-run on clone (it would be\n * a remote-code-execution vector). `init --lessons` writes the first and surfaces\n * the second as a one-time setup hint, so concurrent captures union-merge instead\n * of leaving conflict markers.\n */\nexport const LESSONS_MERGE_DRIVER = 'agentsmesh-lessons';\n\n/** Committable `.gitattributes` entry binding the graph to the union merge driver. */\nexport const LESSONS_GITATTRIBUTES_ENTRY = `.agentsmesh/lessons/lessons.json merge=${LESSONS_MERGE_DRIVER}`;\n\n/** Per-clone `git config` commands that activate the driver (cannot be auto-run on clone). */\nexport const LESSONS_MERGE_DRIVER_CONFIG: readonly string[] = [\n `git config merge.${LESSONS_MERGE_DRIVER}.name \"agentsmesh lessons union\"`,\n `git config merge.${LESSONS_MERGE_DRIVER}.driver \"agentsmesh lessons merge-driver %O %A %B\"`,\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\n/**\n * Extensions whose payload is bytes, not text. A skill may ship an image, a\n * font or an archive, and decoding those as UTF-8 replaces every invalid byte\n * with U+FFFD — the file is corrupt before any generator sees it.\n *\n * This is a deliberate allowlist rather than \"anything not in TEXT_EXTENSIONS\":\n * paths outside both sets (`.py`, `.hbs`, the extensionless `.agentsmesh/ignore`)\n * keep their UTF-8 handling, so widening byte mode cannot regress text content.\n */\nconst BINARY_EXTENSIONS = new Set<string>([\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.ico',\n '.webp',\n '.avif',\n '.tiff',\n '.pdf',\n '.zip',\n '.gz',\n '.tgz',\n '.bz2',\n '.xz',\n '.7z',\n '.rar',\n '.jar',\n '.woff',\n '.woff2',\n '.ttf',\n '.otf',\n '.eot',\n '.mp3',\n '.mp4',\n '.wav',\n '.ogg',\n '.webm',\n '.mov',\n '.wasm',\n '.bin',\n '.dat',\n '.db',\n '.sqlite',\n '.so',\n '.dylib',\n '.dll',\n '.exe',\n '.class',\n '.pyc',\n // Office and design documents are zip or proprietary containers.\n '.xlsx',\n '.xls',\n '.docx',\n '.doc',\n '.pptx',\n '.ppt',\n '.odt',\n '.ods',\n '.psd',\n '.ai',\n '.sketch',\n '.fig',\n '.heic',\n '.heif',\n // Archives, columnar data, models and compressed payloads.\n '.tar',\n '.zst',\n '.br',\n '.lz4',\n '.parquet',\n '.avro',\n '.orc',\n '.pkl',\n '.npy',\n '.npz',\n '.onnx',\n '.pt',\n '.safetensors',\n '.gguf',\n '.sqlite3',\n '.avi',\n '.mkv',\n '.flac',\n '.aac',\n '.m4a',\n '.ttc',\n]);\n\nexport function isBinaryPayloadPath(path: string): boolean {\n return BINARY_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\n/**\n * The encoding to read, write and hash a path's payload with. `latin1` maps\n * each byte to exactly one code unit, so bytes survive a round trip through a\n * JS string unchanged — as long as every side of the pipeline agrees, which is\n * why reads, writes and checksums all resolve the encoding here.\n */\nexport function payloadEncodingFor(path: string): 'utf-8' | 'latin1' {\n return isBinaryPayloadPath(path) ? 'latin1' : 'utf-8';\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/**\n * The payload as writeFileAtomic lands it on disk: BOM stripped and CRLF\n * folded to LF for text files, untouched otherwise. Compare or hash through\n * this so in-memory content and its on-disk form never disagree.\n */\nexport function normalizeTextPayload(path: string, content: string): string {\n if (!shouldNormalizeLineEndings(path)) return content;\n const withoutBom = content.startsWith(UTF8_BOM) ? content.slice(UTF8_BOM.length) : content;\n return normalizeLineEndings(withoutBom);\n}\n","import { rename } from 'node:fs/promises';\nimport { setTimeout as sleep } from 'node:timers/promises';\n\ninterface ErrnoLike {\n code?: string;\n}\n\n/**\n * Errors Windows raises when a just-written directory is briefly locked — by the\n * exited writer's lingering handle (e.g. `git clone`), an antivirus scan, or the\n * search indexer. A same-filesystem rename never produces these on POSIX.\n */\nconst TRANSIENT_RENAME_CODES = new Set(['EPERM', 'EACCES', 'EBUSY', 'ENOTEMPTY', 'EEXIST']);\n\nexport interface RenameRetryOptions {\n /** Total attempts before giving up (default 5). */\n readonly attempts?: number;\n /** Base backoff in ms; doubles each retry (default 50). */\n readonly delayMs?: number;\n}\n\n/**\n * `rename`, retried on the transient lock errors Windows raises right after a\n * child process writes the source tree (the cache-finalize rename in\n * `git-remote.ts` hits this directly after `git clone`). On POSIX it is a single\n * rename. A non-transient error throws immediately; the last transient error\n * throws after the final attempt so a genuine failure still surfaces.\n */\nexport async function renameWithRetry(\n from: string,\n to: string,\n options: RenameRetryOptions = {},\n): Promise<void> {\n const attempts = options.attempts ?? 5;\n const delayMs = options.delayMs ?? 50;\n for (let attempt = 0; ; attempt++) {\n try {\n await rename(from, to);\n return;\n } catch (err) {\n const code = (err as ErrnoLike).code;\n const transient = code !== undefined && TRANSIENT_RENAME_CODES.has(code);\n if (!transient || attempt >= attempts - 1) throw err;\n await sleep(delayMs * 2 ** attempt);\n }\n }\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 { readFile, open, access, mkdir, rm, lstat, type FileHandle } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { dirname } from 'node:path';\nimport { constants } from 'node:fs';\nimport { FileSystemError } from '../../core/errors.js';\nimport {\n UTF8_BOM,\n executableModeFor,\n isBinaryPayloadPath,\n normalizeLineEndings,\n payloadEncodingFor,\n shouldNormalizeLineEndings,\n} from './fs-text-encoding.js';\nimport { renameWithRetry } from './rename-retry.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 // Binary payloads (skill images, fonts, archives) are read as latin1 so\n // every byte survives; a UTF-8 decode would replace invalid bytes with\n // U+FFFD and corrupt the file before generation ever runs.\n const data = await readFile(path, payloadEncodingFor(path));\n if (isBinaryPayloadPath(path)) return data;\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 * Uses an exclusively created temporary file; rename replaces a destination symlink.\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 } 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-${randomUUID()}`;\n const payload = shouldNormalizeLineEndings(path) ? normalizeLineEndings(content) : content;\n const mode = options?.mode ?? executableModeFor(path);\n let handle: FileHandle | undefined;\n let ownsTemporaryFile = false;\n try {\n handle = await open(tmpPath, 'wx', mode);\n ownsTemporaryFile = true;\n await handle.writeFile(payload, payloadEncodingFor(path));\n if (mode !== undefined) await handle.chmod(mode);\n await handle.close();\n handle = undefined;\n // Retrying rename, not a plain one: on Windows, replacing a destination\n // fails with EPERM while another process is mid-replace of the same path.\n // Unique temp names (the fix for torn content) removed the accidental\n // serialization writers used to get from sharing one `<path>.tmp`, so\n // concurrent writers now genuinely race here. POSIX is a single rename.\n await renameWithRetry(tmpPath, path);\n } catch (err) {\n await handle?.close().catch(() => {});\n if (ownsTemporaryFile) 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 `.gitattributes` unless already present. Returns\n * true when the file was modified, false when every entry was already there.\n * Idempotent: safe to call on each re-run. Unlike `.gitignore`, attribute lines\n * have no ancestor coverage, so matching is exact-line only (after trim); comment\n * and blank lines are ignored, and existing content plus its trailing newline are\n * preserved.\n */\nexport async function ensureGitattributesEntries(\n projectRoot: string,\n entries: readonly string[],\n): Promise<boolean> {\n const path = join(projectRoot, '.gitattributes');\n const current = (await readFileSafe(path)) ?? '';\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) => !existing.has(e.trim()));\n if (toAdd.length === 0) return false;\n const suffix = current.endsWith('\\n') || current === '' ? '' : '\\n';\n await writeFileAtomic(path, current + suffix + toAdd.join('\\n') + '\\n');\n return 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","// 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 split = splitFrontmatter(content);\n if (split === null) return { frontmatter: {}, body: content.trim() };\n const yamlStr = split.yaml.trim();\n const frontmatter = yamlStr === '' ? {} : ((yamlParse(yamlStr) as Record<string, unknown>) ?? {});\n return { frontmatter, body: split.body };\n}\n\nconst OPENER = /^---[ \\t]*\\r?\\n/;\nconst CLOSER = /^---[ \\t]*\\r?$/m;\n\nexport interface FrontmatterSplit {\n /** Raw YAML between the delimiters (may be empty). */\n yaml: string;\n /** Trimmed content after the closing delimiter line. */\n body: string;\n /** Byte-exact `---…---` block, for callers that re-emit it verbatim. */\n prefix: string;\n}\n\n/**\n * Locate a leading frontmatter block. Both delimiters must be lines of their\n * own: a `---` inside a value (`description: a --- b`) is content, not a close.\n * Returns null when there is no complete block.\n */\nexport function splitFrontmatter(content: string): FrontmatterSplit | null {\n const opener = OPENER.exec(content);\n if (opener === null) return null;\n const yamlStart = opener[0].length;\n const closer = CLOSER.exec(content.slice(yamlStart));\n if (closer === null) return null;\n const closeStart = yamlStart + closer.index;\n const closeEnd = closeStart + closer[0].length;\n return {\n yaml: content.slice(yamlStart, closeStart),\n body: content.slice(closeEnd).trim(),\n prefix: content.slice(0, closeEnd),\n };\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 return splitFrontmatter(content)?.body ?? content.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 { splitFrontmatter } from '../../utils/text/markdown.js';\nimport { basename, join } from 'node:path';\nimport type { CanonicalRule, CanonicalFiles } 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 const split = splitFrontmatter(content);\n return split === null\n ? { prefix: '', body: content.trim() }\n : { prefix: split.prefix, body: split.body };\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\n/**\n * The embedded-root-rule generator: the root rule's body plus a managed block\n * holding every non-root rule that targets `target`, written to `rootFile`.\n * Targets with no native per-rule file all project rules this way.\n */\nexport function embeddedRootRule(\n canonical: CanonicalFiles,\n target: string,\n rootFile: string,\n): { path: string; content: string }[] {\n const rootBody = canonical.rules.find((rule) => rule.root)?.body.trim() ?? '';\n const nonRootRules = canonical.rules.filter(\n (rule) => !rule.root && (rule.targets.length === 0 || rule.targets.includes(target)),\n );\n const content = appendEmbeddedRulesBlock(rootBody, nonRootRules);\n return content ? [{ path: rootFile, content }] : [];\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\nconst LEGACY_RAW_FORMS = [\n // Pre-`--session auto` wording (2026-07): strip sentinel-less copies so a\n // project scaffolded before the dedup correlator dedups on the next scaffold.\n `## Lessons (BLOCKING)\n\nGraph \\`.agentsmesh/lessons/lessons.json\\` is canonical; never hand-edit it. Manual: \\`lessons\\` skill.\n\n**Recall:** before every file edit or state-changing command, MUST run \\`agentsmesh lessons query --file <path> --cmd <command>\\` and obey matches; at task start, ALSO run \\`agentsmesh lessons query --keyword \"<task terms>\" --always\\` for conceptual + universal rules no path/command names. Pure-read commands and recall itself are exempt.\n\n**Capture:** after any failure, user correction, regression, wrong assumption, useful surprise, repeated friction, or non-obvious fix, MUST self-critique and run \\`agentsmesh lessons add \"<imperative rule>\" --topic <id> --trigger-file <glob> --evidence <sha|lesson-id>\\`.\n\n**Before final:** report \\`Lesson: captured <id>\\` or \\`Lesson: none\\`. No recall/capture gate = task incomplete. No shell: use \\`lessons_query\\` / \\`lessons_add\\`.`,\n `## 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];\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 a procedural rule, so a hand-pasted\n * or merge-mangled raw paragraph de-duplicates on the next scaffold instead of\n * leaving a second copy beside the managed block.\n */\nfunction stripRawProceduralRule(content: string): string {\n return [LESSONS_PROCEDURAL_RULE, ...LEGACY_RAW_FORMS].reduce(\n (next, rule) => next.replace(`\\n\\n${rule}`, '').replace(rule, ''),\n content,\n );\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 rest: the Iron\n * Law gates, the rationalization table, and the capture how-to. It is kept short\n * on purpose — full command/flag reference lives in `agentsmesh lessons --help`,\n * not here (skill best practice: move details to tool help).\n *\n * Borrowed from the superpowers pattern (minimal always-on bootstrap + a\n * progressive-disclosure skill manual, plus its rigid \"Iron Law\" gate framing),\n * but realized with agentsmesh's NATIVE primitives: the trigger rides canonical\n * rules (native on every target) and the manual rides a canonical skill (native\n * on every skill-supporting target), rather than a SessionStart hook (not a\n * canonical event; unsupported on most targets). A target without skills still\n * gets the trigger — graceful fallback.\n */\nexport const LESSONS_SKILL_NAME = 'lessons';\n\n// Skill best practice (superpowers writing-skills / Anthropic): the description\n// is the DISCOVERY signal — third-person, \"Use when…\", TRIGGERS ONLY, short, and\n// NEVER a workflow summary (a summarized workflow makes the agent follow the\n// description instead of reading the body). The two triggers below ARE the recall\n// moment (about to mutate) and the capture moment (after a failure), so the skill\n// self-surfaces as the fallback for the always-on rule. Subcommands live in the body.\nexport const LESSONS_SKILL_DESCRIPTION =\n 'Use when about to edit a file or run a state-changing command, or after any ' +\n 'failure, correction, or surprising result.';\n\nexport const LESSONS_SKILL_BODY = `# Lessons — operating manual (Iron Law)\n\n## The Iron Law\n\n**NO MUTATION WITHOUT RECALL. NO COMPLETION WITHOUT A CAPTURE DECISION.**\n\nViolating the letter is violating the spirit. Edited a file or ran a state-changing\ncommand without recall? Process violation. Did the turn hit a failure / correction /\nregression / wrong assumption / surprise and you have not captured (nor stated\n\\`Lesson: none\\`)? The task is INCOMPLETE — and the user will check. The graph\n\\`.agentsmesh/lessons/lessons.json\\` is canonical — never hand-edit.\n\n## Recall — before each edit/command, and at task start\n\n\\`agentsmesh lessons query --file <path> --cmd <command> --session auto\\`, then apply every\nrule. Pure-read commands (read-only) and the query itself are exempt. **keyword-only recall\nfor a specific edit is the anti-pattern** — anchor those to \\`--file\\`/\\`--cmd\\`. But at the\nSTART of a task (or when planning), run \\`agentsmesh lessons query --keyword \"<the task's\nkey terms>\" --always --session auto\\`: that surfaces the conceptual rules no file/command\nnames PLUS the universal always-on lessons — the manual equivalent of the automatic prompt\nrecall on hook-capable tools. **Always pass \\`--session auto\\`**: it suppresses rules already\nshown this session so repeat recalls stay quiet (without it every recall re-delivers the\nwhole matched set); \\`--no-dedup\\` re-shows everything after a context reset. Author a\n\\`keyword\\` trigger beside a \\`file_glob\\` on conceptual lessons so they are reachable both\nways. No shell → MCP \\`lessons_query\\` (\\`file\\`/\\`command\\`/\\`keyword\\`/\\`always\\`; session dedup\nis on by default there — \\`no_dedup:true\\` to re-show).\n\n## Capture — Gate Function (before any completion claim)\n\n1. **SELF-CRITIQUE**: any failure, correction, regression, wrong assumption,\n useful surprise, repeated friction, or non-obvious fix? Failing\n tests/lint/typecheck and user/review corrections — yours or anyone's — all count.\n PROCESS/TOOLING surprises count too (a sandbox command that silently no-op'd, a port\n already in use, a library's argument shape) — trigger those with \\`--trigger-cmd\\`. So\n does a review finding you REVIEWED then deliberately REJECTED: capture it as a \"do NOT\n refactor\" guard so the reasoning survives the session.\n2. **CAPTURE** a reusable imperative rule with an effective trigger (else say so):\n \\`agentsmesh lessons add \"<rule>\" --topic <id> --trigger-file <glob>\\`. Trigger on the\n file-CLASS where it will RECUR (e.g. \\`**/lib/use*Form*.ts\\`), NOT the single file you\n discovered it in — and NOT a broad \\`src/**\\`. If the rule is a UNIVERSAL standard that\n applies to EVERY task (a comment/test/style convention no file or command names),\n capture it with \\`--scope always\\` instead — it needs no trigger and is delivered on\n every task.\n3. **RECEIPT**: emit \\`Lesson: captured <id>\\` or \\`Lesson: none\\`.\n\nAt least one _effective_ trigger is required (or \\`--scope always\\` for a universal rule) or\nthe capture is rejected (\\`UNRECALLABLE_LESSON\\`); prefer \\`--trigger-file\\`. No shell → MCP \\`lessons_query\\`,\n\\`lessons_add\\`, \\`lessons_topics\\`, \\`lessons_show\\`, \\`lessons_deprecate\\`. Run\n\\`agentsmesh lessons --help\\` for every subcommand and flag: query, add, topics, show,\ndeprecate, merge, untrigger, strip-markers, prune, journal, validate, stats, import-md.\n\n### Rationalization Prevention — these excuses mean STOP\n\n| Excuse | Reality |\n| --- | --- |\n| \"Small edit / I already know this / later\" | Query first — skipping recall is a process violation |\n| \"Nothing reusable here\" | You hit a failure/surprise — name it or capture it |\n| \"My own TDD red, not a real failure\" | A red you did not predict IS a lesson |\n| \"I fixed one site; the twin is obvious\" | Capture it — the unfixed twin is what gets missed |\n| \"Different words, so the rule doesn't apply\" | Spirit over letter |\n\n## Lesson gate — before final response\n\nThe final response MUST carry the receipt: \\`Lesson: captured <id>\\` or \\`Lesson: none\\`.\nNo receipt = task incomplete. Do not capture one-off facts, task summaries, or project\ncontext — only reusable imperative rules with an effective trigger.`;\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 { outcomeLogPath } from './outcome-log.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 { LESSONS_GITATTRIBUTES_ENTRY } from './merge-driver-setup.js';\nimport { recallLogPath } from './telemetry.js';\nimport { ensureGitattributesEntries } from '../utils/filesystem/gitattributes.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 lessons.json merge-driver entry was added to `.gitattributes`. */\n readonly gitattributesUpdated: 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 toRelPath(projectRoot, outcomeLogPath(projectRoot)),\n ]);\n // Commit the merge-driver binding for the shared graph so a team's concurrent\n // captures union-merge instead of leaving conflict markers. This is the\n // COMMITTABLE half; the per-clone `git config` half is surfaced as a setup hint\n // by the renderer (git cannot auto-run it on clone). Idempotent + preserves any\n // existing .gitattributes content.\n const gitattributesUpdated = await ensureGitattributesEntries(projectRoot, [\n LESSONS_GITATTRIBUTES_ENTRY,\n ]);\n return {\n created,\n updated,\n skipped,\n rootRuleUpdated,\n gitignoreUpdated,\n gitattributesUpdated,\n recallHookInjected,\n };\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"]}
|
|
1
|
+
{"version":3,"sources":["../src/lessons/graph-schema.ts","../src/lessons/glob-expand.ts","../src/lessons/glob-parse.ts","../src/lessons/normalize-query-file.ts","../src/lessons/trigger-file-glob.ts","../src/lessons/add-helpers.ts","../src/utils/filesystem/fs-text-encoding.ts","../src/lessons/graph-store.ts","../src/lessons/import-legacy-parse.ts","../src/lessons/add-errors.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/command-pattern-breadth.ts","../src/lessons/rule-line.ts","../src/lessons/ranking-text.ts","../src/lessons/keyword-signal.ts","../src/lessons/trigger-effectiveness.ts","../src/lessons/add-gates.ts","../src/lessons/glob-breadth.ts","../src/lessons/glob-dp.ts","../src/lessons/glob-safety.ts","../src/lessons/file-glob-liveness.ts","../src/lessons/git-exec.ts","../src/lessons/git-path-history.ts","../src/lessons/paths.ts","../src/lessons/project-files.ts","../src/lessons/validate-liveness.ts","../src/lessons/capture-guardrails.ts","../src/lessons/capture-near-duplicate.ts","../src/lessons/leftovers.ts","../src/core/errors.ts","../src/utils/filesystem/process-identity.ts","../src/utils/filesystem/transient-fs.ts","../src/utils/filesystem/rename-retry.ts","../src/utils/filesystem/process-lock-state.ts","../src/utils/filesystem/process-lock-ops.ts","../src/utils/filesystem/process-lock.ts","../src/utils/output/color.ts","../src/utils/output/logger.ts","../src/lessons/lessons-lock.ts","../src/lessons/validate-checks.ts","../src/lessons/validate-quality.ts","../src/lessons/validate-keywords.ts","../src/lessons/validate.ts","../src/lessons/mutate.ts","../src/lessons/add.ts","../src/lessons/import-legacy-merge.ts","../src/utils/filesystem/path-containment.ts","../src/lessons/import-legacy-read.ts","../src/lessons/import-legacy.ts","../src/lessons/auto-migrate.ts","../src/lessons/seen-store.ts","../src/lessons/keyword-match.ts","../src/lessons/query.ts","../src/lessons/jsonl-log.ts","../src/utils/types/guards.ts","../src/lessons/log-record-guards.ts","../src/lessons/telemetry.ts","../src/lessons/cmd-fastpath.ts","../src/lessons/lexical-retrieval.ts","../src/lessons/ranking-signals.ts","../src/lessons/ranking.ts","../src/lessons/recall-config.ts","../src/lessons/command-class.ts","../src/lessons/context-key.ts","../src/lessons/recall-telemetry.ts","../src/lessons/action-match.ts","../src/lessons/effectiveness.ts","../src/lessons/outcome-log.ts","../src/lessons/session-window.ts","../src/lessons/seen-cache.ts","../src/lessons/recall.ts","../src/lessons/prune.ts","../src/lessons/auto-prune.ts","../src/lessons/capture-telemetry.ts","../src/lessons/capture.ts","../src/lessons/merge.ts","../src/lessons/strip-markers.ts","../src/lessons/cli-invocation.ts","../src/lessons/recall-hook-scaffold.ts","../src/lessons/launcher.ts","../src/lessons/merge-driver-setup.ts","../src/lessons/recall-hook-hint.ts","../src/utils/filesystem/fs.ts","../src/utils/filesystem/gitattributes.ts","../src/utils/filesystem/gitignore.ts","../src/utils/text/markdown.ts","../src/targets/projection/managed-blocks.ts","../src/targets/projection/lessons-paragraph.ts","../src/lessons/skill.ts","../src/lessons/init.ts"],"names":["out","c","open","realpathSync","spec","basename","resolve","statSync","dirname","z","makeTriggerId","TRIGGER_PREFIX","createHash","join","existsSync","hex","parseClass","tokenize","cache","relative","readdirSync","rmSync","stat","sleep","readFile","readFileSync","rename","mkdir","hostname","randomUUID","sep","posix","parseYaml","mkdirSync","writeFileSync","renameSync","pause","isRecord","tmpdir","contextKey","union","changedIds","reason","lstat","rm","yamlStringify"],"mappings":"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","file":"lessons.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * Schema version this build WRITES. A graph stamped higher is from a newer CLI.\n * v2 adds the optional lesson `scope: 'always'` (always-on lessons). Reads accept\n * v1 (legacy) and v2 — see {@link VersionSchema}; every write stamps this value, so\n * a v1 graph upgrades to v2 on first mutation. An older CLI reading a v2 graph\n * reports `newer-version` (graph-store) and degrades gracefully rather than\n * choking on the unknown `scope` key under its strict v1 schema.\n */\nexport const CURRENT_GRAPH_VERSION = 2;\n\n/** Versions this build can READ (accepts legacy v1 and current v2). */\nconst VersionSchema = z.union([z.literal(1), z.literal(2)]);\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 * `'always'` marks an ALWAYS-ON lesson: a universal standard delivered on\n * every task (via the UserPromptSubmit hook / a `--always` recall) rather than\n * matched by triggers. Such a lesson needs no trigger and is excluded from\n * triggered recall. Absent = a normal triggered lesson.\n */\n scope: z.literal('always').optional(),\n })\n .strict();\n\nexport const LessonsGraphSchema = z\n .object({\n version: VersionSchema,\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\n/** A graph with no lessons, topics or triggers, at the current schema version. */\nexport function emptyGraph(): LessonsGraph {\n return { version: CURRENT_GRAPH_VERSION, lessons: {}, topics: {}, triggers: {} };\n}\n","/**\n * Raw-pattern passes for glob-parse.ts: star marking and `{a,b}` expansion.\n * Sentinels are control characters, which glob-parse.ts rejects in input.\n */\n\n/** Brace boundary, so `{*,a}*` expands to two stars instead of a globstar. */\nexport const MARK = '\\u0000';\n/** A `*` picomatch guards: it never matches a `.`/`..` segment (see glob-safety). */\nexport const LED = '\\u0001';\n\nconst MAX_EXPANSIONS = 64;\n\nexport function fail(reason: string): never {\n throw new Error(reason);\n}\n\n/** Index just past a `[...]` class starting at `i`, or `i + 1` when unclosed. */\nfunction skipClass(s: string, i: number): number {\n const end = s.indexOf(']', i + 1);\n return end === -1 ? i + 1 : end + 1;\n}\n\n/**\n * Replace each guarded `*` with {@link LED}: a star that starts a segment, or\n * follows a segment-leading `.`, outside any class. picomatch adds its dot guard\n * by the token before the star, so a star right after `{`, `,` or `}` is plain.\n */\nexport function markLedStars(body: string): string {\n let out = '';\n let depth = 0;\n for (let i = 0; i < body.length; ) {\n const c = body[i]!;\n if (c === '[') {\n const end = skipClass(body, i);\n out += body.slice(i, end);\n i = end;\n continue;\n }\n if (c === '{') depth += 1;\n if (c === '}' && depth > 0) depth -= 1;\n const prev = body[i - 1];\n if (c === '*' && prev === '.' && depth > 0) fail('.* inside {…} is not supported');\n const segmentStart = i === 0 || prev === '/';\n const afterLeadingDot = prev === '.' && (i === 1 || body[i - 2] === '/');\n const led =\n c === '*' && body[i + 1] !== '*' && prev !== '*' && (segmentStart || afterLeadingDot);\n out += led ? LED : c;\n i += 1;\n }\n return out;\n}\n\n/** Expand `{a,b}` groups (nested allowed) into at most 64 plain alternatives. */\nexport function expandBraces(s: string): string[] {\n let open = -1;\n for (let i = 0; i < s.length && open === -1; ) {\n if (s[i] === '[') i = skipClass(s, i);\n else if (s[i] === '}') fail('unbalanced }');\n else if (s[i] === '{') open = i;\n else i += 1;\n }\n if (open === -1) return [s];\n const options: string[] = [];\n let depth = 0;\n let start = open + 1;\n let close = -1;\n for (let i = open + 1; i < s.length && close === -1; ) {\n const c = s[i];\n if (c === '[') {\n i = skipClass(s, i);\n continue;\n }\n if (c === '{') depth += 1;\n else if (c === '}' && depth > 0) depth -= 1;\n else if (c === '}') close = i;\n else if (c === ',' && depth === 0) {\n options.push(s.slice(start, i));\n start = i + 1;\n }\n i += 1;\n }\n if (close === -1) fail('unclosed {');\n if (options.length === 0)\n fail('brace groups need a comma, e.g. {a,b} (ranges are not supported)');\n options.push(s.slice(start, close));\n const suffixes = expandBraces(s.slice(close + 1));\n const out: string[] = [];\n for (const option of options) {\n for (const head of expandBraces(option)) {\n for (const tail of suffixes) {\n out.push(s.slice(0, open) + MARK + head + MARK + tail);\n if (out.length > MAX_EXPANSIONS) fail(`more than ${MAX_EXPANSIONS} brace expansions`);\n }\n }\n }\n return out;\n}\n","/**\n * Parser for the `file_glob` subset that glob-safety.ts matches in linear time:\n * literals, `*`, `?`, `**` as a whole segment, `[...]` classes, `{a,b}` groups,\n * a leading `!` (negate) and a leading `./`. picomatch compiles anything beyond\n * that (extglobs, `(…)`/`|` groups, `+` after a class or brace) into raw,\n * backtracking regex, so those are rejected here: the caller gets an error\n * string and the trigger never matches (fail closed).\n */\n\nimport { expandBraces, fail, LED, markLedStars, MARK } from './glob-expand.js';\n\nexport const MAX_GLOB_LENGTH = 256;\n\nexport type GlobToken =\n | { readonly k: 'lit'; readonly ch: string }\n | { readonly k: 'star' }\n | { readonly k: 'one' }\n | { readonly k: 'class'; readonly test: (c: string) => boolean; readonly literal: string | null };\n\nexport type GlobSegment =\n | {\n readonly k: 'globstar';\n /** picomatch: a trailing `/**` after `…*` needs at least one more segment. */\n readonly min1: boolean;\n }\n | {\n readonly k: 'segment';\n readonly tokens: readonly GlobToken[];\n /** The segment text when it has no wildcard (compared directly). */\n readonly literal: string | null;\n /** Starts with a guarded `*`: never `.`/`..`, never an empty last segment. */\n readonly guarded: boolean;\n /** Only unguarded stars, like `{,a}` expanded to empty: may match nothing. */\n readonly matchesEmpty: boolean;\n };\n\nexport interface ParsedGlob {\n readonly negated: boolean;\n /** Brace expansions; the glob matches when any one of them matches. */\n readonly alternatives: readonly (readonly GlobSegment[])[];\n}\n\n/** Parse `pattern`, or return why it is outside the supported subset. */\nexport function parseGlob(pattern: string): ParsedGlob | string {\n try {\n return parseOrThrow(pattern);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n}\n\nfunction parseOrThrow(pattern: string): ParsedGlob {\n if (pattern.length > MAX_GLOB_LENGTH) fail(`longer than ${MAX_GLOB_LENGTH} characters`);\n if (pattern.includes('\\\\')) fail('backslash escapes are not supported (use / as separator)');\n // eslint-disable-next-line no-control-regex\n if (/[\"\\u0000-\\u001f]/.test(pattern)) fail('quotes and control characters are not supported');\n if (/[()|]/.test(pattern.replace(/\\[[^\\]/]*\\]/g, ''))) {\n fail('extglobs and (…)/| groups are not supported (use {a,b})');\n }\n if (/[[\\]{}]\\+/.test(pattern)) fail('+ after a class or brace is a regex quantifier');\n const negated = pattern.startsWith('!');\n let body = negated ? pattern.slice(1) : pattern;\n if (body.startsWith('./')) body = body.slice(2);\n if (body.startsWith('!') || body.startsWith('./')) fail('use a single leading ! and ./');\n if (body === '') fail('empty pattern');\n // picomatch's fast path for exactly `*.*` / `**/*.*` needs a char after the dot.\n const fastPath = !negated && (body === '*.*' || body === '**/*.*');\n if (fastPath) body = `${body.slice(0, -1)}?*`;\n return { negated, alternatives: expandBraces(markLedStars(body)).map(parseAlternative) };\n}\n\nfunction parseAlternative(alt: string): GlobSegment[] {\n const raw = alt.split('/');\n const out: GlobSegment[] = [];\n raw.forEach((segment, i) => {\n if (segment.includes('**')) {\n if (segment !== '**') fail('** must be a whole segment, outside {…} (use * in a segment)');\n if (out.at(-1)?.k === 'globstar') return; // picomatch collapses `**/**`\n const before = raw[i - 1] ?? '';\n const trailing = raw.slice(i + 1).every((s) => s === '**');\n const min1 = trailing && (before.endsWith('*') || before.endsWith(LED));\n out.push({ k: 'globstar', min1 });\n return;\n }\n const tokens = tokenize(segment, alt);\n const guarded = segment.includes(LED);\n const literal = tokens.every((t) => t.k === 'lit')\n ? tokens.map((t) => (t.k === 'lit' ? t.ch : '')).join('')\n : null;\n const matchesEmpty = segment !== '' && !guarded && tokens.every((t) => t.k === 'star');\n out.push({ k: 'segment', tokens, literal, guarded, matchesEmpty });\n });\n return out;\n}\n\nfunction tokenize(segment: string, alt: string): GlobToken[] {\n const tokens: GlobToken[] = [];\n for (let i = 0; i < segment.length; i += 1) {\n const c = segment[i]!;\n if (c === MARK) continue;\n if (c === '*' || c === LED) tokens.push({ k: 'star' });\n else if (c === '?') tokens.push({ k: 'one' });\n else if (c === '[') {\n const end = segment.indexOf(']', i + 1);\n if (end === -1) {\n if (alt.includes(']')) fail('a [...] class cannot span /');\n tokens.push({ k: 'lit', ch: c });\n continue;\n }\n tokens.push(parseClass(segment.slice(i + 1, end)));\n i = end;\n } else tokens.push({ k: 'lit', ch: c });\n }\n return tokens;\n}\n\n/** Characters picomatch treats as regex syntax inside a class body. */\nconst CLASS_SPECIAL = /[-*+?.^${}(|)[\\]]/;\n\nfunction parseClass(body: string): GlobToken {\n if (body === '') fail('empty [] class');\n if (body.startsWith('!')) fail('[!...] is not a negation here; use [^...]');\n if (body.includes('[')) fail('POSIX [:classes:] and nested [ are not supported');\n const negated = body.startsWith('^');\n const members = negated ? body.slice(1) : body;\n if (members === '') fail('empty [^] class');\n const ranges: Array<readonly [string, string]> = [];\n for (let i = 0; i < members.length; i += 1) {\n const lo = members[i]!;\n const hi = members[i + 2];\n if (members[i + 1] === '-' && hi !== undefined) {\n if (hi < lo) fail(`class range out of order: ${lo}-${hi}`);\n ranges.push([lo, hi]);\n i += 2;\n } else ranges.push([lo, lo]);\n }\n const inSet = (c: string): boolean => ranges.some(([lo, hi]) => c >= lo && c <= hi);\n // picomatch also matches the bracket text literally when the body is plain.\n const literal = CLASS_SPECIAL.test(body) ? null : `[${body}]`;\n return { k: 'class', test: negated ? (c) => c !== '/' && !inSet(c) : inSet, literal };\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 { realpathSync, statSync } from 'node:fs';\nimport { join, posix } from 'node:path';\nimport { parseGlob } from './glob-parse.js';\nimport { normalizeRecallFile } from './normalize-query-file.js';\n\n/**\n * Recall matches `file_glob` triggers against project-relative, forward-slash\n * paths, so a captured glob is stored in that one form (`./src/a.ts` and\n * ` src/a.ts` become `src/a.ts`). A glob that could never fire is refused: one\n * outside the project, the project root itself, an existing folder (a folder\n * never matches a file), or one outside the safe glob subset.\n */\n\nconst ABSOLUTE = /^(?:[A-Za-z]:)?\\//;\nconst GLOB_CHARS = /[*?[{]/;\n\nconst CODES = {\n outside: 'TRIGGER_FILE_OUTSIDE_PROJECT',\n root: 'TRIGGER_FILE_IS_PROJECT_ROOT',\n folder: 'TRIGGER_FILE_IS_DIRECTORY',\n unsafe: 'UNSAFE_GLOB_PATTERN',\n} as const;\n\ntype GlobProblem = keyof typeof CODES;\n\nfunction problemMessage(given: string, problem: GlobProblem, detail: string): string {\n switch (problem) {\n case 'outside':\n return (\n `--trigger-file ${given} points outside the project root. File triggers match ` +\n 'project-relative paths, so it would never fire — pass a glob relative to the project ' +\n 'root (e.g. \"src/**/*.ts\").'\n );\n case 'root':\n return (\n `--trigger-file ${given} is the project root itself, and file triggers match files. ` +\n 'Pass a glob such as \"src/**/*.ts\".'\n );\n case 'folder':\n return (\n `--trigger-file ${given} is a folder, and file triggers match files. ` +\n `Use ${JSON.stringify(`${detail}/**`)} to match every file in it.`\n );\n case 'unsafe':\n return (\n `--trigger-file ${given} is outside the safe glob subset: ${detail}. ` +\n 'Use only *, **, ?, [...] and {a,b}.'\n );\n }\n}\n\n/** Thrown when a `--trigger-file` glob could never fire. */\nexport class TriggerFileGlobError extends Error {\n readonly code: (typeof CODES)[GlobProblem];\n constructor(\n public readonly pattern: string,\n problem: GlobProblem = 'outside',\n detail = '',\n ) {\n super(problemMessage(JSON.stringify(pattern), problem, detail));\n this.name = 'TriggerFileGlobError';\n this.code = CODES[problem];\n }\n}\n\n/** True when both paths name the same folder, through any symlink (macOS /tmp is one). */\nfunction sameFolder(a: string, b: string): boolean {\n try {\n return realpathSync(a) === realpathSync(b);\n } catch {\n return false;\n }\n}\n\nfunction isFolder(projectRoot: string, path: string): boolean {\n if (GLOB_CHARS.test(path)) return false;\n return statSync(join(projectRoot, path), { throwIfNoEntry: false })?.isDirectory() === true;\n}\n\n/** Forward-slash, project-relative form of a file glob; throws when it could never fire. */\nexport function projectRelativeGlob(pattern: string, projectRoot: string): string {\n const forward = pattern.trim().replaceAll('\\\\', '/');\n let rel = forward;\n if (ABSOLUTE.test(forward)) {\n const root = projectRoot.replaceAll('\\\\', '/').replace(/\\/+$/, '');\n rel =\n forward.startsWith(`${root}/`) || forward === root\n ? forward.slice(root.length + 1)\n : normalizeRecallFile(forward, projectRoot);\n if (ABSOLUTE.test(rel)) {\n throw new TriggerFileGlobError(\n pattern,\n sameFolder(forward, projectRoot) ? 'root' : 'outside',\n );\n }\n }\n const normalized = posix.normalize(rel === '' ? '.' : rel);\n if (normalized === '..' || normalized.startsWith('../')) {\n throw new TriggerFileGlobError(pattern, 'outside');\n }\n const path = normalized.replace(/\\/+$/, '');\n if (path === '.' || path === '') throw new TriggerFileGlobError(pattern, 'root');\n if (path !== normalized || isFolder(projectRoot, path)) {\n throw new TriggerFileGlobError(pattern, 'folder', path);\n }\n const unsafe = parseGlob(path);\n if (typeof unsafe === 'string') throw new TriggerFileGlobError(pattern, 'unsafe', unsafe);\n return path;\n}\n","import { createHash } from 'node:crypto';\nimport type { AddLessonInput, AddLessonTriggers } from './add.js';\nimport type { Lesson, LessonsGraph, Trigger, TriggerKind } from './graph-schema.js';\nimport { projectRelativeGlob } from './trigger-file-glob.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\n/**\n * Fold a re-captured rule into its existing lesson: union topics, triggers and\n * evidence; the first rationale wins; `--scope always` promotes it to always-on.\n */\nexport function upsertLesson(\n before: Lesson,\n input: AddLessonInput,\n triggerIds: readonly string[],\n): Lesson {\n return {\n ...before,\n topics: union(before.topics, [input.topic]),\n triggers: union(before.triggers, triggerIds),\n evidence: union(before.evidence, input.evidence ?? []),\n ...(before.rationale === undefined && input.rationale !== undefined\n ? { rationale: input.rationale }\n : {}),\n ...(input.scope === 'always' ? { scope: 'always' as const } : {}),\n };\n}\n\n/** What an upsert changed, in a fixed order; empty when the re-add was a no-op. */\nexport function describeUpsert(before: Lesson, after: Lesson): string[] {\n const added = (base: readonly string[], next: readonly string[]): string[] =>\n next.filter((item) => !base.includes(item));\n const topics = added(before.topics, after.topics);\n const triggers = added(before.triggers, after.triggers);\n const evidence = added(before.evidence, after.evidence);\n const changes: string[] = [];\n if (after.scope === 'always' && before.scope !== 'always') changes.push('scope set to always');\n if (topics.length > 0) changes.push(`topic added: ${topics.join(', ')}`);\n if (triggers.length > 0) {\n changes.push(`trigger${triggers.length === 1 ? '' : 's'} attached: ${triggers.join(', ')}`);\n }\n if (evidence.length > 0) changes.push(`evidence added: ${evidence.join(', ')}`);\n if (before.rationale === undefined && after.rationale !== undefined) {\n changes.push('rationale added');\n }\n return changes;\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 */\nexport function 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\ninterface TriggerSpec {\n readonly kind: TriggerKind;\n readonly pattern: string;\n}\n\n/**\n * Resolve/create trigger nodes for the requested patterns; returns referenced +\n * newly-created ids. With `projectRoot`, an absolute file glob inside the\n * project is made relative and one outside it throws TriggerFileGlobError.\n */\nexport function mergeTriggers(\n graph: LessonsGraph,\n spec: AddLessonTriggers,\n projectRoot?: string,\n): { triggerIds: string[]; newTriggerIds: string[] } {\n const requested: TriggerSpec[] = [\n // Recall matches forward-slash, project-relative paths (normalizeRecallFile),\n // so a backslash or absolute pattern stored raw would silently never fire.\n // Normalizing here also dedupes it against the node it equals.\n ...(spec.files ?? []).map(\n (p): TriggerSpec => ({\n kind: 'file_glob',\n pattern:\n projectRoot === undefined ? p.replaceAll('\\\\', '/') : projectRelativeGlob(p, projectRoot),\n }),\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\n/** UTC `YYYY-MM-DD`. */\nexport function todayIso(): string {\n return new Date().toISOString().slice(0, 10);\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\n/**\n * Extensions whose payload is bytes, not text. A skill may ship an image, a\n * font or an archive, and decoding those as UTF-8 replaces every invalid byte\n * with U+FFFD — the file is corrupt before any generator sees it.\n *\n * This is a deliberate allowlist rather than \"anything not in TEXT_EXTENSIONS\":\n * paths outside both sets (`.py`, `.hbs`, the extensionless `.agentsmesh/ignore`)\n * keep their UTF-8 handling, so widening byte mode cannot regress text content.\n */\nconst BINARY_EXTENSIONS = new Set<string>([\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.ico',\n '.webp',\n '.avif',\n '.tiff',\n '.pdf',\n '.zip',\n '.gz',\n '.tgz',\n '.bz2',\n '.xz',\n '.7z',\n '.rar',\n '.jar',\n '.woff',\n '.woff2',\n '.ttf',\n '.otf',\n '.eot',\n '.mp3',\n '.mp4',\n '.wav',\n '.ogg',\n '.webm',\n '.mov',\n '.wasm',\n '.bin',\n '.dat',\n '.db',\n '.sqlite',\n '.so',\n '.dylib',\n '.dll',\n '.exe',\n '.class',\n '.pyc',\n // Office and design documents are zip or proprietary containers.\n '.xlsx',\n '.xls',\n '.docx',\n '.doc',\n '.pptx',\n '.ppt',\n '.odt',\n '.ods',\n '.psd',\n '.ai',\n '.sketch',\n '.fig',\n '.heic',\n '.heif',\n // Archives, columnar data, models and compressed payloads.\n '.tar',\n '.zst',\n '.br',\n '.lz4',\n '.parquet',\n '.avro',\n '.orc',\n '.pkl',\n '.npy',\n '.npz',\n '.onnx',\n '.pt',\n '.safetensors',\n '.gguf',\n '.sqlite3',\n '.avi',\n '.mkv',\n '.flac',\n '.aac',\n '.m4a',\n '.ttc',\n]);\n\nexport function isBinaryPayloadPath(path: string): boolean {\n return BINARY_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\n/**\n * The encoding to read, write and hash a path's payload with. `latin1` maps\n * each byte to exactly one code unit, so bytes survive a round trip through a\n * JS string unchanged — as long as every side of the pipeline agrees, which is\n * why reads, writes and checksums all resolve the encoding here.\n */\nexport function payloadEncodingFor(path: string): 'utf-8' | 'latin1' {\n return isBinaryPayloadPath(path) ? 'latin1' : 'utf-8';\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/**\n * The payload as writeFileAtomic lands it on disk: BOM stripped and CRLF\n * folded to LF for text files, untouched otherwise. Compare or hash through\n * this so in-memory content and its on-disk form never disagree.\n */\nexport function normalizeTextPayload(path: string, content: string): string {\n if (!shouldNormalizeLineEndings(path)) return content;\n return normalizeLineEndings(stripBom(content));\n}\n\n/** `text` without a leading UTF-8 BOM (editors on Windows often add one). */\nexport function stripBom(text: string): string {\n return text.startsWith(UTF8_BOM) ? text.slice(UTF8_BOM.length) : text;\n}\n","import {\n accessSync,\n chmodSync,\n constants,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { stripBom } from '../utils/filesystem/fs-text-encoding.js';\nimport { dirname, resolve } from 'node:path';\nimport { CURRENT_GRAPH_VERSION, parseGraph, type LessonsGraph } from './graph-schema.js';\n\n/** Project-relative path of the lessons graph, forward slashes. */\nexport const LESSONS_GRAPH_PATH = '.agentsmesh/lessons/lessons.json';\n\nexport function graphFilePath(projectRoot: string): string {\n return resolve(projectRoot, LESSONS_GRAPH_PATH);\n}\n\nexport function loadLessonsGraph(projectRoot: string): LessonsGraph {\n const raw = readFileSync(graphFilePath(projectRoot), 'utf8');\n return parseGraph(JSON.parse(stripBom(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(stripBom(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\n/** lessons.json is read-only (a user's choice): nothing is written over it. */\nexport class LessonsGraphReadOnlyError extends Error {\n constructor() {\n super(\n `${LESSONS_GRAPH_PATH} is read-only, so nothing was saved. Make it writable ` +\n `(chmod u+w ${LESSONS_GRAPH_PATH}) to change lessons.`,\n );\n this.name = 'LessonsGraphReadOnlyError';\n }\n}\n\nfunction fileMode(path: string): number | undefined {\n try {\n return statSync(path).mode & 0o777;\n } catch {\n return undefined;\n }\n}\n\nfunction isWritable(path: string): boolean {\n try {\n accessSync(path, constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function saveLessonsGraph(projectRoot: string, graph: LessonsGraph): void {\n const path = graphFilePath(projectRoot);\n mkdirSync(dirname(path), { recursive: true });\n // The rename below would replace a read-only file and reset its mode.\n const mode = fileMode(path);\n if (mode !== undefined && !isWritable(path)) throw new LessonsGraphReadOnlyError();\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 if (mode !== undefined) chmodSync(tmp, mode);\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","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\n/** Thrown when the rule text is empty or whitespace-only — there is nothing to capture. */\nexport class EmptyRuleError extends Error {\n readonly code = 'EMPTY_RULE';\n constructor() {\n super('Lesson rule must not be empty — pass one imperative sentence.');\n this.name = 'EmptyRuleError';\n }\n}\n\n/**\n * Thrown when a `--trigger-cmd` pattern matches the empty string or nearly every\n * command (`.*`, ` `, `\\w`). Such a trigger fires on every recall, so it is a\n * leak that dilutes every command-shaped lesson rather than a trigger.\n */\nexport class BroadCommandPatternError extends Error {\n readonly code = 'BROAD_COMMAND_PATTERN';\n constructor(public readonly pattern: string) {\n super(\n `Command pattern ${JSON.stringify(pattern)} matches nearly every command, so it would fire on ` +\n 'every recall. Key it on the action instead — a word-bounded program + subcommand ' +\n '(e.g. \"\\\\bgit commit\\\\b\", \"\\\\brm\\\\b\").',\n );\n this.name = 'BroadCommandPatternError';\n }\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/** Thrown when a topic id is not kebab-case, so the graph schema would reject it. */\nexport class InvalidTopicIdError extends Error {\n readonly code = 'INVALID_TOPIC_ID';\n constructor(public readonly topic: string) {\n const slug = topic\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n super(\n `Topic id ${JSON.stringify(topic)} must be kebab-case (lowercase letters, digits and -)` +\n (slug.length > 0 ? `, e.g. ${JSON.stringify(slug)}.` : '.'),\n );\n this.name = 'InvalidTopicIdError';\n }\n}\n\n/** Thrown when a capture creates a topic without a (non-blank) summary. */\nexport class TopicSummaryRequiredError extends Error {\n readonly code = 'TOPIC_SUMMARY_REQUIRED';\n constructor(public readonly topic: string) {\n super(\n `New topic ${JSON.stringify(topic)} needs a one-line summary (--topic-summary on the CLI, ` +\n 'topic_summary over MCP).',\n );\n this.name = 'TopicSummaryRequiredError';\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","/** 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\n * rejected (fail closed): it reads as a code point but, without the `u` flag,\n * matches the literal text `u{…}`.\n */\nexport function readUnicodeEscape(src: string, i: number, c: string): { ch: string; len: number } {\n if (c === 'u' && src[i] === '{') {\n throw new UnsupportedRegexError('\\\\u{…} code point escapes are not supported; use \\\\uHHHH');\n }\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 are dead triggers: capture drops them (DEAD_COMMAND_PATTERN), the\n * write barrier and validate flag stored ones (INVALID_/UNSAFE_TRIGGER_PATTERN),\n * and recall skips them: 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 { getCommandMatcher } from './regex-safety.js';\n\n/**\n * Breadth guardrail for `command_pattern` triggers. A pattern that matches the\n * empty string (`.*`, `^`, `x*`, `(git)?`) or nearly every command (` `, `.`,\n * `\\w`) fires on EVERY recall — it is not a trigger, it is a leak that dilutes\n * every command-shaped lesson. Breadth is probed empirically against a fixed\n * corpus of unrelated commands, so the verdict is deterministic and does not\n * depend on regex-shape heuristics. Invalid or unsafe patterns are never\n * \"broad\": those fall through to the existing INVALID/UNSAFE rejection.\n */\n\n/** Twenty unrelated commands; a pattern hitting most of them is a leak, not a trigger. */\nexport const COMMAND_PROBE_CORPUS: readonly string[] = [\n 'git status',\n 'git commit -m \"wip\"',\n 'pnpm test',\n 'npx vitest run src/x.test.ts',\n 'ls -la',\n 'cat README.md',\n 'rm -rf dist',\n 'mkdir -p build/out',\n 'node scripts/build.js',\n 'docker compose up -d',\n 'curl -s https://example.com',\n 'echo hello > out.txt',\n \"sed -i 's/a/b/' file.txt\",\n 'pnpm lint --fix',\n 'python3 -m pytest',\n 'cargo build --release',\n 'make',\n 'npm install --global typescript',\n 'cp a.txt b.txt',\n 'grep -rn TODO src',\n];\n\n/** Broad when the pattern hits MORE than this share of the probe corpus. */\nconst BROAD_HIT_RATIO = 0.5;\n\n/** Generous per-probe work bound; the corpus is tiny, so this never trips a real pattern. */\nconst PROBE_BUDGET = 100_000;\n\n/** True when `pattern` matches the empty string or most of the probe corpus. */\nexport function isBroadCommandPattern(pattern: string): boolean {\n const matcher = getCommandMatcher(pattern);\n if (matcher === null) return false;\n if (matcher.test('', { remaining: PROBE_BUDGET })) return true;\n let hits = 0;\n for (const command of COMMAND_PROBE_CORPUS) {\n if (matcher.test(command, { remaining: PROBE_BUDGET })) hits += 1;\n }\n return hits > COMMAND_PROBE_CORPUS.length * BROAD_HIT_RATIO;\n}\n","import { MAX_RULE_LENGTH } from './graph-schema.js';\n\n/**\n * Bounds for rule text on its way into an agent's context. A graph from a\n * cloned repo is untrusted input: a rule may be megabytes long, or carry line\n * breaks that fake the end of the recalled list and a \"system\" message after it.\n */\n\n/** Delimiters of the fenced recalled-lessons block in hook output. */\nexport const RECALL_BLOCK_OPEN = '<recalled-lessons>';\nexport const RECALL_BLOCK_CLOSE = '</recalled-lessons>';\n\n/** Total rule characters one CLI, MCP or hook answer may carry (~8k tokens). */\nexport const MAX_RECALL_PAYLOAD_CHARS = 32_000;\n\nconst TRUNCATION_MARK = ' …[truncated]';\nconst LINE_BREAKS = /\\s*[\\p{Cc}\\p{Zl}\\p{Zp}]+\\s*/gu;\n/** Invisible format characters: zero-width spaces and joiners, BOM, bidi controls. */\nconst FORMAT_CHARS = /\\p{Cf}/gu;\n/** `<` and its full-width and small forms. */\nconst LESS_THAN = /[<\\uFF1C\\uFE64]/gu;\n/** What may sit between `<` and the tag name: spaces, slash look-alikes, combining marks. */\nconst TAG_GAP = /^[\\s/\\uFF0F\\u2044\\u2215\\u29F8\\p{M}]*/u;\n/** The tag name, with dash look-alikes, after compatibility folding. */\nconst TAG_NAME = /^recalled[-\\u2010-\\u2015\\u2212]lessons/iu;\n/** Room for the tag name even when each letter takes two UTF-16 units. */\nconst TAG_WINDOW = 64;\n\n/** UTF-16 index just past the first `count` characters (code points) of `text`. */\nfunction codePointIndex(text: string, count: number): number {\n let index = 0;\n for (let seen = 0; seen < count && index < text.length; seen++) {\n const unit = text.charCodeAt(index);\n const next = text.charCodeAt(index + 1);\n index += unit >= 0xd800 && unit <= 0xdbff && next >= 0xdc00 && next <= 0xdfff ? 2 : 1;\n }\n return index;\n}\n\n/** Length in characters (code points), so an emoji counts once, not twice. */\nexport function codePointLength(text: string): number {\n return [...text].length;\n}\n\n/** Cut `rule` to at most `max` characters (code points), never inside a surrogate pair. */\nexport function clampText(rule: string, max: number = MAX_RULE_LENGTH): string {\n if (codePointIndex(rule, max) === rule.length) return rule;\n const end = codePointIndex(rule, Math.max(0, max - TRUNCATION_MARK.length));\n return rule.slice(0, end) + TRUNCATION_MARK;\n}\n\n/** True when `text` starts with the tag name, in any compatibility or accented spelling. */\nfunction startsWithTagName(text: string): boolean {\n const gap = TAG_GAP.exec(text)?.[0].length ?? 0;\n const window = text\n .slice(gap, gap + TAG_WINDOW)\n .normalize('NFKD')\n .replace(/\\p{M}/gu, '');\n return TAG_NAME.test(window);\n}\n\n/**\n * `rule` as one clamped line: format characters are dropped, control characters\n * and line or paragraph separators become single spaces, and every `<` look-alike\n * that starts a spelling of the block tag becomes `‹`, so it cannot close the\n * fence early.\n */\nexport function safeRuleLine(rule: string, max: number = MAX_RULE_LENGTH): string {\n const oneLine = rule.replace(FORMAT_CHARS, '').replace(LINE_BREAKS, ' ').trim();\n const line = clampText(oneLine, max);\n return line.replace(LESS_THAN, (lt: string, offset: number) =>\n startsWithTagName(line.slice(offset + 1)) ? '‹' : lt,\n );\n}\n\n/**\n * Keep items in order while their summed size fits `max`. The first item is\n * always kept (it is already clamped), so an answer is never empty.\n */\nexport function capRulePayload<T>(\n items: readonly T[],\n size: (item: T) => number,\n max: number = MAX_RECALL_PAYLOAD_CHARS,\n): { kept: T[]; dropped: number } {\n const kept: T[] = [];\n let used = 0;\n for (const item of items) {\n const cost = size(item);\n if (kept.length > 0 && used + cost > max) break;\n used += cost;\n kept.push(item);\n }\n return { kept, dropped: items.length - kept.length };\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 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 / PENDING_GLOB guardrails), 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/**\n * Dead non-command triggers (the keyword-dead case), for the add gate. A dead\n * `command_pattern` is excluded here: the add gate drops it first with a\n * DEAD_COMMAND_PATTERN warning (see `dropDeadCommandTriggers` in add-gates.ts).\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 {\n BroadCommandPatternError,\n EmptyRuleError,\n InvalidTopicIdError,\n NoTriggerError,\n RuleTooLongError,\n TopicSummaryRequiredError,\n UnknownTopicError,\n UnrecallableLessonError,\n} from './add-errors.js';\nimport type { AddLessonInput, AddLessonOptions } from './add.js';\nimport { isBroadCommandPattern } from './command-pattern-breadth.js';\nimport { MAX_RULE_LENGTH, type LessonsGraph } from './graph-schema.js';\nimport { codePointLength } from './rule-line.js';\nimport {\n blockingDeadTriggers,\n ineffectiveTriggers,\n type IneffectiveTrigger,\n} from './trigger-effectiveness.js';\n\n/**\n * Blocking capture gates for {@link addLessonInto}. Each throws a dedicated\n * rejection error BEFORE the transactional write barrier, so a rejected capture\n * persists nothing and surfaces a precise, actionable reason (CLI exit 2 with\n * the add hint; MCP VALIDATION_FAILED with the machine code).\n */\n\n/** Trim the rule, rejecting an empty or over-long one (a malformed capture). */\nexport function assertRuleShape(rule: string): string {\n const trimmed = rule.trim();\n if (trimmed.length === 0) throw new EmptyRuleError();\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 const length = codePointLength(trimmed);\n if (length > MAX_RULE_LENGTH) throw new RuleTooLongError(length, MAX_RULE_LENGTH);\n return trimmed;\n}\n\n/**\n * Check the topic id and create a new topic when allowed. Returns whether the\n * topic is new. Runs before the trigger gates, so a topic error wins.\n */\nexport function ensureTopic(\n graph: LessonsGraph,\n topic: string,\n options: AddLessonOptions,\n): boolean {\n if (!/^[a-z0-9-]+$/.test(topic)) throw new InvalidTopicIdError(topic);\n if (graph.topics[topic] !== undefined) return false;\n if (options.allowNewTopic !== true) throw new UnknownTopicError(topic);\n const summary = options.topicSummary?.trim() ?? '';\n if (summary.length === 0) throw new TopicSummaryRequiredError(topic);\n graph.topics[topic] = { summary };\n return true;\n}\n\n/**\n * An ALWAYS-ON lesson (scope:'always') is delivered on every task, not matched\n * by triggers, so it needs none — the trigger gates are skipped for it (as\n * legacy-merge recovery also does).\n */\nexport function skipsTriggerGates(input: AddLessonInput, options: AddLessonOptions): boolean {\n return options.allowNoTrigger === true || input.scope === 'always';\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\n/**\n * Gates on the INPUT triggers, before any trigger node is created.\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).\n * - A command pattern that matches nearly every command is a leak, not a\n * trigger. Legacy-merge recovery folds historical lessons as-is (`validate`\n * surfaces them as BROAD_COMMAND_PATTERN).\n */\nexport function assertTriggerInputs(\n input: AddLessonInput,\n options: AddLessonOptions,\n existingTriggerCount: number,\n): void {\n if (\n !skipsTriggerGates(input, options) &&\n countInputTriggers(input.triggers) === 0 &&\n existingTriggerCount === 0\n ) {\n throw new NoTriggerError();\n }\n if (options.allowNoTrigger !== true) {\n const broad = (input.triggers.commands ?? []).find(isBroadCommandPattern);\n if (broad !== undefined) throw new BroadCommandPatternError(broad);\n }\n}\n\n/** Warning for a command trigger dropped at capture because it can never fire. */\nexport interface DeadCommandWarning {\n readonly code: 'DEAD_COMMAND_PATTERN';\n readonly message: string;\n}\n\ninterface MergedTriggers {\n readonly triggerIds: string[];\n readonly newTriggerIds: string[];\n}\n\n/**\n * Drop the input command triggers that can never fire (an invalid regex, or one\n * the linear engine cannot run) instead of letting the write barrier refuse the\n * whole capture: the lesson keeps its live triggers and the caller is warned. A\n * node created for a dropped pattern is removed again, so it is never written.\n * Legacy-merge recovery (`allowNoTrigger`) keeps folding lessons as-is.\n */\nexport function dropDeadCommandTriggers(\n graph: LessonsGraph,\n merged: MergedTriggers,\n options: AddLessonOptions,\n): MergedTriggers & { readonly dropped: IneffectiveTrigger[] } {\n if (options.allowNoTrigger === true) return { ...merged, dropped: [] };\n const dropped = ineffectiveTriggers(graph, merged.triggerIds).filter(\n (t) => t.kind === 'command_pattern',\n );\n const dead = new Set(dropped.map((t) => t.id));\n for (const id of merged.newTriggerIds) if (dead.has(id)) delete graph.triggers[id];\n return {\n triggerIds: merged.triggerIds.filter((id) => !dead.has(id)),\n newTriggerIds: merged.newTriggerIds.filter((id) => !dead.has(id)),\n dropped,\n };\n}\n\nexport function deadCommandWarning(trigger: IneffectiveTrigger): DeadCommandWarning {\n return {\n code: 'DEAD_COMMAND_PATTERN',\n message: `Dropped command trigger ${JSON.stringify(trigger.pattern)} (not saved): ${trigger.reason}.`,\n };\n}\n\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. `dropped` are the\n * dead command triggers already removed from that set; when nothing live is\n * left they are named too. A throw here aborts the transactional write, so\n * nothing is persisted.\n */\nexport function assertRecallable(\n graph: LessonsGraph,\n resultingTriggers: readonly string[],\n dropped: readonly IneffectiveTrigger[],\n): void {\n const blockingDead = blockingDeadTriggers(graph, resultingTriggers);\n const dead = [...dropped, ...blockingDead];\n if (dead.length > 0 && blockingDead.length === resultingTriggers.length) {\n throw new UnrecallableLessonError(dead);\n }\n}\n","/**\n * How narrow a `file_glob` trigger is.\n *\n * Trigger ids are content-addressed, so two lessons never share a pattern and\n * the fanout signal alone cannot tell `src/lessons/recall.ts` from\n * `src/lessons/**` — both are referenced once and both score maximum\n * specificity. Recall then delivers a subsystem-wide rule ahead of the one rule\n * written about the file being edited, and the token budget drops the rest.\n *\n * Narrowness is the share of path segments the pattern pins down literally. A\n * `**` counts as no literal segment AND widens the denominator, because it can\n * span any depth. A negated glob matches every path but its own, so it scores 0.\n */\n\nconst WILDCARD = /[*?[\\]]/;\n\n/** A leading `!` (see glob-parse.ts): the trigger fires on every path it does NOT match. */\nexport function isNegatedGlob(pattern: string): boolean {\n return pattern.startsWith('!');\n}\n\n/** Narrowness in [0,1]: 1 = an exact path, 0 = matches the whole tree. */\nexport function globNarrowness(pattern: string): number {\n if (isNegatedGlob(pattern)) return 0;\n const segments = pattern\n .replaceAll('\\\\', '/')\n .split('/')\n .filter((segment) => segment !== '' && segment !== '.');\n if (segments.length === 0) return 0;\n let literal = 0;\n let globstars = 0;\n for (const segment of segments) {\n if (segment === '**') globstars += 1;\n else if (!WILDCARD.test(segment)) literal += 1;\n }\n return literal / (segments.length + globstars);\n}\n\n/**\n * Broad enough that recall would fire it on most of the repo. Advisory only:\n * a deliberate file-CLASS trigger such as a per-target `index.ts` pattern is the\n * documented way to write a rule about general behaviour, so this never blocks\n * a capture.\n */\nexport const BROAD_GLOB_NARROWNESS = 0.34;\n\nexport function isBroadFileGlob(pattern: string): boolean {\n return globNarrowness(pattern) < BROAD_GLOB_NARROWNESS;\n}\n","/**\n * Dynamic-programming core of the linear glob matcher (see glob-safety.ts).\n * Two nested tables: pattern segments × path segments, and inside one segment,\n * tokens × characters. No backtracking, so cost is O(pattern × path); every\n * cell is charged to `work` and an exhausted budget returns false.\n */\n\nimport type { GlobSegment, GlobToken } from './glob-parse.js';\nimport type { WorkBudget } from './regex-linear/index.js';\n\nconst isDotSegment = (s: string): boolean => s === '.' || s === '..';\n\n/** DP over (pattern segment i, path segment j): does alt[i..] match segments[j..]? */\nexport function matchSegments(\n alt: readonly GlobSegment[],\n segments: string[],\n work: WorkBudget,\n): boolean {\n const n = segments.length;\n let next = new Uint8Array(n + 1);\n next[n] = 1;\n for (let i = alt.length - 1; i >= 0; i -= 1) {\n const seg = alt[i]!;\n const cur = new Uint8Array(n + 1);\n for (let j = n; j >= 0; j -= 1) {\n if (--work.remaining <= 0) return false;\n if (seg.k === 'globstar') {\n const eat = j < n && !isDotSegment(segments[j]!) && (cur[j + 1] === 1 || next[j + 1] === 1);\n cur[j] = (!seg.min1 && next[j] === 1) || eat ? 1 : 0;\n } else if (j < n && next[j + 1] === 1) {\n const text = segments[j]!;\n const ok =\n seg.literal !== null ? text === seg.literal : matchSegment(seg, text, j < n - 1, work);\n cur[j] = ok ? 1 : 0;\n }\n }\n // Set after the loop so a globstar that consumed segments cannot use it.\n if (seg.k === 'globstar' && i >= 1 && tailMatchesNothing(alt, i + 1)) cur[n] = 1;\n next = cur;\n }\n return next[0] === 1;\n}\n\n/**\n * picomatch quirk: a globstar followed by a segment like `{,a}` (optionally then\n * one more globstar) also matches when the path ends right before the globstar.\n */\nfunction tailMatchesNothing(alt: readonly GlobSegment[], from: number): boolean {\n const empty = alt[from];\n const rest = alt[from + 1];\n if (empty?.k !== 'segment' || !empty.matchesEmpty) return false;\n return rest === undefined || (rest.k === 'globstar' && !rest.min1 && from + 2 === alt.length);\n}\n\n/** DP over (token k, char c) within one segment. */\nfunction matchSegment(\n seg: Extract<GlobSegment, { k: 'segment' }>,\n text: string,\n followedBySlash: boolean,\n work: WorkBudget,\n): boolean {\n if (seg.guarded && (isDotSegment(text) || (text === '' && !followedBySlash))) return false;\n const tokens = seg.tokens;\n const len = text.length;\n let next = new Uint8Array(len + 1);\n next[len] = 1;\n for (let k = tokens.length - 1; k >= 0; k -= 1) {\n const tok = tokens[k]!;\n const cur = new Uint8Array(len + 1);\n work.remaining -= len + 1;\n if (work.remaining <= 0) return false;\n for (let c = len; c >= 0; c -= 1) {\n cur[c] = tokenMatches(tok, text, c, next, cur) ? 1 : 0;\n }\n next = cur;\n }\n return next[0] === 1;\n}\n\nfunction tokenMatches(\n tok: GlobToken,\n text: string,\n c: number,\n next: Uint8Array,\n cur: Uint8Array,\n): boolean {\n const ch = text[c];\n switch (tok.k) {\n case 'star':\n return next[c] === 1 || (ch !== undefined && cur[c + 1] === 1);\n case 'one':\n return ch !== undefined && next[c + 1] === 1;\n case 'lit':\n return ch === tok.ch && next[c + 1] === 1;\n case 'class':\n return (\n (ch !== undefined && tok.test(ch) && next[c + 1] === 1) ||\n (tok.literal !== null &&\n text.startsWith(tok.literal, c) &&\n next[c + tok.literal.length] === 1)\n );\n }\n}\n","/**\n * Linear-time matcher for `file_glob` triggers.\n *\n * Recall runs every glob against the edited file on a mandatory hot path.\n * picomatch compiles globs to backtracking RegExps, and a crafted glob (nested\n * extglobs, many `*` in one segment, `(a+)+` passed through as regex) can take\n * seconds to minutes per file. Here a glob from the safe subset (glob-parse.ts)\n * is matched by dynamic programming (glob-dp.ts) over path segments and\n * characters, so the cost is O(pattern × path) and capped by a work budget. Results equal\n * picomatch({ dot: true }) on recall-shaped paths (project-relative, optional\n * leading `../`, no empty or trailing-slash segments); the parity test fuzzes it.\n */\n\nimport { matchSegments } from './glob-dp.js';\nimport { parseGlob, type GlobSegment, type ParsedGlob } from './glob-parse.js';\nimport type { Trigger } from './graph-schema.js';\nimport type { WorkBudget } from './regex-linear/index.js';\nimport type { ValidationFinding } from './validate.js';\n\n/** Longer inputs are not real paths; they never match. */\nexport const MAX_GLOB_PATH_LENGTH = 4096;\n/** Per-match cap on DP cells (~1 ms); a legitimate match uses a few hundred. */\nconst MATCH_WORK_LIMIT = 200_000;\nconst CACHE_LIMIT = 2000;\n\nexport interface GlobMatcher {\n /** True when `path` matches. Charges `budget` when given; out of work = no match. */\n test(path: string, budget?: WorkBudget): boolean;\n}\n\nconst cache = new Map<string, GlobMatcher | null>();\n\n/** UNSAFE_GLOB_PATTERN finding for validate; backslash globs have their own code. */\nexport function unsafeGlobFinding(triggerId: string, trigger: Trigger): ValidationFinding | null {\n if (trigger.kind !== 'file_glob' || trigger.pattern.includes('\\\\')) return null;\n const reason = parseGlob(trigger.pattern);\n if (typeof reason !== 'string') return null;\n return {\n level: 'error',\n code: 'UNSAFE_GLOB_PATTERN',\n message: `Trigger \"${triggerId}\" has a file_glob outside the safe glob subset (${trigger.pattern.slice(0, 120)}): ${reason}. Recall treats it as a non-match. Use only *, **, ?, [...] and {a,b}.`,\n triggerId,\n };\n}\n\n/** A linear-time matcher for `pattern`, or null when it is unsafe (never matches). */\nexport function getGlobMatcher(pattern: string): GlobMatcher | null {\n const hit = cache.get(pattern);\n if (hit !== undefined) return hit;\n if (cache.size >= CACHE_LIMIT) cache.clear();\n // Compare composed (NFC) forms: macOS can hand over decomposed (NFD) paths.\n const composed = pattern.normalize('NFC');\n const parsed = parseGlob(composed);\n const matcher = typeof parsed === 'string' ? null : build(composed, parsed);\n cache.set(pattern, matcher);\n return matcher;\n}\n\nfunction build(pattern: string, parsed: ParsedGlob): GlobMatcher {\n const alts = parsed.alternatives.map(prepare);\n return {\n test(rawPath: string, budget?: WorkBudget): boolean {\n const path = rawPath.normalize('NFC');\n if (path === pattern) return true; // picomatch's literal-equality shortcut\n if (path === '' || path.length > MAX_GLOB_PATH_LENGTH) return false;\n const live = alts.filter((a) => mayMatch(a, path));\n if (live.length === 0) return parsed.negated;\n const limit = Math.min(MATCH_WORK_LIMIT, budget?.remaining ?? MATCH_WORK_LIMIT);\n const work: WorkBudget = { remaining: limit };\n const segments = path.split('/');\n const hit = live.some((a) => matchSegments(a.alt, segments, work));\n if (budget !== undefined) budget.remaining -= limit - work.remaining;\n return work.remaining > 0 && hit !== parsed.negated;\n },\n };\n}\n\n/** An alternative plus cheap necessary conditions checked before the DP. */\ninterface PreparedAlt {\n readonly alt: readonly GlobSegment[];\n /** Literal first segment: must equal the first path segment. */\n readonly head: string | null;\n /** Literal end of the last segment: the path must end with it. */\n readonly tail: string;\n}\n\nfunction mayMatch({ head, tail }: PreparedAlt, path: string): boolean {\n if (!path.endsWith(tail)) return false;\n if (head === null) return true;\n return path.startsWith(head) && (path.length === head.length || path[head.length] === '/');\n}\n\nfunction prepare(alt: readonly GlobSegment[]): PreparedAlt {\n const first = alt[0];\n const last = alt[alt.length - 1];\n let tail = '';\n if (last?.k === 'segment' && !last.matchesEmpty) {\n for (let k = last.tokens.length - 1; k >= 0; k -= 1) {\n const tok = last.tokens[k]!;\n if (tok.k !== 'lit') break;\n tail = tok.ch + tail;\n }\n }\n return { alt, head: first?.k === 'segment' ? first.literal : null, tail };\n}\n","import picomatch from 'picomatch';\nimport type { GitPathHistory } from './git-path-history.js';\nimport { getGlobMatcher } from './glob-safety.js';\n\n/**\n * Verdict for a `file_glob` that matches no file on disk:\n * - `live`: it matches a tracked path (deleted from disk but not committed).\n * - `dead`: HEAD history removed what it matched, so it can never fire again\n * without a re-point. Only this state may be detached.\n * - `pending`: no proof of removal. The path may not exist yet, be ignored build\n * output, live on another branch, or git evidence is missing. Kept.\n *\n * A wildcard glob is dead only when its paths were renamed away: deleted-only\n * matches are a class of files that come and go (a release deletes every\n * changeset, the next change adds one). A glob outside the safe subset is\n * never judged: it stays `pending`.\n */\nexport type MissingGlobState = 'live' | 'dead' | 'pending';\n\nexport function missingGlobState(\n pattern: string,\n history: GitPathHistory | null,\n): MissingGlobState {\n const matcher = getGlobMatcher(pattern);\n if (history === null || matcher === null) return 'pending';\n const matchesAny = (paths: ReadonlySet<string>): boolean =>\n [...paths].some((p) => matcher.test(p));\n if (matchesAny(history.tracked)) return 'live';\n if (matchesAny(history.renamedAway)) return 'dead';\n if (!picomatch.scan(pattern).isGlob && matchesAny(history.deleted)) return 'dead';\n return 'pending';\n}\n","import { spawnSync } from 'node:child_process';\n\ninterface GitResult {\n readonly status: number;\n readonly stdout: string;\n readonly stderr: string;\n}\n\nconst MAX_OUTPUT_BYTES = 64 * 1024 * 1024;\n\nexport type GitRunner = (cwd: string, args: readonly string[]) => GitResult;\n\n/**\n * Run git synchronously in `cwd`. Status is -1 when git could not start, ran\n * past `timeoutMs`, or overflowed the output cap.\n */\nexport function runGit(cwd: string, args: readonly string[], timeoutMs?: number): GitResult {\n const r = spawnSync('git', [...args], {\n cwd,\n encoding: 'utf8',\n maxBuffer: MAX_OUTPUT_BYTES,\n timeout: timeoutMs,\n windowsHide: true,\n });\n const status = r.error === undefined ? (r.status ?? -1) : -1;\n return { status, stdout: r.stdout ?? '', stderr: r.stderr ?? '' };\n}\n","import { runGit } from './git-exec.js';\n\n/**\n * What git knows about project paths, for `file_glob` liveness. All paths are\n * relative to the project root, forward-slash.\n */\nexport interface GitPathHistory {\n /** Paths in the index: live even while missing from disk. */\n readonly tracked: ReadonlySet<string>;\n /** Paths a commit reachable from HEAD deleted. */\n readonly deleted: ReadonlySet<string>;\n /** Old side of every rename reachable from HEAD. */\n readonly renamedAway: ReadonlySet<string>;\n}\n\n/** Bound per git call. A slower scan reads as unknown, never as dead. */\nconst GIT_SCAN_TIMEOUT_MS = 3_000;\n\nconst cache = new Map<string, GitPathHistory | null>();\n\n/** {@link scanGitPathHistory}, run once per project root per process. */\nexport function readGitPathHistory(projectRoot: string): GitPathHistory | null {\n if (!cache.has(projectRoot)) cache.set(projectRoot, scanGitPathHistory(projectRoot));\n return cache.get(projectRoot) ?? null;\n}\n\n// A pathspec would be faster, but it turns a rename out of the pathspec into a\n// plain deletion, which loses the rename proof wildcard globs need.\nconst LOG_ARGS = [\n 'log',\n 'HEAD',\n '--relative',\n '-M',\n '--diff-filter=DR',\n '--name-status',\n '-z',\n '--no-color',\n '--no-show-signature',\n '--pretty=format:',\n];\n\n/**\n * Tracked paths plus the deletions and renames in HEAD's history. `null` means\n * unknown: not a git work tree, no commit yet, or git failed or ran past\n * `timeoutMs`. HEAD only, so a removal on an unmerged branch never counts here.\n * Cost is linear in history: about 0.3 s for 1k commits, 0.55 s for 2.6k.\n */\nexport function scanGitPathHistory(\n projectRoot: string,\n timeoutMs: number = GIT_SCAN_TIMEOUT_MS,\n): GitPathHistory | null {\n const tracked = runGit(projectRoot, ['ls-files', '-z'], timeoutMs);\n if (tracked.status !== 0) return null;\n const log = runGit(projectRoot, LOG_ARGS, timeoutMs);\n if (log.status !== 0) return null;\n return {\n tracked: new Set(tracked.stdout.split('\\0').filter(Boolean)),\n ...parseRemovals(log.stdout),\n };\n}\n\n// `-z` name-status output: a status token, then one path (D) or old + new (R).\nfunction parseRemovals(out: string): Pick<GitPathHistory, 'deleted' | 'renamedAway'> {\n const deleted = new Set<string>();\n const renamedAway = new Set<string>();\n const tokens = out.split('\\0');\n for (let i = 0; i < tokens.length; i += 1) {\n const status = tokens[i] ?? '';\n const path = tokens[i + 1] ?? '';\n if (status.startsWith('D')) {\n if (path !== '') deleted.add(path);\n i += 1;\n } else if (status.startsWith('R')) {\n if (path !== '') renamedAway.add(path);\n i += 2;\n }\n }\n return { deleted, renamedAway };\n}\n","import { existsSync, realpathSync } from 'node:fs';\nimport { homedir } from 'node:os';\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 * The directory whose lessons apply to `start`: `start` itself when it holds a\n * graph or a lessons config, else the nearest ancestor that does, else `start`.\n *\n * The recall hook, the MCP server and the lessons CLI all resolve from here,\n * so running in a package of a monorepo (or any subfolder) finds the project.\n */\nexport function resolveLessonsRoot(start: string): string {\n const origin = resolve(start);\n return findLessonsRoot(origin) ?? origin;\n}\n\n/**\n * The nearest of `start` and its ancestors holding a graph or a lessons config,\n * or null. Keys off `.agentsmesh/lessons/` artifacts, never a bare\n * `.agentsmesh`: the global config lives in `~/.agentsmesh` and holds no graph.\n */\nexport function findLessonsRoot(start: string): string | null {\n return findUp(resolve(start), hasLessonsAt);\n}\n\n/**\n * Where the MCP lessons tools read and write: the nearest lessons root, else\n * the nearest agentsmesh project (`agentsmesh.yaml`), else the git work tree,\n * else null — outside any project there is nowhere a captured lesson belongs.\n */\nexport function findLessonsProjectRoot(start: string): string | null {\n const origin = resolve(start);\n return (\n findLessonsRoot(origin) ??\n findUp(origin, (dir) => existsSync(join(dir, 'agentsmesh.yaml'))) ??\n // Plugin-only use has no agentsmesh.yaml: the repository is the project.\n findUp(origin, (dir) => existsSync(join(dir, '.git')))\n );\n}\n\nfunction hasLessonsAt(dir: string): boolean {\n const paths = lessonsPaths(dir);\n return existsSync(paths.graph) || existsSync(paths.config);\n}\n\n/**\n * The first of `start` and its ancestors where `hit` holds, or null. The walk\n * stops below the home directory: lessons belong to a repository, and a graph\n * under `~` would otherwise apply to every folder beneath it.\n */\nfunction findUp(start: string, hit: (dir: string) => boolean): string | null {\n const stops = homeDirs();\n let dir = start;\n let prev = '';\n while (dir !== prev && !stops.has(dir)) {\n if (hit(dir)) return dir;\n prev = dir;\n dir = dirname(dir);\n }\n return null;\n}\n\n/** True for the home folder, whose `.agentsmesh` is the global config, never a lessons project. */\nexport function isHomeDirectory(dir: string): boolean {\n return homeDirs().has(resolve(dir));\n}\n\n/** The home directory as given and as resolved: HOME may be a symlink (macOS `/tmp`). */\nfunction homeDirs(): ReadonlySet<string> {\n const home = homedir();\n if (home === '') return new Set();\n const dirs = new Set([resolve(home)]);\n try {\n dirs.add(realpathSync(home));\n } catch {\n // A home that does not exist has no other name.\n }\n return dirs;\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)\n\nGraph \\`.agentsmesh/lessons/lessons.json\\` is canonical; never hand-edit it. Manual: \\`lessons\\` skill.\n\n**Recall:** before every file edit or state-changing command, MUST run \\`agentsmesh lessons query --file <path> --cmd <command> --session auto\\` and obey matches; at task start, ALSO run \\`agentsmesh lessons query --keyword \"<task terms>\" --always --session auto\\` for conceptual + universal rules no path/command names. Pure-read commands and recall itself are exempt.\n\n**Capture:** after any failure, user correction, regression, wrong assumption, useful surprise, repeated friction, or non-obvious fix, MUST self-critique and run \\`agentsmesh lessons add \"<imperative rule>\" --topic <id> --trigger-file <glob> --evidence <sha|lesson-id>\\`.\n\n**Before final:** report \\`Lesson: captured <id>\\` or \\`Lesson: none\\`. No recall/capture gate = task incomplete. No shell: use \\`lessons_query\\` / \\`lessons_add\\`.`;\n","import { readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type GitPathHistory, readGitPathHistory } from './git-path-history.js';\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 * a glob over a present-but-gitignored build artifact must read as LIVE.\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/** On-disk project files plus the git evidence that decides whether a missing glob is dead. */\nexport interface ProjectFiles extends ReadonlySet<string> {\n /** Read lazily (only when some glob matches nothing on disk); null = no evidence. */\n readonly gitHistory: () => GitPathHistory | null;\n}\n\nexport function projectFilesOf(\n paths: Iterable<string>,\n gitHistory: () => GitPathHistory | null,\n): ProjectFiles {\n return Object.assign(new Set(paths), { gitHistory });\n}\n\n/** Git evidence carried by `paths`; null for a plain set, so nothing can be proven dead. */\nexport function gitHistoryOf(paths: ReadonlySet<string>): GitPathHistory | null {\n return (paths as Partial<ProjectFiles>).gitHistory?.() ?? null;\n}\n\n/**\n * The on-disk file list (project-relative, forward-slash) used by the\n * `file_glob` liveness checks, with the project's git evidence attached — or\n * `null` (unknown) when it cannot be read or the walk passes `maxFiles`, so the\n * caller SKIPS the checks instead of judging globs against a partial list.\n *\n * Walks by existence, not git tracking, so a present-but-gitignored file (e.g. a\n * build output) is live. A glob matching nothing here is not dead by itself:\n * see `fileGlobLiveness`. Skips `.git`/`node_modules`. Never throws. Not on the\n * recall hot path (only capture, `validate`/`lint`/`prune` call it).\n */\nexport function listProjectFiles(\n projectRoot: string,\n maxFiles: number = MAX_FILES,\n): ProjectFiles | 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 > maxFiles) return null;\n }\n }\n }\n } catch {\n return null;\n }\n return projectFilesOf(out, () => readGitPathHistory(projectRoot));\n}\n","import { isBroadFileGlob } from './glob-breadth.js';\nimport { isBroadCommandPattern } from './command-pattern-breadth.js';\nimport { missingGlobState } from './file-glob-liveness.js';\nimport { getGlobMatcher } from './glob-safety.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { gitHistoryOf } from './project-files.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 whose path git history removed, and\n * `collectRunnerAnchoredPatterns` flags a scope-MATCH gap (anchored to one\n * runner), not a scope-too-narrow one.\n */\n\nexport function 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/** Active `file_glob` trigger ids that match no file on disk, split by {@link missingGlobState}. */\nexport interface FileGlobLiveness {\n /** Git history renamed or deleted what they matched: safe to detach. */\n readonly dead: ReadonlySet<string>;\n /** No proof of removal (not created yet, ignored output, no git): never detached. */\n readonly pending: ReadonlySet<string>;\n}\n\n/**\n * Judge every `file_glob` on an active lesson against `knownPaths` (on-disk,\n * project-relative, forward-slash) and the git evidence it carries (see\n * `listProjectFiles`). Git is read only when some glob matches nothing on disk;\n * a plain set carries no evidence, so nothing in it can be proven dead.\n * `triggerIds` narrows the judgement (e.g. to one captured lesson).\n */\nexport function fileGlobLiveness(\n graph: LessonsGraph,\n knownPaths: ReadonlySet<string>,\n triggerIds?: readonly string[],\n): FileGlobLiveness {\n const active = triggerIds === undefined ? activeTriggerIds(graph) : new Set(triggerIds);\n const paths = [...knownPaths];\n const missing: Array<[string, string]> = [];\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'file_glob' || !active.has(triggerId)) continue;\n // An unsafe glob gets its own UNSAFE_GLOB_PATTERN error; never judge it here.\n const matcher = getGlobMatcher(trigger.pattern);\n if (matcher === null) continue;\n if (!paths.some((p) => matcher.test(p))) missing.push([triggerId, trigger.pattern]);\n }\n const dead = new Set<string>();\n const pending = new Set<string>();\n if (missing.length === 0) return { dead, pending };\n const history = gitHistoryOf(knownPaths);\n for (const [triggerId, pattern] of missing) {\n const state = missingGlobState(pattern, history);\n if (state === 'dead') dead.add(triggerId);\n else if (state === 'pending') pending.add(triggerId);\n }\n return { dead, pending };\n}\n\n/**\n * Warn on each dead `file_glob`: the lesson is unreachable via that trigger\n * because git history moved or deleted its path. Pending globs are not reported\n * (they fire once the path exists). Skipped entirely when the caller has no file\n * list (see {@link validateLessonsGraph}).\n */\nexport function collectDeadFileGlobs(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n knownPaths: ReadonlySet<string>,\n): void {\n for (const triggerId of fileGlobLiveness(graph, knownPaths).dead) {\n findings.push({\n level: 'warning',\n code: 'DEAD_FILE_GLOB',\n message: `file_glob trigger \"${triggerId}\" (${graph.triggers[triggerId]?.pattern ?? ''}) matches no file, and git history shows its path was renamed or deleted — the lesson is unreachable via this trigger. 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/** How many working-tree paths a `file_glob` pattern matches — for the breadth guardrail. */\nexport function fileGlobMatchCount(pattern: string, knownPaths: ReadonlySet<string>): number {\n const matcher = getGlobMatcher(pattern);\n if (matcher === null) return 0;\n let n = 0;\n for (const p of knownPaths) if (matcher.test(p)) n += 1;\n return 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\n/**\n * A `file_glob` that covers most of the tree fires on nearly every edit, so it\n * crowds out the rule written about the file actually being touched once the\n * recall token budget bites. Warn-only and never blocking: a deliberate\n * file-CLASS trigger is the documented way to state general behaviour, and only\n * genuinely repo-wide patterns are reported.\n */\nexport function collectBroadFileGlobs(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const active = activeTriggerIds(graph);\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'file_glob') continue;\n if (!active.has(triggerId)) continue;\n if (!isBroadFileGlob(trigger.pattern)) continue;\n findings.push({\n level: 'warning',\n code: 'BROAD_FILE_GLOB',\n message: `file_glob trigger \"${triggerId}\" (${trigger.pattern}) matches most of the repository, so it outranks nothing and crowds the recall budget. Narrow it to the directory or file class the rule is really about, or detach it with \\`lessons untrigger\\`.`,\n triggerId,\n });\n }\n}\n\n/**\n * A `command_pattern` on an active lesson that matches the empty string or most\n * unrelated commands fires on every recall. `add` rejects a new one\n * (BROAD_COMMAND_PATTERN, exit 2); this is the `validate` counterpart for a\n * graph built before that guardrail existed (or a hand-edit). Warn-only.\n */\nexport function collectBroadCommandPatterns(\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 (!isBroadCommandPattern(trigger.pattern)) continue;\n findings.push({\n level: 'warning',\n code: 'BROAD_COMMAND_PATTERN',\n message: `command_pattern trigger \"${triggerId}\" (${trigger.pattern}) matches nearly every command, so the lesson fires on every recall. Key it on the action (e.g. \\`\\\\bgit commit\\\\b\\`), or detach it with \\`lessons untrigger\\`.`,\n triggerId,\n });\n }\n}\n","import { isNegatedGlob } from './glob-breadth.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport {\n isLowSignalKeyword,\n keywordNeedleLosesTokens,\n MAX_RECOMMENDED_KEYWORD_TOKENS,\n} from './keyword-signal.js';\nimport { fileGlobLiveness, fileGlobMatchCount } 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 | 'WIDE_GLOB_MATCH'\n | 'KEYWORD_ONLY_LESSON'\n | 'LOW_SIGNAL_KEYWORD'\n | 'STOPWORD_KEYWORD'\n | 'DEAD_GLOB'\n | 'PENDING_GLOB'\n | 'NEAR_DUPLICATE_LESSON';\n\n/**\n * A `file_glob` matching more working-tree files than this is too wide for one\n * lesson — it will fire on many unrelated edits and dilute recall. Complements the\n * STRUCTURAL {@link isBroadGlob} check: catches a globstar with a CONCRETE basename\n * (an `index.ts` at any depth) or a single-directory wildcard (`src/lib/*.ts`) —\n * not structurally broad, yet still matching a large swath of the actual tree.\n */\nexport const WIDE_GLOB_MATCH_COUNT = 40;\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. Exported so capture-time trigger repair narrows on the SAME\n * predicate this guardrail warns on.\n */\nexport function isBroadGlob(pattern: string): boolean {\n const p = pattern.trim();\n if (p === '*' || p === '**' || isNegatedGlob(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 and\n * PENDING_GLOB liveness warnings. The pure write-barrier path passes nothing (no\n * tree walk on the hot mutate path); only the capture entry point supplies it, so\n * a dead or mistyped glob is flagged at the best moment to fix it.\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 contiguous token-run in --keyword or 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, pending } = fileGlobLiveness(graph, knownPaths, lesson.triggers);\n const deadHere = patternsIn(graph, lesson.triggers, dead);\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, and git history shows the path was renamed or deleted — likely a rename. Re-point them at the current path, or the lesson is unreachable via those globs.`,\n });\n }\n const pendingHere = patternsIn(graph, lesson.triggers, pending);\n if (pendingHere.length > 0) {\n warnings.push({\n code: 'PENDING_GLOB',\n message: `Lesson \"${lessonId}\" has file_glob trigger(s) (${pendingHere.join(', ')}) whose path does not exist yet — the trigger will fire once it does, so it is kept. If the path is a typo, re-point it.`,\n });\n }\n\n // File-COUNT breadth (complements the structural isBroadGlob check): a glob that\n // is not structurally broad but still matches a large swath of the real tree.\n const wide = triggers\n .filter((t) => t.kind === 'file_glob' && !isBroadGlob(t.pattern))\n .filter((t) => fileGlobMatchCount(t.pattern, knownPaths) > WIDE_GLOB_MATCH_COUNT)\n .map((t) => t.pattern);\n if (wide.length > 0) {\n warnings.push({\n code: 'WIDE_GLOB_MATCH',\n message: `Lesson \"${lessonId}\" has file glob(s) (${wide.join(', ')}) matching more than ${WIDE_GLOB_MATCH_COUNT} files in the working tree; narrow to the file-CLASS where the rule actually applies so it does not fire on unrelated edits.`,\n });\n }\n }\n\n return warnings;\n}\n\nfunction patternsIn(\n graph: LessonsGraph,\n ids: readonly string[],\n keep: ReadonlySet<string>,\n): string[] {\n return ids\n .filter((id) => keep.has(id))\n .map((id) => graph.triggers[id]?.pattern)\n .filter((p): p is string => p !== undefined);\n}\n","import type { GuardrailWarning } from './capture-guardrails.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { tokenize } from './ranking-text.js';\n\n/**\n * Near-duplicate detection for capture — split from capture-guardrails.ts (the\n * trigger-hygiene warnings) so each stays within the 200-line limit and owns one\n * responsibility: this module answers \"does this new rule paraphrase an existing\n * one?\", the other \"are this lesson's triggers reachable and precise?\".\n */\n\n/** Token-Jaccard similarity at/above which a new lesson is flagged a near-duplicate. */\nexport const NEAR_DUPLICATE_THRESHOLD = 0.6;\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 { readdirSync, rmSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { lessonsPaths } from './paths.js';\n\n/**\n * A crashed writer can leave a temp file (`<name>.<pid>.tmp`) or a lock folder\n * set aside for inspection (`<lock>.<id>.stale`) in `.agentsmesh/lessons/`.\n * Nothing else removes them, so every graph write sweeps the old ones.\n */\nconst LEFTOVER = /\\.(?:\\d+\\.tmp|[\\w-]+\\.stale)$/;\n\n/** Younger entries may belong to a writer that is still running. */\nconst LEFTOVER_AGE_MS = 60_000;\n\nexport function sweepLessonsLeftovers(projectRoot: string, now: number = Date.now()): void {\n const dir = lessonsPaths(projectRoot).base;\n let names: string[];\n try {\n names = readdirSync(dir);\n } catch {\n return;\n }\n for (const name of names) {\n if (!LEFTOVER.test(name)) continue;\n const path = join(dir, name);\n try {\n if (now - statSync(path).mtimeMs > LEFTOVER_AGE_MS)\n rmSync(path, { recursive: true, force: true });\n } catch {\n // Best-effort housekeeping: never fail a write over a leftover.\n }\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_IMPORT_FAILED'\n | 'AM_GENERATION_FAILED'\n | 'AM_REMOTE_FETCH_FAILED'\n | 'AM_LOCK_ACQUISITION_FAILED'\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\n/** A user-authored canonical file (mcp.json, permissions.yaml, hooks.yaml) has a syntax error. */\nexport class CanonicalParseError extends AgentsMeshError {\n readonly path: string;\n\n constructor(path: string, cause: unknown) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(\n 'AM_CONFIG_INVALID',\n `Invalid canonical file ${path}: ${detail}. Fix the syntax and try again.`,\n {\n cause,\n },\n );\n this.name = 'CanonicalParseError';\n this.path = path;\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 * Start-time identity of a process. A lock holder records its own identity so\n * a later reader can tell the holder apart from an unrelated process that got\n * the same pid (pid reuse after a crash, a reboot, or a container restart).\n */\n\nimport { execFile } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\nconst PS_TIMEOUT_MS = 2_000;\n\nlet self: Promise<string | null> | undefined;\n\n/**\n * An identity that stays the same for the whole life of `pid` and differs for\n * any later process with that pid. Null when the pid is not running or the\n * platform has no cheap probe (Windows).\n */\nexport async function processIdentity(\n pid: number,\n platform: NodeJS.Platform = process.platform,\n): Promise<string | null> {\n if (!Number.isInteger(pid) || pid <= 0 || platform === 'win32') return null;\n try {\n return platform === 'linux' ? await linuxIdentity(pid) : await psIdentity(pid);\n } catch {\n return null;\n }\n}\n\n/** Identity of the current process, probed once. */\nexport function selfIdentity(): Promise<string | null> {\n self ??= processIdentity(process.pid);\n return self;\n}\n\n/** `<boot id>:<start ticks>` from `/proc/<pid>/stat`; wall-clock changes do not move it. */\nexport function linuxStartIdentity(stat: string, bootId: string): string | null {\n // Fields after \"(comm)\" start at field 3, so starttime (field 22) is index 19.\n const start = stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19];\n const boot = bootId.trim();\n if (start === undefined || !/^\\d+$/.test(start) || boot === '') return null;\n return `${boot}:${start}`;\n}\n\nasync function linuxIdentity(pid: number): Promise<string | null> {\n const [stat, bootId] = await Promise.all([\n readFile(`/proc/${pid}/stat`, 'utf-8'),\n readFile('/proc/sys/kernel/random/boot_id', 'utf-8'),\n ]);\n return linuxStartIdentity(stat, bootId);\n}\n\nasync function psIdentity(pid: number): Promise<string | null> {\n // UTC and the C locale keep the printed start time stable across DST and locales.\n const { stdout } = await execFileAsync('ps', ['-o', 'lstart=', '-p', String(pid)], {\n env: { ...process.env, LC_ALL: 'C', TZ: 'UTC' },\n timeout: PS_TIMEOUT_MS,\n });\n const start = stdout.trim();\n return start === '' ? null : start;\n}\n","import { setTimeout as sleep } from 'node:timers/promises';\n\n/**\n * Windows fails a filesystem call with these for a short time while another\n * process has the same path open or is removing it (\"delete pending\").\n */\nconst TRANSIENT_CODES: ReadonlySet<string> = new Set(['EPERM', 'EACCES', 'EBUSY']);\nconst ATTEMPTS = 5;\nconst BASE_DELAY_MS = 25;\nconst pause = new Int32Array(new SharedArrayBuffer(4));\n\nexport function isTransientFsError(err: unknown): boolean {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n return typeof code === 'string' && TRANSIENT_CODES.has(code);\n}\n\n/** Runs `op`, retrying a transient error with a short backoff; a lasting one still throws. */\nexport async function retryTransient<T>(op: () => Promise<T>): Promise<T> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await op();\n } catch (err) {\n if (!isTransientFsError(err) || attempt >= ATTEMPTS) throw err;\n await sleep(BASE_DELAY_MS * 2 ** (attempt - 1));\n }\n }\n}\n\n/** Sync `retryTransient`, for code that must not become async. */\nexport function retryTransientSync<T>(op: () => T): T {\n for (let attempt = 1; ; attempt++) {\n try {\n return op();\n } catch (err) {\n if (!isTransientFsError(err) || attempt >= ATTEMPTS) throw err;\n Atomics.wait(pause, 0, 0, BASE_DELAY_MS * 2 ** (attempt - 1));\n }\n }\n}\n","import { rename } from 'node:fs/promises';\nimport { setTimeout as sleep } from 'node:timers/promises';\n\ninterface ErrnoLike {\n code?: string;\n}\n\n/**\n * Errors Windows raises when a just-written directory is briefly locked — by the\n * exited writer's lingering handle (e.g. `git clone`), an antivirus scan, or the\n * search indexer. A same-filesystem rename never produces these on POSIX.\n */\nconst TRANSIENT_RENAME_CODES = new Set(['EPERM', 'EACCES', 'EBUSY', 'ENOTEMPTY', 'EEXIST']);\n\nexport interface RenameRetryOptions {\n /** Total attempts before giving up (default 5). */\n readonly attempts?: number;\n /** Base backoff in ms; doubles each retry (default 50). */\n readonly delayMs?: number;\n}\n\n/**\n * `rename`, retried on the transient lock errors Windows raises right after a\n * child process writes the source tree (the cache-finalize rename in\n * `git-remote.ts` hits this directly after `git clone`). On POSIX it is a single\n * rename. A non-transient error throws immediately; the last transient error\n * throws after the final attempt so a genuine failure still surfaces.\n */\nexport async function renameWithRetry(\n from: string,\n to: string,\n options: RenameRetryOptions = {},\n): Promise<void> {\n const attempts = options.attempts ?? 5;\n const delayMs = options.delayMs ?? 50;\n for (let attempt = 0; ; attempt++) {\n try {\n await rename(from, to);\n return;\n } catch (err) {\n const code = (err as ErrnoLike).code;\n const transient = code !== undefined && TRANSIENT_RENAME_CODES.has(code);\n if (!transient || attempt >= attempts - 1) throw err;\n await sleep(delayMs * 2 ** attempt);\n }\n }\n}\n","/**\n * Reading a process lock directory.\n *\n * Layout: `<lock>/owner-<token>/` marks the current holder and `<lock>/holder.json`\n * describes it (pid, host, start time, token). A lock written by an older\n * version has only holder.json and no token.\n */\n\nimport { readdir, readFile, stat } from 'node:fs/promises';\nimport { hostname } from 'node:os';\nimport { join } from 'node:path';\nimport { processIdentity } from './process-identity.js';\n\nconst HOLDER_FILE = 'holder.json';\nconst OWNER_PREFIX = 'owner-';\n// A lock dir without a complete owner is being created or removed right now;\n// past this window it counts as abandoned.\nconst YOUNG_LOCK_GRACE_MS = 2_000;\n// A healthy critical section is short, so only older holders are probed for pid reuse.\nconst PID_REUSE_PROBE_AFTER_MS = 2_000;\n// Hosts sharing a lock may disagree on the time a little. A start time (or dir\n// mtime) further ahead than this cannot be a running holder's: it counts as stale.\nconst CLOCK_SKEW_TOLERANCE_MS = 5 * 60 * 1000;\n\nexport interface LockMetadata {\n pid: number;\n started: number;\n hostname?: string;\n token?: string;\n /** Start identity of `pid` (see process-identity.ts). */\n procStart?: string;\n}\n\nexport type LockState =\n | { kind: 'gone' }\n | { kind: 'young' }\n | { kind: 'held'; token: string; meta: LockMetadata }\n | { kind: 'legacy'; meta: LockMetadata; raw: string }\n | { kind: 'orphan'; tokens: string[]; raw: string | null };\n\n/** Cached pid-reuse verdicts for one acquire call. */\nexport type ProbeCache = Map<string, Promise<boolean>>;\n\nexport function ownerPath(lockPath: string, token: string): string {\n return join(lockPath, `${OWNER_PREFIX}${token}`);\n}\n\nexport function holderPath(lockPath: string): string {\n return join(lockPath, HOLDER_FILE);\n}\n\nexport function errorCode(err: unknown): string | undefined {\n return (err as NodeJS.ErrnoException | null)?.code;\n}\n\n/** The lock path holds a file, where agentsmesh keeps a lock folder. */\nexport class LockPathNotFolderError extends Error {\n constructor(lockPath: string) {\n super(\n `${lockPath.replaceAll('\\\\', '/')} is a file, but agentsmesh keeps its lock there as a ` +\n 'folder. Delete it and run the command again.',\n );\n this.name = 'LockPathNotFolderError';\n }\n}\n\n/** Owner tokens inside `dir`, or null when `dir` does not exist. */\nexport async function ownerTokens(dir: string): Promise<string[] | null> {\n try {\n const entries = await readdir(dir);\n return entries\n .filter((e) => e.startsWith(OWNER_PREFIX))\n .map((e) => e.slice(OWNER_PREFIX.length));\n } catch (err) {\n if (errorCode(err) === 'ENOENT') return null;\n if (errorCode(err) === 'ENOTDIR') throw new LockPathNotFolderError(dir);\n throw err;\n }\n}\n\nexport async function readHolderRaw(dir: string): Promise<string | null> {\n return readFile(holderPath(dir), 'utf-8').catch(() => null);\n}\n\n/** Owner token recorded in holder.json text, if any. */\nexport function holderToken(raw: string | null): string | undefined {\n return raw === null ? undefined : parseMetadata(raw)?.token;\n}\n\nexport async function inspectLock(lockPath: string): Promise<LockState> {\n const tokens = await ownerTokens(lockPath);\n if (tokens === null) return { kind: 'gone' };\n const raw = await readHolderRaw(lockPath);\n const meta = raw === null ? null : parseMetadata(raw);\n const [only] = tokens;\n if (meta && tokens.length === 1 && only !== undefined && meta.token === only) {\n return { kind: 'held', token: only, meta };\n }\n if (meta && raw !== null && tokens.length === 0 && meta.token === undefined) {\n return { kind: 'legacy', meta, raw };\n }\n const age = await dirAgeMs(lockPath);\n if (age === null) return { kind: 'gone' };\n // Negative ages (mtime a hair ahead of Date.now()) are young too.\n const young = age < YOUNG_LOCK_GRACE_MS && age >= -CLOCK_SKEW_TOLERANCE_MS;\n return young ? { kind: 'young' } : { kind: 'orphan', tokens, raw };\n}\n\n/** Dead same-host pid, reused pid, older than `staleMs`, or started in the future. */\nexport async function isStale(\n meta: LockMetadata,\n staleMs: number,\n cache: ProbeCache,\n): Promise<boolean> {\n const age = Date.now() - meta.started;\n if (age > staleMs || age < -CLOCK_SKEW_TOLERANCE_MS) return true;\n if (meta.hostname && meta.hostname !== hostname()) return false;\n if (!isProcessAlive(meta.pid)) return true;\n if (meta.procStart === undefined || age < PID_REUSE_PROBE_AFTER_MS) return false;\n return pidReused(meta.pid, meta.procStart, cache);\n}\n\nexport function describeHolder(state: LockState): string {\n if (state.kind !== 'held' && state.kind !== 'legacy') return 'unknown (unreadable lock metadata)';\n const { meta } = state;\n const host = meta.hostname ? `${meta.hostname}:` : '';\n return `${host}pid ${meta.pid} (running ${Math.max(0, Date.now() - meta.started)}ms)`;\n}\n\nasync function dirAgeMs(lockPath: string): Promise<number | null> {\n try {\n return Date.now() - (await stat(lockPath)).mtimeMs;\n } catch (err) {\n if (errorCode(err) === 'ENOENT') return null;\n throw err;\n }\n}\n\nfunction pidReused(pid: number, recorded: string, cache: ProbeCache): Promise<boolean> {\n const key = `${pid}:${recorded}`;\n let verdict = cache.get(key);\n if (!verdict) {\n verdict = processIdentity(pid).then((current) => current !== null && current !== recorded);\n cache.set(key, verdict);\n }\n return verdict;\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 errorCode(err) === 'EPERM';\n }\n}\n\nfunction parseMetadata(raw: string): LockMetadata | null {\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n return null;\n }\n if (typeof value !== 'object' || value === null) return null;\n const v = value as Record<string, unknown>;\n if (typeof v.pid !== 'number' || typeof v.started !== 'number') return null;\n const optionalText = (x: unknown): boolean => x === undefined || typeof x === 'string';\n const textOk = [v.hostname, v.token, v.procStart].every(optionalText);\n return textOk ? (value as LockMetadata) : null;\n}\n","/**\n * Changes to a process lock directory.\n *\n * Ownership moves only by removing the exact `owner-<token>` marker, which\n * fails once that marker is gone. Only whoever removed it may then tear the\n * dir down, so neither a release nor an eviction can delete a lock that has\n * already passed to another process.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { existsSync, readFileSync, rmdirSync, unlinkSync } from 'node:fs';\nimport { mkdir, rename, rm, rmdir, unlink, writeFile } from 'node:fs/promises';\nimport { renameWithRetry } from './rename-retry.js';\nimport { retryTransient } from './transient-fs.js';\nimport {\n errorCode,\n holderPath,\n holderToken,\n ownerPath,\n ownerTokens,\n readHolderRaw,\n type LockMetadata,\n type LockState,\n} from './process-lock-state.js';\n\n/** Claims `lockPath` for `meta.token`; false when another process holds or wins it. */\nexport async function tryAcquire(\n lockPath: string,\n meta: LockMetadata & { token: string },\n): Promise<boolean> {\n try {\n await mkdir(lockPath);\n } catch (err) {\n if (errorCode(err) === 'EEXIST') return false;\n throw err;\n }\n const owner = ownerPath(lockPath, meta.token);\n let writingHolder = false;\n try {\n await mkdir(owner);\n // A stalled claimer can land in this dir too; only a sole owner goes on.\n if ((await ownerTokens(lockPath))?.length !== 1) return await backOff(lockPath, owner);\n writingHolder = true;\n // `wx`: never overwrite another holder's metadata.\n await writeFile(holderPath(lockPath), JSON.stringify(meta), { encoding: 'utf-8', flag: 'wx' });\n } catch (err) {\n const code = errorCode(err);\n if (code === 'ENOENT' || code === 'EEXIST') return backOff(lockPath, owner);\n if (writingHolder) await rm(holderPath(lockPath), { force: true }).catch(() => {});\n await backOff(lockPath, owner);\n throw err;\n }\n // The marker can be evicted while this process stalls mid-claim; then the claim is lost.\n if (existsSync(owner)) return true;\n await teardown(lockPath, [meta.token]);\n return false;\n}\n\n/** Sync `evictOwners(lockPath, [token])` for exit and signal handlers. */\nexport function releaseOwnedSync(lockPath: string, token: string): void {\n try {\n rmdirSync(ownerPath(lockPath, token));\n } catch {\n return;\n }\n try {\n if (holderToken(readFileSync(holderPath(lockPath), 'utf-8')) === token) {\n unlinkSync(holderPath(lockPath));\n }\n } catch {\n // Already gone.\n }\n try {\n rmdirSync(lockPath);\n } catch {\n // Not empty or already gone.\n }\n}\n\n/** Removes a lock judged stale, but only if the judged holder still owns it. */\nexport async function evict(lockPath: string, state: LockState): Promise<void> {\n if (state.kind === 'held') return evictOwners(lockPath, [state.token]);\n if (state.kind === 'orphan' && state.tokens.length > 0) {\n return evictOwners(lockPath, state.tokens);\n }\n if (state.kind === 'legacy' || state.kind === 'orphan') return dropUnowned(lockPath, state.raw);\n}\n\n/** Gives up the holds of `tokens`; a no-op for any token that no longer owns the lock. */\nexport async function evictOwners(lockPath: string, tokens: readonly string[]): Promise<void> {\n const removed: string[] = [];\n for (const token of tokens) {\n if (await removeOwner(lockPath, token)) removed.push(token);\n }\n if (removed.length > 0) await teardown(lockPath, removed);\n}\n\nasync function removeOwner(lockPath: string, token: string): Promise<boolean> {\n try {\n // Windows: a marker another evictor is removing fails rmdir with EPERM for a moment.\n await retryTransient(() => rmdir(ownerPath(lockPath, token)));\n return true;\n } catch (err) {\n if (errorCode(err) === 'ENOENT') return false;\n throw err;\n }\n}\n\n/**\n * Removes a dir after this process removed the markers of `tokens`. If the\n * lock passed to a new holder meanwhile, its holder.json carries another\n * token and `rmdir` fails on its non-empty dir, so nothing of it is removed.\n */\nasync function teardown(lockPath: string, tokens: readonly string[]): Promise<void> {\n const token = holderToken(await readHolderRaw(lockPath));\n if (token !== undefined && tokens.includes(token)) {\n await unlink(holderPath(lockPath)).catch(() => {});\n }\n await rmdir(lockPath).catch(() => {});\n}\n\n/**\n * Removes a lock dir with no owner marker (older version, or abandoned while\n * being created). It is moved aside and checked first: a dir that changed\n * since it was judged is put back instead of deleted.\n */\nasync function dropUnowned(lockPath: string, judgedRaw: string | null): Promise<void> {\n const aside = `${lockPath}.${randomUUID()}.stale`;\n try {\n await renameWithRetry(lockPath, aside);\n } catch (err) {\n if (errorCode(err) === 'ENOENT') return;\n throw err;\n }\n const owners = await ownerTokens(aside);\n if (owners?.length !== 0 || (await readHolderRaw(aside)) !== judgedRaw) {\n return putBack(aside, lockPath);\n }\n try {\n await rm(aside, { recursive: true, force: true });\n } catch (err) {\n await putBack(aside, lockPath);\n throw err;\n }\n}\n\nasync function putBack(aside: string, lockPath: string): Promise<void> {\n await rename(aside, lockPath).catch(() => {});\n}\n\nasync function backOff(lockPath: string, owner: string): Promise<false> {\n await rmdir(owner).catch(() => {});\n // Removes the claim dir only if nothing else is in it.\n await rmdir(lockPath).catch(() => {});\n return false;\n}\n","/**\n * Cross-platform process lock backed by an atomic mkdir.\n *\n * Each acquisition gets a random owner token, kept as an `owner-<token>` marker\n * in the lock dir next to `holder.json` (pid, host, start time). The lock\n * changes hands only by removing that exact marker, so neither a release nor\n * a stale eviction can delete a lock that already passed to another process.\n *\n * Stale recovery: a dead same-host holder, or a live pid that now belongs to\n * another process, is evicted at once. Any holder older than `staleMs` (or\n * dated in the future past clock skew) is evicted too — the bound for hung\n * processes and holders on other hosts. A holder evicted this way sees\n * `isHeld()` turn false, so it can refuse to write.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { hostname } from 'node:os';\nimport { dirname } from 'node:path';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { LockAcquisitionError } from '../../core/errors.js';\nimport { selfIdentity } from './process-identity.js';\nimport { isTransientFsError } from './transient-fs.js';\nimport { evict, evictOwners, releaseOwnedSync, tryAcquire } from './process-lock-ops.js';\nimport {\n describeHolder,\n inspectLock,\n isStale,\n ownerPath,\n type LockMetadata,\n type LockState,\n type ProbeCache,\n} from './process-lock-state.js';\n\nconst DEFAULT_STALE_MS = 6 * 60 * 60 * 1000;\nconst DEFAULT_RETRIES = 30;\nconst DEFAULT_RETRY_DELAY_MS = 200;\n// Evictions and vanished locks retry at once; this caps a run of them.\nconst MAX_IMMEDIATE_RETRIES = 100;\nconst MAX_TRANSIENT_ERRORS = 5; // short Windows errors in a row before one counts as real\n\nexport interface LockOptions {\n /** Maximum retry attempts before throwing LockAcquisitionError. */\n retries?: number;\n /** Delay before the first retry in ms (default 200). */\n retryDelayMs?: number;\n /** Cap for the doubling delay. Defaults to `retryDelayMs`, i.e. a fixed delay. */\n maxRetryDelayMs?: number;\n /** Spread each delay over the upper half of its window so waiters do not retry in step. */\n jitter?: boolean;\n /**\n * Age bound (default 6h): a lock older than this is evicted even when its\n * holder is still alive or cannot be probed (other host).\n */\n staleMs?: number;\n /** Human-readable lock name surfaced in LockAcquisitionError, e.g. \"lessons lock\". */\n label?: string;\n /** Called once, with the holder, when a wait lasts `waitNoticeMs` (default 2000). */\n onWait?: (holder: string) => void;\n waitNoticeMs?: number;\n}\n\nexport type LockRelease = () => Promise<void>;\n\n/** The release function of an acquired lock. */\nexport interface HeldLock extends LockRelease {\n /**\n * False once this acquisition no longer owns the lock: released, or evicted\n * as stale (e.g. the process was paused longer than `staleMs`). Check it\n * right before a write that must not overwrite a later holder's work.\n */\n isHeld(): Promise<boolean>;\n}\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 (with `isHeld()`); 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<HeldLock> {\n const retries = opts.retries ?? DEFAULT_RETRIES;\n const staleMs = opts.staleMs ?? DEFAULT_STALE_MS;\n\n await mkdir(dirname(lockPath), { recursive: true });\n const procStart = await selfIdentity();\n const probes: ProbeCache = new Map();\n\n let attempt = 0;\n let immediate = 0;\n const waitingSince = Date.now();\n let noticed = false;\n let transient = 0;\n while (true) {\n let state: LockState;\n try {\n const holder = newHolder(procStart);\n if (await tryAcquire(lockPath, holder)) return holdLock(lockPath, holder.token);\n state = await inspectLock(lockPath);\n transient = 0;\n } catch (err) {\n // Windows: claiming or reading a lock dir another process is removing fails for a moment.\n if (!isTransientFsError(err) || ++transient >= MAX_TRANSIENT_ERRORS) throw err;\n await sleep(lockRetryDelayMs(transient, opts));\n continue;\n }\n // A vanished or just-evicted lock is bookkeeping, not a wait: no retry budget used.\n if (immediate < MAX_IMMEDIATE_RETRIES && (await clearedNow(lockPath, state, staleMs, probes))) {\n immediate++;\n continue;\n }\n\n if (attempt >= retries) {\n throw new LockAcquisitionError(lockPath, describeHolder(state), { label: opts.label });\n }\n attempt++;\n immediate = 0;\n if (!noticed && opts.onWait && Date.now() - waitingSince >= (opts.waitNoticeMs ?? 2000)) {\n noticed = true;\n opts.onWait(describeHolder(state));\n }\n await sleep(lockRetryDelayMs(attempt, opts));\n }\n}\n\n/** Delay before retry number `attempt` (1-based). */\nexport function lockRetryDelayMs(\n attempt: number,\n opts: Readonly<LockOptions>,\n random: () => number = Math.random,\n): number {\n const base = opts.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const cap = Math.max(base, opts.maxRetryDelayMs ?? base);\n const delay = Math.min(cap, base * 2 ** (attempt - 1));\n return opts.jitter ? delay * (0.5 + random() * 0.5) : delay;\n}\n\n/** True when the lock is gone or was just evicted, so the next try needs no wait. */\nasync function clearedNow(\n lockPath: string,\n state: LockState,\n staleMs: number,\n probes: ProbeCache,\n): Promise<boolean> {\n if (state.kind === 'gone') return true;\n if (state.kind === 'young') return false;\n if (state.kind !== 'orphan' && !(await isStale(state.meta, staleMs, probes))) return false;\n await evict(lockPath, state);\n return true;\n}\n\nfunction newHolder(procStart: string | null): LockMetadata & { token: string } {\n return {\n pid: process.pid,\n started: Date.now(),\n hostname: hostname(),\n token: randomUUID(),\n ...(procStart === null ? {} : { procStart }),\n };\n}\n\nfunction holdLock(lockPath: string, token: string): HeldLock {\n let released = false;\n const cleanup = (): void => {\n if (released) return;\n released = true;\n releaseOwnedSync(lockPath, token);\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 const release = async (): Promise<void> => {\n if (released) return;\n released = true;\n process.off('SIGINT', signalHandler);\n process.off('SIGTERM', signalHandler);\n process.off('exit', cleanup);\n // Removes the lock only while this token still owns it.\n await evictOwners(lockPath, [token]).catch(() => {});\n };\n // The owner marker leaves only through release or eviction (see process-lock-ops.ts).\n const isHeld = async (): Promise<boolean> => !released && existsSync(ownerPath(lockPath, token));\n return Object.assign(release, { isHeld });\n}\n","// Single source of truth for whether ANSI color should be emitted to a stream.\n//\n// Precedence (matches the supports-color / NO_COLOR conventions):\n// FORCE_COLOR > NO_COLOR > stream.isTTY\n//\n// Piped consumers (no TTY) get plain text by default, so agents reading the CLI\n// over a pipe never see escape bytes. FORCE_COLOR lets a caller opt back in\n// (e.g. `agentsmesh matrix | less -R`).\n\ninterface ColorStream {\n isTTY?: boolean;\n}\n\nfunction noColorRequested(): boolean {\n const value = process.env.NO_COLOR;\n return value !== undefined && value !== '';\n}\n\n/** `undefined` when FORCE_COLOR is unset, else the forced on/off decision. */\nfunction forceColorRequested(): boolean | undefined {\n const value = process.env.FORCE_COLOR;\n if (value === undefined) return undefined;\n return value !== '0' && value !== 'false';\n}\n\nexport function colorEnabled(stream: ColorStream = process.stdout): boolean {\n const forced = forceColorRequested();\n if (forced !== undefined) return forced;\n if (noColorRequested()) return false;\n return stream.isTTY === true;\n}\n","// Colored console output\n\nimport { colorEnabled } from './color.js';\n\nconst C = {\n green: '\\x1b[32m',\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n reset: '\\x1b[0m',\n};\n\nlet muted = false;\nlet stdoutRedirectedToStderr = false;\n\nexport function muteLogger(): void {\n muted = true;\n}\n\nexport function unmuteLogger(): void {\n muted = false;\n}\n\nexport function redirectLoggerToStderr(): void {\n stdoutRedirectedToStderr = true;\n}\n\nfunction outStream(): NodeJS.WriteStream {\n return stdoutRedirectedToStderr ? process.stderr : process.stdout;\n}\n\nfunction out(text: string): void {\n outStream().write(text);\n}\n\nfunction c(code: string, text: string, stream: NodeJS.WriteStream): string {\n return colorEnabled(stream) ? `${code}${text}${C.reset}` : text;\n}\n\nexport const logger = {\n info(msg: string): void {\n if (muted) return;\n out(c(C.cyan, msg, outStream()) + '\\n');\n },\n warn(msg: string): void {\n if (muted) return;\n process.stderr.write(c(C.yellow, '⚠ ', process.stderr) + msg + '\\n');\n },\n error(msg: string): void {\n if (muted) return;\n process.stderr.write(c(C.red, '✗ ', process.stderr) + msg + '\\n');\n },\n success(msg: string): void {\n if (muted) return;\n out(c(C.green, '✓ ', outStream()) + msg + '\\n');\n },\n debug(msg: string): void {\n if (muted) return;\n if (process.env.AGENTSMESH_DEBUG === '1') {\n out(c(C.cyan, '[debug] ', outStream()) + msg + '\\n');\n }\n },\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`, with its own timing below.\n */\n\nimport { resolve } from 'node:path';\nimport {\n acquireProcessLock,\n type HeldLock,\n type LockOptions,\n} from '../utils/filesystem/process-lock.js';\nimport { logger } from '../utils/output/logger.js';\n\nexport const LESSONS_LOCK_FILENAME = '.lessons.lock';\n\n/**\n * A lessons write holds the lock for milliseconds, so a lock older than a\n * minute is abandoned (reused pid, other host, devcontainer). Many parallel\n * captures queue behind each other, so waiters back off with jitter and wait\n * longer than the stale window before giving up.\n */\nexport const LESSONS_LOCK_OPTIONS = Object.freeze({\n retries: 500,\n retryDelayMs: 25,\n maxRetryDelayMs: 250,\n jitter: true,\n staleMs: 60_000,\n});\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<HeldLock> {\n return acquireProcessLock(lessonsLockPath(projectRoot), {\n retries: opts.retries ?? LESSONS_LOCK_OPTIONS.retries,\n retryDelayMs: opts.retryDelayMs ?? LESSONS_LOCK_OPTIONS.retryDelayMs,\n maxRetryDelayMs: opts.maxRetryDelayMs ?? LESSONS_LOCK_OPTIONS.maxRetryDelayMs,\n jitter: opts.jitter ?? LESSONS_LOCK_OPTIONS.jitter,\n staleMs: opts.staleMs ?? LESSONS_LOCK_OPTIONS.staleMs,\n label: 'lessons lock',\n waitNoticeMs: opts.waitNoticeMs,\n onWait:\n opts.onWait ??\n ((holder) =>\n logger.warn(\n `Waiting for the lessons lock, held by ${holder}; a lock older than ` +\n `${LESSONS_LOCK_OPTIONS.staleMs / 1000} s is taken over.`,\n )),\n });\n}\n\n/** The lessons lock was evicted as stale while this process held it; nothing was saved. */\nexport class LessonsLockLostError extends Error {\n constructor() {\n super(\n 'lost the lessons lock while writing (the process was paused longer than the ' +\n `${LESSONS_LOCK_OPTIONS.staleMs / 1000} s stale window?); nothing was saved — retry the command`,\n );\n this.name = 'LessonsLockLostError';\n }\n}\n\n/** Call right before saving: throws LessonsLockLostError once `lock` no longer owns the lock. */\nexport async function assertLessonsLockHeld(lock: HeldLock): Promise<void> {\n if (!(await lock.isHeld())) throw new LessonsLockLostError();\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","import { normalizeRule } from './add-helpers.js';\nimport { unsafeGlobFinding } from './glob-safety.js';\nimport type { LessonsGraph } from './graph-schema.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` that is not a valid regex, or that the linear matcher\n * cannot run (a backreference or a lookaround), is dead: recall skips it (see\n * regex-safety.ts). Both are errors for validate and the write barrier; capture\n * drops them first (add-gates.ts dropDeadCommandTriggers). Unsafe\n * `file_glob`s get the same treatment (UNSAFE_GLOB_PATTERN, see glob-safety.ts).\n * MCP redacts `/word` tokens as paths, so messages must not echo one.\n */\nexport function collectInvalidTriggerPatterns(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n): void {\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n const globFinding = unsafeGlobFinding(triggerId, trigger);\n if (globFinding !== null) findings.push(globFinding);\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}): ${regexSyntaxReason(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 the linear matcher cannot run (${trigger.pattern}). It does not support backreferences (\\\\1, \\\\k<name>), lookarounds ((?=x), (?!x), (?<=x), (?<!x)), or patterns too large to run, such as (a{1000}){10}. Nested quantifiers such as (a+)+ are fine. Rewrite the pattern without the unsupported part.`,\n triggerId,\n });\n }\n }\n}\n\n/** The parser's reason without V8's `/pattern/:` echo, which a redactor reads as a path. */\nfunction regexSyntaxReason(err: unknown): string {\n const text = err instanceof Error ? err.message : String(err);\n return text.replace(/^Invalid regular expression: \\/[\\s\\S]*\\/[a-z]*: /, '');\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 * Recall delivers a handful of matches per call, so a trigger set shared by more\n * lessons than that is a tie the ranker cannot break: identical triggers score\n * identically on specificity, and the choice falls to topic coherence and rule\n * text. Which lessons an agent actually sees becomes close to arbitrary.\n *\n * Derived from the graph alone, so it works without telemetry.\n */\nconst TIED_TRIGGER_SET_THRESHOLD = 5;\n\nexport function collectTriggerSetCollisions(\n graph: LessonsGraph,\n findings: ValidationFinding[],\n): void {\n const bySet = new Map<string, string[]>();\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status !== 'active') continue;\n const key = [...lesson.triggers].sort().join(',');\n if (key === '') continue;\n const group = bySet.get(key);\n if (group === undefined) bySet.set(key, [id]);\n else group.push(id);\n }\n\n const contested = [...bySet.values()].filter((ids) => ids.length > TIED_TRIGGER_SET_THRESHOLD);\n if (contested.length === 0) return;\n\n const largest = contested.reduce((a, b) => (b.length > a.length ? b : a));\n const affected = contested.reduce((n, ids) => n + ids.length, 0);\n findings.push({\n level: 'warning',\n code: 'TIED_TRIGGER_SETS',\n message:\n `${contested.length} trigger set(s) are each shared by more than ${TIED_TRIGGER_SET_THRESHOLD} ` +\n `active lessons (largest ${largest.length}, ${affected} lessons in total). Identical triggers ` +\n 'score identically on specificity, so recall picks among them by weaker signals — split the ' +\n 'triggers so the lesson that matters for a given file can win.',\n lessonIds: largest.sort(),\n });\n}\n","import { activeTriggerIds } from './validate-liveness.js';\nimport 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 type { ValidationFinding } from './validate.js';\n\n/**\n * `validate` checks on `keyword` triggers — the curation counterparts to the\n * capture-time LOW_SIGNAL_KEYWORD / STOPWORD_KEYWORD guardrails, so a graph\n * built before those existed still surfaces its structurally-dead keywords.\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 active = activeTriggerIds(graph);\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'keyword') continue;\n if (!active.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 contiguous token-run in --keyword or 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(graph: LessonsGraph, findings: ValidationFinding[]): void {\n const active = activeTriggerIds(graph);\n for (const [triggerId, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind !== 'keyword') continue;\n if (!active.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","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 collectTriggerSetCollisions,\n collectInvalidTriggerPatterns,\n} from './validate-quality.js';\nimport { collectLowSignalKeywords, collectStopwordKeywords } from './validate-keywords.js';\nimport {\n collectBroadCommandPatterns,\n collectBroadFileGlobs,\n collectDeadFileGlobs,\n collectRunnerAnchoredPatterns,\n} 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 /** Every lesson one aggregate finding covers (machine-readable; the message names a few). */\n readonly lessonIds?: readonly 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 collectTriggerSetCollisions(graph, findings);\n collectLowSignalKeywords(graph, findings);\n collectStopwordKeywords(graph, findings);\n collectRunnerAnchoredPatterns(graph, findings);\n collectBroadCommandPatterns(graph, findings);\n collectBroadFileGlobs(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 { CURRENT_GRAPH_VERSION, emptyGraph, type LessonsGraph } from './graph-schema.js';\nimport { saveLessonsGraph, tryLoadLessonsGraph } from './graph-store.js';\nimport { sweepLessonsLeftovers } from './leftovers.js';\nimport { acquireLessonsLock, assertLessonsLockHeld } from './lessons-lock.js';\nimport { validateLessonsGraph, type ValidationFinding, type ValidationReport } from './validate.js';\n\n/** The validator refused a write; `findings` are the errors the change would add. */\nexport class LessonsWriteRefusedError extends Error {\n readonly findings: readonly ValidationFinding[];\n constructor(findings: readonly ValidationFinding[]) {\n const errors = findings.map((f) => `${f.code}: ${f.message.replace(/[.\\s]+$/, '')}`).join('; ');\n super(\n `Refused to save the lessons graph: this change would add ${errors}. Nothing was written.`,\n );\n this.name = 'LessonsWriteRefusedError';\n this.findings = findings;\n }\n}\n\nexport interface MutateOptions {\n readonly retries?: number;\n}\n\n/**\n * Stable identity of a finding, independent of its (churn-prone) message. Keyed on\n * code + the node it points at; findings carry a triggerId OR a lessonId (never a\n * topicId), so those two suffice to tell a pre-existing finding from a new one.\n */\nfunction findingKey(f: ValidationFinding): string {\n return `${f.code}|${f.triggerId ?? ''}|${f.lessonId ?? ''}`;\n}\n\nfunction errorSignatures(report: ValidationReport): Set<string> {\n return new Set(report.findings.filter((f) => f.level === 'error').map(findingKey));\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 sweepLessonsLeftovers(projectRoot);\n const graph = tryLoadLessonsGraph(projectRoot) ?? emptyGraph();\n // Snapshot pre-existing error findings BEFORE applying the mutation. We only\n // block on errors this mutation INTRODUCES — a single pre-existing invalid\n // trigger (from a merge/hand-edit) must not permanently poison every future\n // capture. recall already skips invalid triggers safely at runtime.\n const baseline = errorSignatures(validateLessonsGraph(graph));\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 const introduced = report.findings.filter(\n (f) => f.level === 'error' && !baseline.has(findingKey(f)),\n );\n if (introduced.length > 0) {\n throw new LessonsWriteRefusedError(introduced);\n }\n\n // Upgrade-on-write: every persisted graph is stamped at the current version,\n // so a loaded legacy v1 graph migrates to v2 the first time it is mutated.\n graph.version = CURRENT_GRAPH_VERSION;\n // A pause past the stale window lets a later writer take the lock and save;\n // saving now would silently erase that write.\n await assertLessonsLockHeld(release);\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 {\n describeUpsert,\n findExistingLessonByRule,\n makeLessonId,\n mergeTriggers,\n normalizeRule,\n todayIso,\n union,\n upsertLesson,\n} from './add-helpers.js';\nimport {\n assertRecallable,\n assertRuleShape,\n assertTriggerInputs,\n deadCommandWarning,\n dropDeadCommandTriggers,\n ensureTopic,\n skipsTriggerGates,\n type DeadCommandWarning,\n} from './add-gates.js';\nimport type { AutoPruneSummary } from './auto-prune.js';\nimport { type GuardrailWarning, inspectCapturedLesson } from './capture-guardrails.js';\nimport { nearDuplicateWarning } from './capture-near-duplicate.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { mutateLessonsGraph } from './mutate.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 BroadCommandPatternError,\n EmptyRuleError,\n InvalidTopicIdError,\n NoTriggerError,\n RuleTooLongError,\n TopicSummaryRequiredError,\n UnknownTopicError,\n UnrecallableLessonError,\n} from './add-errors.js';\nexport { TriggerFileGlobError } from './trigger-file-glob.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 /** `'always'` = a universal always-on lesson (no trigger needed; gates skipped). */\n readonly scope?: 'always';\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\ninterface AddLessonIntoOptions extends AddLessonOptions {\n /**\n * Project root for making absolute `--trigger-file` globs project-relative\n * (and rejecting ones outside it). `addLesson` sets it; legacy merge omits it.\n */\n readonly projectRoot?: string;\n}\n\n/** A non-blocking capture warning: a guardrail nudge or a dropped dead command trigger. */\nexport type AddLessonWarning = GuardrailWarning | DeadCommandWarning;\n\nexport interface AddLessonResult {\n readonly id: string;\n readonly isNewLesson: boolean;\n readonly isNewTopic: boolean;\n readonly newTriggerIds: string[];\n /** What a re-add changed on the existing lesson; empty for a new lesson or a no-op. */\n readonly changes: string[];\n /** Non-blocking capture warnings for the resulting (merged) lesson. */\n readonly warnings: AddLessonWarning[];\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\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(\n projectRoot,\n (graph) => addLessonInto(graph, input, { ...options, projectRoot }),\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: AddLessonIntoOptions,\n): AddLessonResult {\n const ruleKey = normalizeRule(input.rule);\n const trimmedRule = assertRuleShape(input.rule);\n const existingId = findExistingLessonByRule(graph, ruleKey);\n\n const isNewTopic = ensureTopic(graph, input.topic, options);\n\n // Gates (see add-gates.ts): a throw aborts the transactional write.\n const existing = existingId !== null ? graph.lessons[existingId] : undefined;\n assertTriggerInputs(input, options, existing?.triggers.length ?? 0);\n const merged = mergeTriggers(graph, input.triggers, options.projectRoot);\n const { triggerIds, newTriggerIds, dropped } = dropDeadCommandTriggers(graph, merged, options);\n if (!skipsTriggerGates(input, options)) {\n const resulting = existing === undefined ? triggerIds : union(existing.triggers, triggerIds);\n assertRecallable(graph, resulting, dropped);\n }\n const droppedWarnings = dropped.map(deadCommandWarning);\n\n if (existingId !== null && existing !== undefined) {\n const updated = upsertLesson(existing, input, triggerIds);\n graph.lessons[existingId] = updated;\n return {\n id: existingId,\n isNewLesson: false,\n isNewTopic,\n newTriggerIds,\n changes: describeUpsert(existing, updated),\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: [\n ...inspectCapturedLesson(graph, existingId, options.knownPaths),\n ...droppedWarnings,\n ],\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: [...new Set(input.evidence ?? [])],\n status: 'active',\n createdAt: input.createdAt ?? todayIso(),\n ...(input.rationale === undefined ? {} : { rationale: input.rationale }),\n ...(input.scope === 'always' ? { scope: 'always' as const } : {}),\n };\n const nearDup = nearDuplicateWarning(graph, id);\n return {\n id,\n isNewLesson: true,\n isNewTopic,\n newTriggerIds,\n changes: [],\n warnings: [\n ...inspectCapturedLesson(graph, id, options.knownPaths),\n ...(nearDup === null ? [] : [nearDup]),\n ...droppedWarnings,\n ],\n };\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 { realpath } from 'node:fs/promises';\nimport { basename, dirname, join, resolve, sep } from 'node:path';\n\n/** Resolve existing ancestors; a missing leaf is safe only for rename-based writes. */\nexport async function canonicalizePath(path: string): Promise<string> {\n try {\n return await realpath(path);\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n const parent = dirname(path);\n if (parent === path) return resolve(path);\n return join(await canonicalizePath(parent), basename(path));\n }\n}\n\nexport function isPathInside(target: string, root: string): boolean {\n return target === root || target.startsWith(root.endsWith(sep) ? root : `${root}${sep}`);\n}\n\nconst display = (path: string): string => path.replaceAll('\\\\', '/');\n\n/**\n * The error names where the path resolves to and the boundary it escapes, so a\n * user can see which symlink is responsible without rerunning under --verbose.\n */\nexport async function assertPathInsideRoot(root: string, target: string): Promise<void> {\n const rootAbs = resolve(root);\n const targetAbs = resolve(target);\n if (!isPathInside(targetAbs, rootAbs)) {\n throw new Error(`Unsafe filesystem path: ${display(target)} is outside ${display(rootAbs)}`);\n }\n let realTarget: string;\n let realRoot: string;\n try {\n [realTarget, realRoot] = await Promise.all([\n canonicalizePath(targetAbs),\n canonicalizePath(rootAbs),\n ]);\n } catch (cause: unknown) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n throw new Error(\n `Unsafe filesystem path: ${display(target)} could not be resolved (${detail})`,\n { cause },\n );\n }\n if (isPathInside(realTarget, realRoot)) return;\n throw new Error(\n `Unsafe filesystem path: ${display(target)} resolves to ${display(realTarget)} outside ${display(realRoot)}`,\n );\n}\n","/**\n * Reads the legacy YAML index + per-topic Markdown into graph pieces for the\n * migrator. The index is committed content, so every topic `file` is untrusted:\n * it must stay inside `<projectRoot>/.agentsmesh/lessons/` or nothing is read.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join, posix } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { assertPathInsideRoot } from '../utils/filesystem/path-containment.js';\nimport type { AddLessonInput } from './add.js';\nimport type { Lesson, Topic, Trigger } from './graph-schema.js';\nimport {\n collectClusterTriggerIds,\n LegacyIndexSchema,\n parseRulesSection,\n} from './import-legacy-parse.js';\nimport { lessonsPaths } from './paths.js';\n\nconst LESSONS_DIR = '.agentsmesh/lessons';\n\n/** Thrown when a legacy index points a topic file outside `.agentsmesh/lessons/`. */\nexport class LegacyTopicPathError extends Error {\n readonly code = 'LEGACY_TOPIC_PATH_OUTSIDE';\n constructor(file: string) {\n super(\n `Legacy topic file path is outside .agentsmesh/lessons/: ${file}. Refusing to migrate (legacy artifacts left intact).`,\n );\n this.name = 'LegacyTopicPathError';\n }\n}\n\n/**\n * Resolve a project-relative legacy topic path, refusing absolute paths, drive\n * or UNC paths (on any host OS), traversal after normalization, and symlinks\n * that resolve outside the lessons directory.\n */\nasync function resolveLegacyTopicPath(projectRoot: string, file: string): Promise<string> {\n const forward = file.replaceAll('\\\\', '/');\n const normalized = posix.normalize(forward);\n const relative =\n !/^[A-Za-z]:/.test(forward) &&\n !forward.startsWith('/') &&\n normalized.startsWith(`${LESSONS_DIR}/`);\n if (!relative) throw new LegacyTopicPathError(file);\n const target = join(projectRoot, normalized);\n try {\n await assertPathInsideRoot(join(projectRoot, LESSONS_DIR), target);\n } catch {\n throw new LegacyTopicPathError(file);\n }\n return target;\n}\n\nexport interface LegacySource {\n readonly topics: Record<string, Topic>;\n readonly triggers: Record<string, Trigger>;\n readonly lessons: Record<string, Lesson>;\n /** Per-lesson specs for the MERGE path (rule + raw trigger patterns + topic). */\n readonly specs: AddLessonInput[];\n readonly summaryByTopic: Map<string, string>;\n}\n\n/**\n * Parse the legacy store. Throws (nothing written or deleted) on a malformed\n * index, a topic path outside the lessons directory, or a missing topic file.\n */\nexport async function readLegacySource(\n projectRoot: string,\n migratedAt: string,\n): Promise<LegacySource> {\n const index = LegacyIndexSchema.parse(\n parseYaml(readFileSync(lessonsPaths(projectRoot).index, 'utf8')),\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 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 = await resolveLegacyTopicPath(projectRoot, cluster.file);\n if (!existsSync(topicFile)) {\n // Fail closed: migrating an incomplete graph would then delete the source.\n throw new Error(\n `Legacy topic file is missing: ${cluster.file}. Refusing to migrate (legacy artifacts left intact).`,\n );\n }\n\n for (const { index: ruleIndex, body, evidence } of parseRulesSection(\n readFileSync(topicFile, 'utf8'),\n )) {\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: 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: migratedAt,\n });\n }\n }\n\n return { topics, triggers: Object.fromEntries(triggersById), lessons, specs, summaryByTopic };\n}\n","import { existsSync } from 'node:fs';\nimport { CURRENT_GRAPH_VERSION } from './graph-schema.js';\nimport { deleteLegacyArtifacts } from './import-legacy-parse.js';\nimport { mergeLegacy } from './import-legacy-merge.js';\nimport { readLegacySource, type LegacySource } from './import-legacy-read.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 * Refuse ({@link LessonsGraphExistsError}) when `lessons.json` exists at write\n * time under the lock, even if empty. Auto-migration sets this so two first\n * writers cannot both migrate.\n */\n readonly requireAbsentGraph?: 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(\n 'A non-empty lessons.json already exists. Pass --force to overwrite it, or --merge to add the legacy lessons to it.',\n );\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 * Topic files outside `.agentsmesh/lessons/` are refused (LegacyTopicPathError).\n */\nexport async function importLegacyLessons(\n projectRoot: string,\n options: ImportLegacyOptions,\n): Promise<ImportLegacyReport> {\n const paths = lessonsPaths(projectRoot);\n if (options.merge === true) {\n const { specs, summaryByTopic } = await readLegacySource(projectRoot, options.migratedAt);\n return mergeLegacy(projectRoot, paths, specs, summaryByTopic, options);\n }\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 const { topics, lessons, triggers } = await mutateLessonsGraphLocked(projectRoot, async (g) => {\n // Existence is checked UNDER the lock (callers' checks are racy), and the\n // legacy store is read only after it, so a waiter never re-reads a store a\n // concurrent migrator already consumed. \"Populated\" means ANY content.\n if (options.requireAbsentGraph === true && existsSync(paths.graph)) {\n throw new LessonsGraphExistsError();\n }\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 const source: LegacySource = await readLegacySource(projectRoot, options.migratedAt);\n g.version = CURRENT_GRAPH_VERSION;\n g.lessons = source.lessons;\n g.topics = source.topics;\n g.triggers = source.triggers;\n return source;\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: Object.keys(triggers).length,\n };\n}\n","import { todayIso } from './add-helpers.js';\nimport { existsSync } from 'node:fs';\nimport { graphFilePath } from './graph-store.js';\nimport { importLegacyLessons, LessonsGraphExistsError } from './import-legacy.js';\nimport { lessonsPaths } from './paths.js';\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 * The unlocked checks are a fast path; `requireAbsentGraph` repeats the graph\n * check under the lessons lock before the legacy store is read.\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(), requireAbsentGraph: true });\n return true;\n } catch (err) {\n // Another writer created the graph (even an empty one) before we got the\n // lock — migration refused rather than clobber it. Not an error here.\n if (err instanceof LessonsGraphExistsError) return false;\n throw err;\n }\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\nimport { isTransientFsError, retryTransientSync } from '../utils/filesystem/transient-fs.js';\n\n/**\n * File-IO half of session dedup, split from seen-cache.ts for the 200-line\n * limit. Two on-disk shapes coexist: the legacy flat array of delivered ids\n * (untimed sessions — harness/hook and explicit ids), and a v2 object\n * `{ v: 2, seen: { id: deliveredAtMs } }` for TTL sessions (the `--session\n * auto` day bucket), whose entries expire so a later same-day session is not\n * starved. Every operation is best-effort — dedup is an optimization and must\n * never break the blocking recall path.\n */\n\nconst SEEN_DIR = 'agentsmesh-lessons-seen';\n\n/** Short, stable, dependency-free hash (djb2) of a string, base-36. */\nexport function shortHash(value: string): string {\n let h = 5381;\n for (let i = 0; i < value.length; i += 1) h = ((h << 5) + h + value.charCodeAt(i)) >>> 0;\n return h.toString(36);\n}\n\n/**\n * Store location. `projectRoot` namespaces by a hash of the resolved root, so\n * two projects sharing one session id keep SEPARATE dedup state. Omitted → the\n * legacy flat path.\n */\nexport function seenStorePath(id: string, projectRoot?: string): string {\n const safe = id.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 200);\n const scoped = projectRoot === undefined ? safe : `${safe}__${shortHash(resolve(projectRoot))}`;\n return join(tmpdir(), SEEN_DIR, `${scoped}.json`);\n}\n\n/** Parsed store: v2 carries per-id delivery stamps; legacy arrays carry ids only. */\nexport interface StoredSeen {\n readonly ids: ReadonlySet<string>;\n /** null for a legacy array store (no timestamps recorded). */\n readonly stamps: ReadonlyMap<string, number> | null;\n /**\n * Last time this session did ANYTHING (v2 only; absent on stores written\n * before the field existed). Distinct from the delivery stamps: a recall that\n * delivered nothing still counts as activity — see session-window.ts.\n */\n readonly lastAt?: number;\n}\n\n/** Read a store, tolerating both shapes; anything unreadable is an empty store. */\nexport function readSeenStore(path: string): StoredSeen {\n if (!existsSync(path)) return { ids: new Set(), stamps: null };\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (Array.isArray(parsed)) {\n const ids = new Set(parsed.filter((x): x is string => typeof x === 'string'));\n return { ids, stamps: null };\n }\n if (typeof parsed === 'object' && parsed !== null) {\n const seen = (parsed as Record<string, unknown>).seen;\n if (typeof seen === 'object' && seen !== null) {\n const stamps = new Map<string, number>();\n for (const [id, ms] of Object.entries(seen)) {\n if (typeof ms === 'number') stamps.set(id, ms);\n }\n const lastAt = (parsed as Record<string, unknown>).lastAt;\n return {\n ids: new Set(stamps.keys()),\n stamps,\n ...(typeof lastAt === 'number' ? { lastAt } : {}),\n };\n }\n }\n return { ids: new Set(), stamps: null };\n } catch {\n return { ids: new Set(), stamps: null };\n }\n}\n\n/** Atomic best-effort write; an array writes the legacy shape, a map writes v2. */\nexport function writeSeenStore(\n path: string,\n data: readonly string[] | ReadonlyMap<string, number>,\n lastAt?: number,\n): void {\n try {\n mkdirSync(dirname(path), { recursive: true });\n const body =\n data instanceof Map\n ? JSON.stringify({ v: 2, lastAt: lastAt ?? Date.now(), seen: Object.fromEntries(data) })\n : JSON.stringify(data);\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, body, 'utf8');\n // Windows: renaming onto a store another recall is reading fails with EPERM for a moment.\n retryTransientSync(() => renameSync(tmp, path));\n } catch {\n // Optimization only — never fail recall because the seen store could not be written.\n }\n}\n\n/** Best-effort removal (context reset). */\nexport function removeSeenStore(path: string): void {\n try {\n rmSync(path, { force: true, recursive: true });\n } catch {\n // Never let a dedup-reset failure break the blocking recall path.\n }\n}\n\n/** What an update writes: ids (legacy shape) or stamps (v2), or null for no write. */\nexport interface SeenWrite {\n readonly data: readonly string[] | ReadonlyMap<string, number>;\n}\n\n/** How long a commit waits for another recall's lock before writing anyway. */\nconst LOCK_WAIT_MS = 2_000;\n/** A lock this old was left by a crashed process. */\nconst LOCK_STALE_MS = 10_000;\nconst pause = new Int32Array(new SharedArrayBuffer(4));\n\nfunction lockIsStale(lock: string): boolean {\n try {\n return Date.now() - statSync(lock).mtimeMs > LOCK_STALE_MS;\n } catch {\n return false;\n }\n}\n\n/** Take the store's lock folder; false when it stays busy (the caller goes on unlocked). */\nfunction takeLock(lock: string): boolean {\n const deadline = Date.now() + LOCK_WAIT_MS;\n for (;;) {\n try {\n mkdirSync(dirname(lock), { recursive: true });\n mkdirSync(lock);\n return true;\n } catch (err) {\n // A lock another recall is removing fails with EPERM on Windows: still busy, not broken.\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST' && !isTransientFsError(err)) {\n return false;\n }\n }\n if (lockIsStale(lock)) removeSeenStore(lock);\n else if (Date.now() >= deadline) return false;\n else Atomics.wait(pause, 0, 0, 5);\n }\n}\n\n/**\n * Apply `update` to the LATEST store under a short lock, so overlapping recalls\n * add to each other's deliveries instead of overwriting them. Best-effort: a\n * lock that never frees means an unlocked write, never a failed recall.\n */\nexport function updateSeenStore(\n path: string,\n update: (latest: StoredSeen) => SeenWrite | null,\n): void {\n const lock = `${path}.lock`;\n const locked = takeLock(lock);\n try {\n const next = update(readSeenStore(path));\n if (next !== null) writeSeenStore(path, next.data);\n } finally {\n if (locked) removeSeenStore(lock);\n }\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 — on BOTH paths, so \"cat\"\n * cannot fire on \"category\", \"art\" cannot fire on \"start\", and a multi-word\n * 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/**\n * Tokens implied by the current edit/command — the recall's task context.\n *\n * Each identifier contributes BOTH its whole lowercased form AND its camelCase /\n * acronym sub-words. Retaining the whole token keeps this fully backward\n * compatible — every keyword trigger that matched before still matches — while the\n * sub-words give conceptual reach a compressed file path otherwise hides: `guard`\n * now reaches `useLeaveGuard`, `selector` reaches `InvoiceCompanySelector`. A\n * sub-word run follows its whole token, so a multi-word needle (`company selector`)\n * still matches as a contiguous run. UNFILTERED (stopwords kept) so \"read only\"\n * cannot match the non-adjacent \"read the only\".\n */\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 if (parts.length === 0) return [];\n const out: string[] = [];\n for (const raw of splitTokens(parts.join(' '))) {\n out.push(raw.toLowerCase());\n const sub = raw\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2') // camelCase / digit→Upper boundary\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2') // ACRONYM→Word boundary\n .toLowerCase()\n .split(' ')\n .filter((t) => t.length > 0);\n if (sub.length > 1) out.push(...sub);\n }\n return out;\n}\n\n/** Split on non-alphanumerics, keeping every word (stopwords included). Not lowercased. */\nfunction splitTokens(text: string): string[] {\n return text.split(/[^A-Za-z0-9]+/).filter((t) => t.length > 0);\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 const needle = tokenize(pattern);\n // 1. Explicit --keyword, as a contiguous token-run (never a mid-word substring).\n if (\n query.keyword !== undefined &&\n containsRun(needle, splitTokens(query.keyword.toLowerCase()))\n ) {\n return true;\n }\n // 2. Derived from file + command, on token boundaries.\n return containsRun(needle, deriveHaystackTokens(query));\n}\n","import { getGlobMatcher } from './glob-safety.js';\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\n/**\n * Query-wide budget for file_glob matching (DP cells, see glob-safety.ts). Each\n * glob is also capped per match; this bounds a graph full of costly globs to a\n * few tens of ms. A normal query uses well under 1%.\n */\nconst GLOB_MATCH_BUDGET = 2_000_000;\n\ntype MatchBudgets = Record<'command' | 'glob', WorkBudget>;\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 /** Set when the lesson was reached by its wording, not a trigger (lexical retrieval). */\n readonly lexical?: true;\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 // Always-on lessons are delivered on every task (see collectAlwaysLessons),\n // not via triggers — exclude them here so triggered recall never double-injects.\n if (lesson.scope === 'always') 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/**\n * Active always-on lessons (`scope: 'always'`) — universal standards delivered on\n * every task rather than matched by triggers. Sorted newest-first (then id) so a\n * token cap keeps the most recent; the caller bounds the set.\n */\nexport function collectAlwaysLessons(graph: LessonsGraph): MatchedLesson[] {\n const out: MatchedLesson[] = [];\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status === 'active' && lesson.scope === 'always') out.push({ id, lesson });\n }\n out.sort((a, b) =>\n a.lesson.createdAt !== b.lesson.createdAt\n ? a.lesson.createdAt < b.lesson.createdAt\n ? 1\n : -1\n : a.id < b.id\n ? -1\n : 1,\n );\n return out;\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 per kind, shared across ALL triggers of that kind in this query.\n const budgets: MatchBudgets = {\n command: { remaining: COMMAND_MATCH_BUDGET },\n glob: { remaining: GLOB_MATCH_BUDGET },\n };\n for (const [id, trigger] of Object.entries(graph.triggers)) {\n if (triggerMatches(trigger, query, budgets)) 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, budgets: MatchBudgets): boolean {\n switch (trigger.kind) {\n case 'file_glob': {\n if (query.file === undefined) return false;\n // Linear-time matcher; null = outside the safe glob subset, so a hostile\n // or unsupported glob is a non-match (fail closed, see glob-safety.ts).\n const matcher = getGlobMatcher(trigger.pattern);\n return matcher !== null && matcher.test(query.file, budgets.glob);\n }\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, budgets.command);\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\n/**\n * Fast-path parity probe: could a command-only query match ANY of these\n * patterns? MUST mirror {@link queryLessons}'s trigger matching exactly (same\n * linear engine, same budget seed, same keyword semantics) — a false \"cannot\n * match\" here would silently skip a mandatory recall. Consumed by\n * cmd-fastpath.ts against its precomputed active-trigger pattern lists.\n */\nexport function commandCouldMatch(\n commandPatterns: readonly string[],\n keywordPatterns: readonly string[],\n command: string,\n): boolean {\n const budget: WorkBudget = { remaining: COMMAND_MATCH_BUDGET };\n const query: LessonsQuery = { command };\n return (\n commandPatterns.some((p) => {\n const matcher = getCommandMatcher(p);\n return matcher !== null && matcher.test(command, budget);\n }) || keywordPatterns.some((p) => keywordMatches(p, query))\n );\n}\n","import {\n appendFileSync,\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readFileSync,\n readSync,\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) and rows their guard rejects, so a\n * diagnostic log can never crash stats. Every call is best-effort: a log that\n * cannot be written or read never breaks the recall hook or the command.\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 truncation to the last N\n * records within half the trigger, so a committed `.agentsmesh/` never\n * accumulates an unbounded diagnostic file, even from one giant line. 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/**\n * Append one record, creating parent dirs; truncate when past the byte trigger.\n * Never throws: a read-only or broken log path just drops the record.\n */\nexport function appendJsonl(path: string, record: unknown, opts: JsonlAppendOptions): void {\n try {\n mkdirSync(dirname(path), { recursive: true });\n // A file cut off mid-line would glue this record onto the broken one.\n const lead = endsWithoutNewline(path) ? '\\n' : '';\n appendFileSync(path, `${lead}${JSON.stringify(record)}\\n`, 'utf8');\n if (statSync(path).size > opts.trimTriggerBytes) {\n capJsonl(path, opts.maxRecords, opts.trimTriggerBytes / 2);\n }\n } catch {\n // Diagnostic side channel: losing a record beats breaking the caller.\n }\n}\n\nfunction endsWithoutNewline(path: string): boolean {\n let fd: number | undefined;\n try {\n const size = statSync(path).size;\n if (size === 0) return false;\n fd = openSync(path, 'r');\n const last = Buffer.alloc(1);\n readSync(fd, last, 0, 1, size - 1);\n return last[0] !== 0x0a;\n } catch {\n return false;\n } finally {\n if (fd !== undefined) closeSync(fd);\n }\n}\n\n/**\n * Truncate the log to its last `maxRecords` records that fit in `maxBytes`; a\n * single record larger than `maxBytes` is dropped. No-op when absent or already\n * within both caps. Rewrites atomically (temp + rename) so a reader never sees\n * a torn file. Idempotent and safe to call from any append path.\n */\nexport function capJsonl(path: string, maxRecords: number, maxBytes = Infinity): void {\n if (!existsSync(path)) return;\n const lines = readFileSync(path, 'utf8')\n .split('\\n')\n .filter((l) => l.trim().length > 0);\n const kept: string[] = [];\n let bytes = 0;\n for (let i = lines.length - 1; i >= 0 && kept.length < maxRecords; i -= 1) {\n const size = Buffer.byteLength(lines[i]!) + 1;\n if (size > maxBytes) continue;\n if (bytes + size > maxBytes) break;\n bytes += size;\n kept.push(lines[i]!);\n }\n if (kept.length === lines.length) return;\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, kept.length === 0 ? '' : `${kept.reverse().join('\\n')}\\n`, 'utf8');\n renameSync(tmp, path);\n}\n\n/** The whole file, or only its last `maxBytes` from the first full line on. */\nfunction readTail(path: string, maxBytes: number | undefined): string {\n const size = maxBytes === undefined ? 0 : statSync(path).size;\n if (maxBytes === undefined || size <= maxBytes) return readFileSync(path, 'utf8');\n const fd = openSync(path, 'r');\n try {\n const tail = Buffer.alloc(maxBytes);\n readSync(fd, tail, 0, maxBytes, size - maxBytes);\n const text = tail.toString('utf8');\n return text.slice(text.indexOf('\\n') + 1);\n } finally {\n closeSync(fd);\n }\n}\n\n/**\n * Read every record `isRecord` accepts, skipping torn or malformed lines; with\n * `maxBytes`, only the newest records in that many bytes. Returns [] when the\n * log is absent or cannot be read.\n */\nexport function readJsonl<T>(\n path: string,\n isRecord: (value: unknown) => value is T,\n opts: { readonly maxBytes?: number } = {},\n): T[] {\n let text: string;\n try {\n text = readTail(path, opts.maxBytes);\n } catch {\n return [];\n }\n const out: T[] = [];\n for (const line of text.split('\\n')) {\n if (line.trim().length === 0) continue;\n try {\n const value: unknown = JSON.parse(line);\n if (isRecord(value)) out.push(value);\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","/** Shared runtime type guards. */\n\n/** True for a non-null, non-array object — the shape every config/settings merger narrows to. */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import type { CaptureTelemetryRecord } from './capture-telemetry.js';\nimport { isRecord } from '../utils/types/guards.js';\nimport type { OutcomeEvent } from './outcome-log.js';\nimport type { RecallTelemetryRecord } from './telemetry.js';\n\n/**\n * Shape guards for the lessons JSONL logs. A log is plain text that can be\n * hand-edited, merged or committed, so every reader keeps only rows with the\n * fields its consumers read. Optional fields are checked only when present,\n * so rows written before a field existed still count.\n */\n\nconst isStr = (v: unknown): v is string => typeof v === 'string';\nconst isNum = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);\nconst isBool = (v: unknown): v is boolean => typeof v === 'boolean';\nconst isStrList = (v: unknown): boolean => Array.isArray(v) && v.every(isStr);\nconst optional = (v: unknown, check: (x: unknown) => boolean): boolean =>\n v === undefined || check(v);\n\n/** An object whose `file`, `command` and `keyword` counts are numbers. */\nconst isKindCounts = (v: unknown): boolean =>\n isRecord(v) && isNum(v.file) && isNum(v.command) && isNum(v.keyword);\n\nexport function isOutcomeEvent(v: unknown): v is OutcomeEvent {\n if (!isRecord(v) || !isStr(v.ts) || !isStr(v.contextKey)) return false;\n if (!optional(v.session, isStr)) return false;\n if (v.kind === 'delivered') return isStr(v.lessonId) && optional(v.rank, isNum);\n return v.kind === 'failure' && optional(v.errorClass, isStr);\n}\n\nexport function isRecallRecord(v: unknown): v is RecallTelemetryRecord {\n return (\n isRecord(v) &&\n isStr(v.ts) &&\n [v.hasFile, v.hasCommand, v.hasKeyword, v.truncated].every(isBool) &&\n [v.totalMatches, v.returnedCount, v.returnedTokens].every(isNum) &&\n isKindCounts(v.matchedByKind) &&\n optional(v.contextKey, isStr) &&\n optional(v.session, isStr) &&\n optional(v.lessonIds, isStrList) &&\n optional(v.bypassed, isBool)\n );\n}\n\nexport function isCaptureRecord(v: unknown): v is CaptureTelemetryRecord {\n return (\n isRecord(v) &&\n isStr(v.ts) &&\n [v.isNewLesson, v.isNewTopic, v.blocked].every(isBool) &&\n isNum(v.newTriggerCount) &&\n isKindCounts(v.triggerKinds) &&\n isStrList(v.warningCodes) &&\n optional(v.session, isStr) &&\n optional(v.lessonId, isStr)\n );\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { stripBom } from '../utils/filesystem/fs-text-encoding.js';\nimport { appendJsonl, logExists, readJsonl } from './jsonl-log.js';\nimport { isRecallRecord } from './log-record-guards.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. Opt in per project with `\"telemetry\": true` in\n * `.agentsmesh/lessons/config.json`, or per process with {@link TELEMETRY_ENV}\n * (`1` forces on, `0` forces off). The config path exists because the hooks are\n * the most important writer and a hook spawned by a desktop app inherits none of\n * the user's shell exports: an env-only gate left every hook blind for weeks\n * while the CLI in a terminal kept logging. Records carry field-PRESENCE\n * booleans only — never the raw file / command / keyword text — so the log stays\n * 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 /**\n * The normalized action this recall was for (`file:src/x.ts`, `cmd:git commit`,\n * or `none` for a keyword-only query) — the SAME key the outcome log uses, so\n * this stores no content the logs did not already hold.\n *\n * Without it the log proves a recall happened but not for which action, so\n * occurrences per action cannot be counted and no before/after effectiveness\n * claim is computable. Optional because records written before this existed\n * have no key.\n */\n readonly contextKey?: string;\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 /** Candidates reached by rule wording (lexical retrieval). Absent on older rows. */\n readonly text?: 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\n/** A boolean field of the project's lessons config; undefined when absent or unreadable. */\nexport function configFlag(projectRoot: string, key: string): boolean | undefined {\n const path = lessonsPaths(projectRoot).config;\n if (!existsSync(path)) return undefined;\n try {\n const parsed: unknown = JSON.parse(stripBom(readFileSync(path, 'utf8')));\n if (typeof parsed !== 'object' || parsed === null) return undefined;\n const value = (parsed as Record<string, unknown>)[key];\n return typeof value === 'boolean' ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** `1`/`true`/`yes`/`on` force on, `0`/`false`/`no`/`off` force off; else the config decides. */\nfunction envOverride(raw: string | undefined): boolean | undefined {\n const value = raw?.trim().toLowerCase();\n if (value === '1' || value === 'true' || value === 'yes' || value === 'on') return true;\n if (value === '0' || value === 'false' || value === 'no' || value === 'off') return false;\n return undefined;\n}\n\n/**\n * The env var wins in both directions (`1` on, `0` off); otherwise the project\n * config decides when a root is known. Writers pass their project root so a\n * hook process with an empty environment still honours the project's opt-in.\n */\nexport function isTelemetryEnabled(\n env: NodeJS.ProcessEnv = process.env,\n projectRoot?: string,\n): boolean {\n return (\n envOverride(env[TELEMETRY_ENV]) ??\n (projectRoot !== undefined && configFlag(projectRoot, 'telemetry') === true)\n );\n}\n\n/**\n * Env override for the outcome log (`1` on, `0` off). The outcome log is a\n * separate switch from telemetry: repeat-failure detection reads it, so it is\n * ON unless `.agentsmesh/lessons/config.json` sets `\"outcomeLog\": false`. It is\n * local, gitignored and holds normalized keys and error classes only.\n */\nexport const OUTCOME_LOG_ENV = 'AGENTSMESH_LESSONS_OUTCOME_LOG';\n\nexport function isOutcomeLogEnabled(\n env: NodeJS.ProcessEnv = process.env,\n projectRoot?: string,\n): boolean {\n return (\n envOverride(env[OUTCOME_LOG_ENV]) ??\n (projectRoot === undefined || configFlag(projectRoot, 'outcomeLog') !== false)\n );\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, projectRoot)) return;\n appendJsonl(recallLogPath(projectRoot), record, {\n maxRecords: MAX_RECALL_LOG_RECORDS,\n trimTriggerBytes: RECALL_LOG_TRIM_TRIGGER_BYTES,\n });\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 every well-formed recall record. Returns [] when absent or unreadable. */\nexport function readRecallLog(projectRoot: string): RecallTelemetryRecord[] {\n return readJsonl(recallLogPath(projectRoot), isRecallRecord, {\n maxBytes: RECALL_LOG_TRIM_TRIGGER_BYTES,\n });\n}\n","import { shortHash } from './seen-store.js';\nimport { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { graphFilePath } from './graph-store.js';\nimport { commandCouldMatch } from './query.js';\nimport { appendRecallRecord, sessionId as envSessionId } from './telemetry.js';\n\n/**\n * Command-recall fast path. The hook recalls on EVERY shell command, but a\n * graph holds few command_pattern/keyword triggers relative to the command\n * firehose, so most command-only recalls provably match nothing yet still pay\n * a full graph parse + outcome-log read (field-measured at >80% no-match). This\n * caches the active command-reachable trigger patterns in the OS temp dir\n * (never the project tree), stamped with the graph file's (mtimeMs, size):\n * a stale or missing or corrupt cache ALWAYS falls back to the full path, so\n * the worst failure mode is \"no speedup\", never a skipped match. Matching\n * reuses `commandCouldMatch` — the exact engine `queryLessons` runs — so the\n * fast \"cannot match\" verdict and the full path agree by construction.\n */\n\nconst FASTPATH_DIR = 'agentsmesh-lessons-cmdidx';\n\ninterface FastpathCache {\n readonly stamp: { readonly mtimeMs: number; readonly size: number };\n readonly commandPatterns: readonly string[];\n readonly keywordPatterns: readonly string[];\n}\n\n/** Short, stable, dependency-free hash (djb2) of a string, base-36. */\n/** Cache location (per project, in the OS temp dir). Exported for tests. */\nexport function commandFastpathCachePath(projectRoot: string): string {\n return join(tmpdir(), FASTPATH_DIR, `${shortHash(resolve(projectRoot))}.json`);\n}\n\n/**\n * The graph file's freshness stamp RIGHT NOW. Callers that go on to read the\n * graph must take this BEFORE the read and hand it to\n * {@link refreshCommandFastpath} — stamping after the read races a concurrent\n * atomic graph write (stale patterns under a fresh stamp = a poisoned cache\n * that produces false \"cannot match\" verdicts until the next write).\n */\nexport function currentGraphStamp(projectRoot: string): { mtimeMs: number; size: number } | null {\n try {\n const s = statSync(graphFilePath(projectRoot));\n return { mtimeMs: s.mtimeMs, size: s.size };\n } catch {\n return null;\n }\n}\n\nfunction isStringArray(v: unknown): v is readonly string[] {\n return Array.isArray(v) && v.every((x) => typeof x === 'string');\n}\n\nfunction readCache(path: string): FastpathCache | null {\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (typeof parsed !== 'object' || parsed === null) return null;\n const c = parsed as Record<string, unknown>;\n const stamp = c.stamp as Record<string, unknown> | undefined;\n if (\n typeof stamp?.mtimeMs !== 'number' ||\n typeof stamp.size !== 'number' ||\n !isStringArray(c.commandPatterns) ||\n !isStringArray(c.keywordPatterns)\n ) {\n return null;\n }\n return {\n stamp: { mtimeMs: stamp.mtimeMs, size: stamp.size },\n commandPatterns: c.commandPatterns,\n keywordPatterns: c.keywordPatterns,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Write (or freshen) the cache from a loaded graph. Best-effort: any failure is\n * swallowed — the cache is an optimization, never a dependency. Extraction\n * mirrors `queryLessons`'s lesson filter: triggers reachable via ACTIVE,\n * non-always lessons only (always-on lessons are delivered, not matched).\n *\n * `preReadStamp` is the stamp the caller took BEFORE reading `graph`\n * ({@link currentGraphStamp}). The write happens only when the file still\n * carries that exact stamp: a mismatch means an atomic write landed inside the\n * read window and `graph` no longer describes the file — caching it under the\n * new stamp would be a self-perpetuating false \"cannot match\". Skipping is\n * safe: the next recall re-reads and re-tries.\n */\nexport function refreshCommandFastpath(\n projectRoot: string,\n graph: LessonsGraph,\n preReadStamp: { mtimeMs: number; size: number } | null,\n): void {\n try {\n if (preReadStamp === null) return;\n const stamp = currentGraphStamp(projectRoot);\n if (stamp === null) return;\n if (stamp.mtimeMs !== preReadStamp.mtimeMs || stamp.size !== preReadStamp.size) return;\n const path = commandFastpathCachePath(projectRoot);\n const existing = readCache(path);\n if (\n existing !== null &&\n existing.stamp.mtimeMs === stamp.mtimeMs &&\n existing.stamp.size === stamp.size\n ) {\n return;\n }\n const reachable = new Set<string>();\n for (const lesson of Object.values(graph.lessons)) {\n if (lesson.status !== 'active' || lesson.scope === 'always') continue;\n for (const t of lesson.triggers) reachable.add(t);\n }\n const commandPatterns: string[] = [];\n const keywordPatterns: string[] = [];\n for (const [id, trigger] of Object.entries(graph.triggers)) {\n if (!reachable.has(id)) continue;\n if (trigger.kind === 'command_pattern') commandPatterns.push(trigger.pattern);\n else if (trigger.kind === 'keyword') keywordPatterns.push(trigger.pattern);\n }\n const cache: FastpathCache = { stamp, commandPatterns, keywordPatterns };\n mkdirSync(dirname(path), { recursive: true });\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify(cache), 'utf8');\n renameSync(tmp, path);\n } catch {\n // Optimization only — never let a cache write break recall.\n }\n}\n\n/**\n * True ONLY when a fresh cache proves no active trigger can match `command`.\n * Every uncertain condition (no cache, stale stamp, corrupt file, fs error)\n * returns false, sending the caller down the full recall path.\n */\nexport function commandDefinitelyUnmatched(projectRoot: string, command: string): boolean {\n try {\n const stamp = currentGraphStamp(projectRoot);\n if (stamp === null) return false;\n const cache = readCache(commandFastpathCachePath(projectRoot));\n if (cache === null) return false;\n if (cache.stamp.mtimeMs !== stamp.mtimeMs || cache.stamp.size !== stamp.size) return false;\n return !commandCouldMatch(cache.commandPatterns, cache.keywordPatterns, command);\n } catch {\n return false;\n }\n}\n\n/**\n * Telemetry parity for a fast-path exit: the full path writes a no-match recall\n * record, so the fast path must too or `stats` silently loses its no-match\n * volume. Gated on the same telemetry env inside appendRecallRecord.\n */\nexport function recordFastpathNoMatch(projectRoot: string, session?: string): void {\n const sess = session ?? envSessionId();\n appendRecallRecord(projectRoot, {\n ts: new Date().toISOString(),\n hasFile: false,\n hasCommand: true,\n hasKeyword: false,\n totalMatches: 0,\n returnedCount: 0,\n returnedTokens: 0,\n truncated: false,\n matchedByKind: { file: 0, command: 0, keyword: 0 },\n lessonIds: [],\n bypassed: false,\n ...(sess !== undefined ? { session: sess } : {}),\n });\n}\n\n/**\n * Hook-facing composite: true (after recording no-match telemetry) when this\n * tool call is a command-only recall that provably matches nothing. False for\n * anything uncertain or out of scope (file present, diff keyword present),\n * sending the hook down the full recall path.\n */\nexport function hookCommandFastpath(\n projectRoot: string,\n input: { file?: string; command?: string; keyword: string; sessionId?: string },\n): boolean {\n if (input.file !== undefined || input.command === undefined || input.keyword.length > 0) {\n return false;\n }\n if (!commandDefinitelyUnmatched(projectRoot, input.command)) return false;\n recordFastpathNoMatch(projectRoot, input.sessionId);\n return true;\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport { queryLessons, type LessonsQuery, type MatchedLesson } from './query.js';\nimport { bm25, buildCorpus, tokenize } from './ranking-text.js';\n\n/**\n * Lexical retrieval: reach a lesson by the wording of its rule, not only by a\n * trigger. Trigger recall is exact and cheap, but a conceptual lesson fires only\n * when its keyword trigger happens to appear in the task text; phrased another\n * way, it is silent. Scoring the task text against every active rule with the\n * BM25 the ranker already owns closes most of that gap for zero dependencies.\n *\n * Runs ONLY for keyword-only queries — the prompt-submit hook and the task-start\n * `lessons query --keyword` — never for a file/command query, where a wording\n * match would be weaker evidence than the trigger that fired and precision is\n * what matters. Candidates carry `lexical: true`; they match no trigger, so the\n * ranker's specificity puts them below any triggered lesson.\n */\n\n/** Most wording matches added per recall; the caps still apply after ranking. */\nexport const LEXICAL_LIMIT = 3;\n/** Distinct query terms a rule must contain; one shared word is coincidence. */\nexport const LEXICAL_MIN_TERMS = 2;\n\n/**\n * Words too generic to count toward the gate. The ranker's stoplist is tiny on\n * purpose (BM25 weighs the rest by rarity), but the gate is a yes/no: \"top\" and\n * \"left\" once qualified a merge-conflict-marker rule for an SVG prompt. BM25\n * still scores these; they just cannot be the reason a rule qualifies.\n */\nconst GENERIC = new Set(\n (\n 'top left right bottom before after first last next new old use used using run make keep set ' +\n 'get add all any each every not no never always only one two more less same other than then ' +\n 'into from over under out up down off via per so if else when where which what who how why ' +\n 'do does did done can could should would will may might has have had are was were been being ' +\n 'also still just even very both either such these those they them their we you your our he ' +\n 'she his her my me our us own same here there now then again once about above below between ' +\n 'during through until while because but by need needs needed way ways thing things'\n ).split(' '),\n);\n\nexport function isKeywordOnlyQuery(query: LessonsQuery): boolean {\n return query.keyword !== undefined && query.file === undefined && query.command === undefined;\n}\n\nexport interface MatchResult {\n /** Trigger matches first, then wording matches (each flagged `lexical`). */\n readonly matches: MatchedLesson[];\n /** How many of `matches` came from wording, for telemetry. */\n readonly lexicalCount: number;\n}\n\n/** The one candidate step every recall entry point shares (CLI, MCP, hook). */\nexport function matchLessons(graph: LessonsGraph, query: LessonsQuery): MatchResult {\n const triggered = queryLessons(graph, query);\n const lexical =\n isKeywordOnlyQuery(query) && query.keyword !== undefined\n ? lexicalCandidates(\n graph,\n query.keyword,\n triggered.map((m) => m.id),\n )\n : [];\n return { matches: [...triggered, ...lexical], lexicalCount: lexical.length };\n}\n\n/**\n * Active, non-always lessons whose rule shares at least {@link LEXICAL_MIN_TERMS}\n * distinct terms with `keyword`, best BM25 first, capped at {@link LEXICAL_LIMIT}.\n * `excludeIds` are the lessons a trigger already matched.\n */\nexport function lexicalCandidates(\n graph: LessonsGraph,\n keyword: string,\n excludeIds: readonly string[],\n): MatchedLesson[] {\n const terms = [...new Set(tokenize(keyword))];\n if (terms.length < LEXICAL_MIN_TERMS) return [];\n const excluded = new Set(excludeIds);\n const corpus = buildCorpus(graph);\n const scored: { id: string; lesson: LessonsGraph['lessons'][string]; score: number }[] = [];\n for (const [id, lesson] of Object.entries(graph.lessons)) {\n if (lesson.status !== 'active' || lesson.scope === 'always' || excluded.has(id)) continue;\n const ruleTerms = new Set(tokenize(lesson.rule));\n let shared = 0;\n for (const t of terms) if (!GENERIC.has(t) && ruleTerms.has(t)) shared += 1;\n if (shared < LEXICAL_MIN_TERMS) continue;\n scored.push({ id, lesson, score: bm25(terms, lesson.rule, corpus) });\n }\n scored.sort((a, b) => (b.score !== a.score ? b.score - a.score : a.id < b.id ? -1 : 1));\n return scored.slice(0, LEXICAL_LIMIT).map(({ id, lesson }) => ({ id, lesson, lexical: true }));\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport { globNarrowness } from './glob-breadth.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 * A keyword can match a `--file` query incidentally, because recall also tests\n * the path's own tokens: \"lessons recall\" hits `src/lessons/recall.ts`. That is\n * weaker evidence than any glob deliberately written about the path, so it\n * ranks below every such glob and above only a repo-wide one. In a keyword\n * query every match is a keyword, so they all tie here and the ordering is the\n * one this signal never touched.\n */\nconst KEYWORD_NARROWNESS = 0.4;\n\n/**\n * Narrowness per trigger id, in [0,1]. A `file_glob` scores by how much of the\n * path it pins down; a keyword scores the constant above; a command pattern is\n * neutral, since it can only match a command query where every rival is also a\n * command pattern.\n */\nexport function buildNarrowness(graph: LessonsGraph): Map<string, number> {\n const narrowness = new Map<string, number>();\n for (const [id, trigger] of Object.entries(graph.triggers)) {\n if (trigger.kind === 'file_glob') narrowness.set(id, globNarrowness(trigger.pattern));\n else narrowness.set(id, trigger.kind === 'keyword' ? KEYWORD_NARROWNESS : 1);\n }\n return narrowness;\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 type { Lesson, LessonsGraph } from './graph-schema.js';\nimport { collectMatchedTriggerIds, type LessonsQuery, type MatchedLesson } from './query.js';\nimport { buildFanout, buildNarrowness, 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 /** Reached by rule wording rather than a trigger (see lexical-retrieval.ts). */\n readonly lexical?: true;\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 * Per-lesson effectiveness score in [0,1] from the outcome log (1 = always\n * helped; absent = neutral). Fed as a LOW-weight RRF signal so a proven\n * fire-but-fail lesson sinks below an equally-matched effective one — a\n * corrective nudge, never a driver. Empty/absent ⇒ every lesson ties on this\n * signal ⇒ ordering is unchanged from the pre-effectiveness ranker.\n */\n readonly effectiveness?: ReadonlyMap<string, 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 = 1200;\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 */\n// Strictly greater than TOPIC_COHERENCE + BM25 + EFFECTIVENESS, so a lesson\n// that wins specificity cannot be outvoted by a clean sweep of the weaker\n// signals. Mandatory recall fires on --file/--cmd, where \"which trigger matched\n// and how precisely\" is the evidence; the rest only order what specificity ties.\nconst SPECIFICITY_WEIGHT = 5;\nconst TOPIC_COHERENCE_WEIGHT = 2;\nconst BM25_WEIGHT = 1;\n// Effectiveness (outcome-log) is a corrective nudge, not a driver — the same low\n// weight as BM25, so it only sinks a proven fire-but-fail lesson below an\n// equally-matched sibling and never overrides a specificity lead. Neutral (every\n// lesson equal) when the log carries no signal, so ranking is then unchanged.\nconst EFFECTIVENESS_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 narrowness = buildNarrowness(graph);\n const coherence = buildTopicCoherence(matches);\n const matchedTriggerIds = collectMatchedTriggerIds(graph, query);\n\n const scored = matches.map(({ id, lesson, lexical }) => {\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 // Fanout alone cannot separate a pinpoint glob from a subtree glob (trigger\n // ids are content-addressed, so both are referenced once); narrowness does.\n for (const t of hitTriggers) {\n specificity = Math.max(specificity, (narrowness.get(t) ?? 1) / fanout.get(t)!);\n }\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 // Absent from the log ⇒ neutral 1, so a lesson with no outcome data never\n // sinks below one that has merely been recorded.\n effectiveness: options.effectiveness?.get(id) ?? 1,\n lexical,\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 const effRanks = rankMap(scored.map((s) => ({ id: s.id, value: s.effectiveness })));\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 EFFECTIVENESS_WEIGHT / (RRF_K + effRanks.get(s.id)!),\n reason: {\n matchedTriggers: s.matchedTriggers,\n bm25: s.bm25,\n specificity: s.specificity,\n topicCoherence: s.topicCoherence,\n ...(s.lexical === true ? { lexical: true as const } : {}),\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 { stripBom } from '../utils/filesystem/fs-text-encoding.js';\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 /** Opt into the recall and capture logs that `stats` and the health view read. */\n readonly telemetry: boolean;\n /** The outcome log behind effectiveness ranking; its own switch, on by default (see telemetry.ts). */\n readonly outcomeLog: 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 telemetry: false,\n outcomeLog: true,\n };\n}\n\n/**\n * Hard ceilings for the committed config. `config.json` is git-tracked, so a\n * cloned repo sets these; without a cap it could make every recall inject\n * hundreds of thousands of characters. 50 lessons / 8000 tokens (~32k chars)\n * is 5x/6x the defaults. Per-invocation flags are the user's own and not capped.\n */\nexport const MAX_RECALL_LIMIT = 50;\nexport const MAX_RECALL_MAX_TOKENS = 8000;\n\nfunction positiveInt(value: unknown): number | null {\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : null;\n}\n\nfunction clamped(value: unknown, ceiling: number): number | null {\n const n = positiveInt(value);\n return n === null ? null : Math.min(n, ceiling);\n}\n\nfunction overCeiling(value: unknown, ceiling: number): boolean {\n const n = positiveInt(value);\n return n !== null && n > ceiling;\n}\n\nfunction invalidFields(fields: readonly string[], expected: string): string {\n return (\n `lessons config.json has invalid ${fields.join(' and ')} (expected ${expected}) — using the ` +\n `default for ${fields.length === 1 ? 'it' : 'them'}.`\n );\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(stripBom(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 || Array.isArray(parsed)) {\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 badInts = ['recallLimit', 'recallMaxTokens'].filter(\n (key) => key in cfg && positiveInt(cfg[key]) === null,\n );\n const badSwitches = ['autoPrune', 'telemetry', 'outcomeLog'].filter(\n (key) => key in cfg && typeof cfg[key] !== 'boolean',\n );\n const invalid = [\n ...(badInts.length > 0 ? [invalidFields(badInts, 'a positive integer')] : []),\n ...(badSwitches.length > 0 ? [invalidFields(badSwitches, 'true or false')] : []),\n ];\n if (invalid.length > 0) return invalid.join(' ');\n const over: string[] = [];\n if (overCeiling(cfg.recallLimit, MAX_RECALL_LIMIT))\n over.push(`recallLimit above ${MAX_RECALL_LIMIT}`);\n if (overCeiling(cfg.recallMaxTokens, MAX_RECALL_MAX_TOKENS)) {\n over.push(`recallMaxTokens above ${MAX_RECALL_MAX_TOKENS}`);\n }\n if (over.length > 0) {\n return `lessons config.json sets ${over.join(' and ')} — clamped to the ceiling.`;\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(stripBom(readFileSync(path, 'utf8')));\n if (typeof parsed !== 'object' || parsed === null) return fallback;\n const cfg = parsed as Record<string, unknown>;\n return {\n limit: clamped(cfg.recallLimit, MAX_RECALL_LIMIT) ?? fallback.limit,\n maxTokens: clamped(cfg.recallMaxTokens, MAX_RECALL_MAX_TOKENS) ?? fallback.maxTokens,\n };\n } catch {\n return fallback;\n }\n}\n","import { posix } from 'node:path';\n\n/**\n * Reduce a shell command to the program it really runs plus an optional\n * subcommand — the stable CLASS outcomes and command triggers bind to.\n *\n * A compound command is split on `&&`, `||`, `;`, `|` and newlines (outside\n * quotes); segments that only navigate or set up the shell (`cd`, `export`,\n * `set`, comments, loop headers) are skipped, so `cd /repo && pnpm tsc` keys as\n * `pnpm tsc`, not `cd`. For programs with known global flags, those flags (and\n * their values) are skipped before the subcommand: `git -C app commit` →\n * `git commit`. Other programs keep the operand rule: past a flag, a bare word\n * is an argument (`rm -rf build` → `rm`).\n */\n\nexport interface CommandClass {\n readonly program: string;\n readonly subcommand?: string;\n /** True when global flags sat between program and subcommand (`git -C x commit`). */\n readonly gapped: boolean;\n}\n\n/** Value-taking global flags of programs whose first plain word is a subcommand. */\nconst GLOBAL_VALUE_FLAGS: ReadonlyMap<string, readonly string[]> = new Map([\n [\n 'git',\n ['-C', '-c', '--git-dir', '--work-tree', '--namespace', '--super-prefix', '--config-env'],\n ],\n ['npm', ['--prefix', '-w', '--workspace', '--userconfig', '--cache', '--loglevel']],\n ['pnpm', ['-C', '--dir', '-F', '--filter', '--loglevel', '--reporter']],\n ['yarn', ['--cwd']],\n ['npx', ['-p', '--package', '-c', '--call']],\n ['bun', ['--cwd', '--config']],\n ['bunx', ['-p', '--package']],\n ['make', ['-C', '--directory', '-f', '--file', '--makefile', '-I', '--include-dir']],\n ['docker', ['-H', '--host', '--context', '-c', '--config', '-l', '--log-level']],\n [\n 'kubectl',\n ['-n', '--namespace', '--context', '--kubeconfig', '--cluster', '--user', '-s', '--server'],\n ],\n ['cargo', ['-C', '--config', '-Z', '--color']],\n ['go', ['-C']],\n]);\n\n/** Programs that only move around or set up the shell — never the action itself. */\nconst SHELL_SETUP = new Set([\n 'cd',\n 'pushd',\n 'popd',\n 'export',\n 'set',\n 'unset',\n 'source',\n '.',\n '[',\n '[[',\n 'test',\n 'true',\n 'false',\n ':',\n]);\n/** Leading shell keywords stripped before the program. */\nconst SHELL_PREFIX = new Set(['if', 'then', 'else', 'elif', 'do', 'while', 'until', '!', 'time']);\n/** Segments that are shell block syntax, not a command. */\nconst BLOCK_SYNTAX = new Set(['for', 'case', 'select', 'function', 'done', 'fi', 'esac']);\n\nconst ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=/;\nconst SUBCOMMAND = /^[A-Za-z][A-Za-z0-9_-]*(?::[A-Za-z0-9_-]+)*$/;\n\n/** Split on `&&`, `||`, `;`, `|`, `|&` and newlines outside quotes. */\nfunction splitSegments(command: string): string[] {\n const out: string[] = [];\n let cur = '';\n let quote: string | null = null;\n for (let i = 0; i < command.length; i += 1) {\n const ch = command[i]!;\n const next = command[i + 1];\n if (quote !== null) {\n cur += ch;\n if (ch === quote) quote = null;\n continue;\n }\n if (ch === \"'\" || ch === '\"' || ch === '`') {\n quote = ch;\n cur += ch;\n } else if (ch === '\\\\' && next !== undefined) {\n cur += ch + next;\n i += 1;\n } else if (ch === ';' || ch === '\\n' || ch === '|' || (ch === '&' && next === '&')) {\n out.push(cur);\n cur = '';\n if (ch !== ';' && ch !== '\\n' && (next === ch || next === '&')) i += 1;\n } else {\n cur += ch;\n }\n }\n out.push(cur);\n return out;\n}\n\n/** `node_modules/.bin/vitest` → `vitest`; a plain name is kept. */\nfunction programName(word: string): string {\n return posix.basename(word.replaceAll('\\\\', '/')) || word;\n}\n\nfunction subcommandOf(program: string, args: readonly string[]): Omit<CommandClass, 'program'> {\n const valueFlags = GLOBAL_VALUE_FLAGS.get(program);\n let i = 0;\n while (valueFlags !== undefined && i < args.length && /^-./.test(args[i]!)) {\n const flag = args[i]!;\n i += flag !== '--' && !flag.includes('=') && valueFlags.includes(flag) ? 2 : 1;\n if (flag === '--') break;\n }\n const next = args[i];\n return next !== undefined && SUBCOMMAND.test(next)\n ? { subcommand: next, gapped: i > 0 }\n : { gapped: false };\n}\n\nfunction segmentClass(segment: string): CommandClass | null {\n const words = segment\n .replace(/^[\\s({]+/, '')\n .replace(/[\\s)}]+$/, '')\n .split(/\\s+/)\n .filter((w) => w.length > 0);\n while (words.length > 0 && SHELL_PREFIX.has(words[0]!)) words.shift();\n const first = words[0];\n if (first === undefined || first.startsWith('#') || BLOCK_SYNTAX.has(first)) return null;\n while (words.length > 0 && ASSIGNMENT.test(words[0]!)) words.shift();\n if (words.length === 0) return null;\n const program = programName(words[0]!);\n return { program, ...subcommandOf(program, words.slice(1)) };\n}\n\n/** The class of the first segment that runs a real program, else of the first setup step. */\nexport function commandClass(command: string): CommandClass | null {\n let setup: CommandClass | null = null;\n for (const segment of splitSegments(command.replace(/\\\\\\r?\\n/g, ' '))) {\n const cls = segmentClass(segment);\n if (cls === null) continue;\n if (!SHELL_SETUP.has(cls.program)) return cls;\n setup ??= { program: cls.program, gapped: false };\n }\n return setup;\n}\n","import { commandClass } from './command-class.js';\nimport { normalizeRecallFile } from './normalize-query-file.js';\n\n/**\n * A `contextKey` binds an outcome (a lesson delivered, or a failure observed) to\n * the concrete ACTION about to happen — the file being edited or the command\n * class being run. A delivery and a later failure on the SAME action share this\n * key, which is how effectiveness attributes a recurrence to the lesson meant to\n * prevent it. It is the action ONLY — the error class is recorded separately and\n * is never folded in here, because the `delivered` event is emitted before any\n * error exists, so an error-bearing key could never match its later `failure`.\n */\n\n/**\n * A shell command as its stable class — program plus optional subcommand — so\n * outcomes bind to the action, not its arguments (see command-class.ts):\n * \"git commit -m 'wip'\" → \"git commit\"; \"cd /r && pnpm tsc\" → \"pnpm tsc\".\n * '' when the command runs no program (`FOO=bar`).\n */\nexport function normalizeCommand(command: string): string {\n const cls = commandClass(command);\n if (cls === null) return '';\n return cls.subcommand === undefined ? cls.program : `${cls.program} ${cls.subcommand}`;\n}\n\n/** Deterministic action key. File takes precedence (the tighter signal). Never raw text. */\nexport function contextKey(\n input: { file?: string; command?: string },\n projectRoot: string,\n): string {\n if (input.file !== undefined && input.file.length > 0) {\n return `file:${normalizeRecallFile(input.file, projectRoot)}`;\n }\n if (input.command !== undefined && input.command.length > 0) {\n return `cmd:${normalizeCommand(input.command)}`;\n }\n return 'none';\n}\n","import type { LessonsGraph } from './graph-schema.js';\nimport { collectMatchedTriggersByKind, type LessonsQuery, type MatchedLesson } from './query.js';\nimport { estTokens, type RankedLesson } from './ranking.js';\nimport { appendRecallRecord, isTelemetryEnabled, sessionId } from './telemetry.js';\nimport { contextKey } from './context-key.js';\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: {\n readonly bypassed?: boolean;\n readonly session?: string;\n /** Candidates that came from rule wording, not a trigger (lexical retrieval). */\n readonly lexical?: number;\n } = {},\n): void {\n if (!isTelemetryEnabled(process.env, projectRoot)) 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 // Explicit caller session (hook stdin / --session) wins; env is the fallback.\n const session = options.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 contextKey: contextKey({ file: query.file, command: query.command }, projectRoot),\n matchedByKind: {\n file: countVia(byKind.file_glob),\n command: countVia(byKind.command_pattern),\n keyword: countVia(byKind.keyword),\n ...(options.lexical !== undefined ? { text: options.lexical } : {}),\n },\n lessonIds: lessons.map((l) => l.id),\n bypassed: options.bypassed === true,\n ...(session !== undefined ? { session } : {}),\n });\n}\n","import { getGlobMatcher } from './glob-safety.js';\nimport type { LessonsGraph, Trigger } from './graph-schema.js';\nimport { keywordMatches } from './keyword-match.js';\nimport { commandCouldMatch } from './query.js';\n\n/**\n * Does a recorded action (an outcome/recall `contextKey`) re-match one of a\n * lesson's OWN triggers? Uses recall's trigger semantics: file globs as in\n * queryLessons, command patterns and keyword triggers through\n * commandCouldMatch / keywordMatches. A `cmd:` key holds only the command\n * CLASS, so a pattern that needs the full argv (`git commit -m`) does not\n * re-match it — the check errs toward \"no match\", never a false one.\n */\n\ntype ActionQuery = { readonly file: string } | { readonly command: string };\n\n/** The recall query a stored action key stands for; null for `none` or unknown keys. */\nexport function queryFromContextKey(key: string): ActionQuery | null {\n if (key.startsWith('file:')) return { file: key.slice('file:'.length) };\n if (key.startsWith('cmd:') && key.length > 'cmd:'.length)\n return { command: key.slice('cmd:'.length) };\n return null;\n}\n\nexport type ActionMatcher = (lessonId: string, contextKey: string) => boolean;\n\n/**\n * A matcher over one graph. Globs use recall's safe matcher; an unsafe one never\n * matches. Each (lesson, action) answer is kept: effectiveness asks the same\n * pairs many times over one outcome log.\n */\nexport function createActionMatcher(graph: LessonsGraph): ActionMatcher {\n const seen = new Map<string, Map<string, boolean>>();\n return (lessonId, contextKey) => {\n let byKey = seen.get(lessonId);\n if (byKey === undefined) {\n byKey = new Map();\n seen.set(lessonId, byKey);\n }\n let hit = byKey.get(contextKey);\n if (hit === undefined) {\n hit = matchesOwnTrigger(graph, lessonId, contextKey);\n byKey.set(contextKey, hit);\n }\n return hit;\n };\n}\n\nfunction matchesOwnTrigger(graph: LessonsGraph, lessonId: string, contextKey: string): boolean {\n const query = queryFromContextKey(contextKey);\n const lesson = graph.lessons[lessonId];\n if (query === null || lesson === undefined) return false;\n const triggers = lesson.triggers\n .map((id) => graph.triggers[id])\n .filter((t): t is Trigger => t !== undefined);\n const patterns = (kind: Trigger['kind']): string[] =>\n triggers.filter((t) => t.kind === kind).map((t) => t.pattern);\n if ('command' in query) {\n return commandCouldMatch(patterns('command_pattern'), patterns('keyword'), query.command);\n }\n return (\n patterns('file_glob').some((p) => getGlobMatcher(p)?.test(query.file) ?? false) ||\n patterns('keyword').some((p) => keywordMatches(p, query))\n );\n}\n","import { createActionMatcher, type ActionMatcher } from './action-match.js';\nimport type { Lesson, LessonsGraph } from './graph-schema.js';\nimport type { OutcomeDelivered, OutcomeEvent } from './outcome-log.js';\n\n/**\n * Did a delivered lesson prevent the repeat? Derived from the outcome log.\n *\n * A delivery is a MISS only when a failure follows it in the SAME session,\n * within {@link MISS_WINDOW_MS}, on an action that re-matches one of THAT\n * lesson's own triggers. Sessionless events are never attributed. This feeds\n * three views that must agree: recall ranking ({@link effectivenessScores}),\n * `validate` (INEFFECTIVE_LESSON) and `stats` (held rate). Still a coarse\n * signal — no miss is not proof the lesson prevented anything.\n */\n\n/** Deliveries needed before a lesson is judged ineffective or down-ranked. */\nexport const INEFFECTIVE_MIN_DELIVERIES = 3;\n/** A failure later than this after a delivery is not attributed to it. */\nexport const MISS_WINDOW_MS = 30 * 60 * 1000;\n\ninterface LessonOutcome {\n readonly delivered: number;\n readonly missed: number;\n /** Distinct failing actions (context keys) behind `missed`, sorted. */\n readonly failingActions: readonly string[];\n}\n\ninterface TimedFailure {\n readonly index: number;\n readonly at: number;\n readonly contextKey: string;\n}\n\nfunction failuresBySession(events: readonly OutcomeEvent[]): Map<string, TimedFailure[]> {\n const out = new Map<string, TimedFailure[]>();\n events.forEach((ev, index) => {\n const at = Date.parse(ev.ts);\n if (ev.kind !== 'failure' || ev.session === undefined || !Number.isFinite(at)) return;\n const list = out.get(ev.session) ?? [];\n list.push({ index, at, contextKey: ev.contextKey });\n out.set(ev.session, list);\n });\n return out;\n}\n\nfunction impeachingFailure(\n ev: OutcomeDelivered,\n index: number,\n failures: ReadonlyMap<string, readonly TimedFailure[]>,\n matches: ActionMatcher,\n): TimedFailure | undefined {\n const at = Date.parse(ev.ts);\n if (ev.session === undefined || !Number.isFinite(at)) return undefined;\n return failures\n .get(ev.session)\n ?.find(\n (f) =>\n f.index > index &&\n f.at >= at &&\n f.at - at <= MISS_WINDOW_MS &&\n matches(ev.lessonId, f.contextKey),\n );\n}\n\n/** Per-lesson delivered/missed tallies. Pure and deterministic. */\nexport function effectiveness(\n events: readonly OutcomeEvent[],\n graph: LessonsGraph,\n): Map<string, LessonOutcome> {\n const failures = failuresBySession(events);\n const matches = createActionMatcher(graph);\n const acc = new Map<string, { delivered: number; missed: number; actions: Set<string> }>();\n events.forEach((ev, index) => {\n if (ev.kind !== 'delivered') return;\n const cur = acc.get(ev.lessonId) ?? { delivered: 0, missed: 0, actions: new Set<string>() };\n acc.set(ev.lessonId, cur);\n cur.delivered += 1;\n const hit = impeachingFailure(ev, index, failures, matches);\n if (hit === undefined) return;\n cur.missed += 1;\n cur.actions.add(hit.contextKey);\n });\n const out = new Map<string, LessonOutcome>();\n for (const [id, a] of acc) {\n out.set(id, {\n delivered: a.delivered,\n missed: a.missed,\n failingActions: [...a.actions].sort(),\n });\n }\n return out;\n}\n\n/** 1 = always helped, 0 = never helped. Undelivered lessons are neutral (1). */\nexport function effectivenessScore(o: Pick<LessonOutcome, 'delivered' | 'missed'>): number {\n return o.delivered === 0 ? 1 : 1 - o.missed / o.delivered;\n}\n\n/** Delivered enough to judge, missed every time, and still active. */\nexport function isIneffective(o: LessonOutcome, lesson: Lesson | undefined): boolean {\n return (\n o.delivered >= INEFFECTIVE_MIN_DELIVERIES &&\n o.missed === o.delivered &&\n lesson?.status === 'active'\n );\n}\n\n/**\n * Ranking scores in [0,1] for lessons delivered at least\n * {@link INEFFECTIVE_MIN_DELIVERIES} times; thinner samples are absent (neutral),\n * so ranking never acts on less evidence than `validate` needs to judge.\n */\nexport function effectivenessScores(\n events: readonly OutcomeEvent[],\n graph: LessonsGraph,\n): Map<string, number> {\n const out = new Map<string, number>();\n for (const [id, o] of effectiveness(events, graph)) {\n if (o.delivered >= INEFFECTIVE_MIN_DELIVERIES) out.set(id, effectivenessScore(o));\n }\n return out;\n}\n","import { join } from 'node:path';\nimport { effectivenessScores } from './effectiveness.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { appendJsonl, logExists, readJsonl } from './jsonl-log.js';\nimport { isOutcomeEvent } from './log-record-guards.js';\nimport { lessonsPaths } from './paths.js';\nimport { isOutcomeLogEnabled, sessionId } from './telemetry.js';\n\n/**\n * The outcome log: an append-only side-channel (NEVER the graph, which is\n * `.strict()` + frozen) of two event kinds — a lesson delivered for an action,\n * and a failure observed on an action. Repeat-failure detection and\n * effectiveness are DERIVED from it at read time.\n *\n * ON by default, under its own switch (`\"outcomeLog\": false` in the lessons\n * config turns it off) — see isOutcomeLogEnabled. It holds normalized action\n * keys and normalized error classes only, never raw commands or error text.\n */\n\nconst MAX_OUTCOME_LOG_RECORDS = 5000;\nconst OUTCOME_LOG_TRIM_TRIGGER_BYTES = 2_000_000;\n\n/** A lesson injected into agent context for a concrete action. */\nexport interface OutcomeDelivered {\n /** ISO-8601 timestamp supplied by the caller (engine never reads the wall clock). */\n readonly ts: string;\n readonly kind: 'delivered';\n readonly lessonId: string;\n /** Normalized action key — see context-key.ts. Never raw text. */\n readonly contextKey: string;\n readonly session?: string;\n /** 0-based relevance rank within its delivery batch (0 = top-ranked). */\n readonly rank?: number;\n}\n\n/** A failure observed at a decision point (the thing a lesson is meant to prevent). */\nexport interface OutcomeFailure {\n readonly ts: string;\n readonly kind: 'failure';\n readonly contextKey: string;\n /** Coarse class of the error (see error-class.ts) — a hint for STORE, not a key. */\n readonly errorClass?: string;\n readonly session?: string;\n}\n\nexport type OutcomeEvent = OutcomeDelivered | OutcomeFailure;\n\n/** Append-only outcome log, sibling of the graph — never the graph itself. */\nexport function outcomeLogPath(projectRoot: string): string {\n return join(lessonsPaths(projectRoot).base, 'outcome-log.jsonl');\n}\n\n/** Append one event — a no-op when the outcome log is switched off. */\nexport function appendOutcomeEvent(\n projectRoot: string,\n event: OutcomeEvent,\n env: NodeJS.ProcessEnv = process.env,\n): void {\n if (!isOutcomeLogEnabled(env, projectRoot)) return;\n appendJsonl(outcomeLogPath(projectRoot), event, {\n maxRecords: MAX_OUTCOME_LOG_RECORDS,\n trimTriggerBytes: OUTCOME_LOG_TRIM_TRIGGER_BYTES,\n });\n}\n\n/** Read every well-formed outcome event. Returns [] when absent or unreadable. */\nexport function readOutcomeLog(projectRoot: string): OutcomeEvent[] {\n return readJsonl(outcomeLogPath(projectRoot), isOutcomeEvent, {\n maxBytes: OUTCOME_LOG_TRIM_TRIGGER_BYTES,\n });\n}\n\n/** True when the outcome log file exists — distinguishes \"never recorded\" from \"empty\". */\nexport function outcomeLogExists(projectRoot: string): boolean {\n return logExists(outcomeLogPath(projectRoot));\n}\n\n/**\n * Record that these lessons were injected for `contextKey` (stamps ts + session +\n * per-batch rank; ids MUST arrive relevance-ranked). No-op when the log is off.\n * An explicit `session` (the harness's hook-stdin id) wins over the env fallback —\n * the env var is unset in hook deployments, which left every record session-less.\n */\nexport function recordDelivered(\n projectRoot: string,\n lessonIds: readonly string[],\n contextKey: string,\n env: NodeJS.ProcessEnv = process.env,\n session: string | undefined = sessionId(env),\n): void {\n if (!isOutcomeLogEnabled(env, projectRoot) || lessonIds.length === 0) return;\n const ts = new Date().toISOString();\n lessonIds.forEach((lessonId, rank) => {\n appendOutcomeEvent(\n projectRoot,\n {\n ts,\n kind: 'delivered',\n lessonId,\n contextKey,\n rank,\n ...(session !== undefined ? { session } : {}),\n },\n env,\n );\n });\n}\n\n/**\n * Record a failure observed for `contextKey` (stamps ts + session). No-op when\n * the log is off. Explicit `session` wins over the env fallback (see above).\n */\nexport function recordFailure(\n projectRoot: string,\n contextKey: string,\n errorClass?: string,\n env: NodeJS.ProcessEnv = process.env,\n session: string | undefined = sessionId(env),\n): void {\n appendOutcomeEvent(\n projectRoot,\n {\n ts: new Date().toISOString(),\n kind: 'failure',\n contextKey,\n ...(errorClass !== undefined ? { errorClass } : {}),\n ...(session !== undefined ? { session } : {}),\n },\n env,\n );\n}\n\n/** Failures older than this do not count as a recurrence. */\nexport const RECURRENCE_WINDOW_MS = 24 * 60 * 60 * 1000;\n\n/** The latest error class for an action, and how many times THAT error recurred in the window. */\nexport interface RecurringFailure {\n /** Undefined when the harness reported no error text for any failure. */\n readonly errorClass?: string;\n readonly sameClassCount: number;\n}\n\n/**\n * The most recent error class for this action and its recurrence count.\n *\n * The action key is deliberately coarse (`cat x` and `cat y` share `cmd:cat`),\n * so a plain failure count cannot support the claim that one problem recurred —\n * six unrelated errors under one class look identical to the same error six\n * times. Counting per class is what makes \"this failed before\" mean something.\n */\nexport function recurringFailure(\n projectRoot: string,\n contextKey: string,\n now: number = Date.now(),\n): RecurringFailure {\n const perClass = new Map<string, number>();\n let errorClass: string | undefined;\n for (const ev of readOutcomeLog(projectRoot)) {\n if (ev.kind !== 'failure' || ev.contextKey !== contextKey) continue;\n if (ev.errorClass === undefined) continue;\n // Old failures say nothing about a retry now; counting them all inflated the count.\n const at = Date.parse(ev.ts);\n if (!Number.isFinite(at) || now - at > RECURRENCE_WINDOW_MS) continue;\n errorClass = ev.errorClass;\n perClass.set(ev.errorClass, (perClass.get(ev.errorClass) ?? 0) + 1);\n }\n if (errorClass === undefined) return { sameClassCount: 0 };\n return { errorClass, sameClassCount: perClass.get(errorClass) ?? 0 };\n}\n\n/**\n * Per-lesson ranking scores from the written log (see effectivenessScores).\n * Empty — every lesson neutral — until the log holds both deliveries and\n * failures. `lessonIds` limits the work to the lessons the caller will rank.\n */\nexport function loadEffectiveness(\n projectRoot: string,\n graph: LessonsGraph,\n lessonIds?: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const all = readOutcomeLog(projectRoot);\n const events =\n lessonIds === undefined\n ? all\n : all.filter((e) => e.kind !== 'delivered' || lessonIds.has(e.lessonId));\n const kinds = new Set(events.map((e) => e.kind));\n if (!kinds.has('delivered') || !kinds.has('failure')) return new Map();\n return effectivenessScores(events, graph);\n}\n","import { sessionId as envSessionId } from './telemetry.js';\n\n/**\n * When a signal-less recall session begins and ends.\n *\n * A hook is TOLD what happened to the model's context (SessionStart\n * compact/clear/startup), so it can reset dedup exactly. The CLI and the MCP\n * server are told nothing — they are a command someone runs and a process\n * someone keeps alive — so for them \"which chat is this?\" has to be inferred.\n * This module owns that inference: the fallback correlator plus the two windows\n * that bound how wrong it can be. Split from seen-cache.ts (which owns the seen\n * set itself) for the 200-line limit; it imports no dedup state, so the\n * dependency runs one way only.\n */\n\n/**\n * Ceiling for a correlator with no context-reset signal (the `--session auto`\n * day bucket, and the MCP server). It bounds the worst case: a new chat opened\n * with no pause at all inherits the previous chat's suppressions only until this\n * window passes. Kept short deliberately — re-showing a rule costs a few hundred\n * tokens, hiding one from a fresh context costs the whole point of recall.\n */\nexport const AUTO_SESSION_TTL_MS = 60 * 60 * 1000;\n\n/**\n * A quiet gap this long means the previous chat is over, so the WHOLE session\n * resets rather than expiring entry by entry. A new chat usually starts after a\n * pause, so idleness is the best signal available; `lessons stats` groups\n * sessions by the same kind of gap.\n */\nexport const AUTO_SESSION_IDLE_MS = 30 * 60 * 1000;\n\n/**\n * Resolve `--session auto`: the exported `AGENTSMESH_SESSION_ID` when present,\n * else a day-bucket key. Prose-driven (non-hook) recall has no harness stdin to\n * carry a session id, so without this every ritual recall re-delivers the whole\n * matched set all day (field-measured at ~59% repeated rule-tokens). The day key\n * is deliberately coarse — {@link AUTO_SESSION_IDLE_MS} and\n * {@link AUTO_SESSION_TTL_MS} are what keep a new chat from inheriting an old\n * one's suppressions, and `--no-dedup` is the immediate escape.\n */\nexport function autoSessionId(env: NodeJS.ProcessEnv = process.env): string {\n return envSessionId(env) ?? dayBucketId();\n}\n\n/**\n * The env-independent half of {@link autoSessionId}. A reset runs in a DIFFERENT\n * process from the recall it is resetting (the hook is a subprocess; the CLI\n * runs in the agent's shell), and those environments need not match — one may\n * see `AGENTSMESH_SESSION_ID` while the other does not. So a reset clears this\n * key as well, rather than assuming both processes resolved the same one.\n */\nexport function dayBucketId(): string {\n return `auto-${new Date().toISOString().slice(0, 10)}`;\n}\n\n/** Clock jitter between the writing and reading process that is not suspicious. */\nconst FUTURE_TOLERANCE_MS = 60_000;\n\n/**\n * Age of a stamp. A stamp meaningfully in the FUTURE cannot be trusted — a clock\n * jump, or a store copied from a machine ahead of this one — and treating it as\n * fresh would pin both the entry and the whole session forever, which is exactly\n * the \"rule hidden indefinitely\" failure this module exists to prevent. Such a\n * stamp is reported as infinitely old instead, so it expires and its session\n * resets: the cost is one re-delivery, which is always the safe direction.\n */\nexport function stampAgeMs(stamp: number, now: number = Date.now()): number {\n if (stamp - now > FUTURE_TOLERANCE_MS) return Number.POSITIVE_INFINITY;\n return Math.max(0, now - stamp);\n}\n\n/**\n * True when this session's last ACTIVITY predates the idle gap. Activity is not\n * the same as delivery: a recall whose matches were all already suppressed\n * delivers nothing, and treating that as inactivity would re-deliver the whole\n * set every gap even while the agent works steadily. So the store records\n * `lastAt` on every recall and this falls back to the newest delivery stamp only\n * for stores written before that field existed. An unstamped (legacy) or empty\n * store is never \"idle\": there is nothing to reset, and the TTL path already\n * treats it as fully expired.\n */\nexport function isIdleSession(\n stamps: ReadonlyMap<string, number> | null,\n lastAt?: number,\n): boolean {\n if (stamps === null || stamps.size === 0) return false;\n let newest = lastAt ?? 0;\n for (const ms of stamps.values()) if (ms > newest) newest = ms;\n return stampAgeMs(newest) > AUTO_SESSION_IDLE_MS;\n}\n","import type { MatchedLesson } from './query.js';\nimport {\n readSeenStore,\n removeSeenStore,\n seenStorePath,\n updateSeenStore,\n type StoredSeen,\n} from './seen-store.js';\nimport { autoSessionId, dayBucketId, isIdleSession, stampAgeMs } from './session-window.js';\nimport { sessionId as envSessionId } from './telemetry.js';\n\n// The session-window policy (correlator + expiry windows) lives next door;\n// re-exported here so `seen-cache` stays the one import for session dedup.\nexport { AUTO_SESSION_IDLE_MS, AUTO_SESSION_TTL_MS, autoSessionId } from './session-window.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 — see seen-store.ts), so it never dirties `.agentsmesh/` and the\n * OS reclaims it. TTL sessions (the `--session auto` day bucket) stamp each\n * delivery and expire entries after {@link AUTO_SESSION_TTL_MS}, so a fresh\n * agent session later the same day is not starved by the morning's deliveries.\n */\n\nexport interface SessionDedup {\n readonly sessionId: string;\n readonly seen: ReadonlySet<string>;\n readonly path: string;\n /** Per-id delivery stamps from a v2 store; null for legacy array stores. */\n readonly stamps: ReadonlyMap<string, number> | null;\n /** Set for TTL sessions: an entry suppresses only within this window. */\n readonly ttlMs?: number;\n /** When an idle session dropped its old set on open; commits keep only newer writes. */\n readonly resetAt?: number;\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 * Project root. Namespaces the seen file by a hash of the resolved root, so two\n * projects sharing one fixed `AGENTSMESH_SESSION_ID` (e.g. a CI runner that\n * exports it once) keep SEPARATE dedup state — otherwise project B inherits\n * project A's \"seen\" set and suppresses coincidentally-colliding lesson ids.\n * Omitted → the legacy flat path (unchanged behavior).\n */\n readonly projectRoot?: string;\n /**\n * Expire suppressions after this window (TTL sessions — the auto day bucket).\n * A legacy array store has no stamps and is treated as fully expired under a\n * TTL: the safe direction is re-delivery, never over-suppression.\n */\n readonly ttlMs?: number;\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 = seenStorePath(id, options.projectRoot);\n const store = readSeenStore(path);\n // A signal-less session that has gone quiet belonged to a context that is\n // gone: drop the whole set, and drop the stamps too so the next commit cannot\n // resurrect it (see AUTO_SESSION_IDLE_MS).\n const stale = options.ttlMs !== undefined && isIdleSession(store.stamps, store.lastAt);\n const stamps = stale ? null : store.stamps;\n return {\n sessionId: id,\n seen: stale ? new Set<string>() : visibleSeen(store.ids, stamps, options.ttlMs),\n path,\n stamps,\n ...(options.ttlMs !== undefined ? { ttlMs: options.ttlMs } : {}),\n ...(stale ? { resetAt: Date.now() } : {}),\n };\n}\n\n/** Under a TTL only stamped-and-fresh entries suppress; untimed stores suppress fully. */\nfunction visibleSeen(\n ids: ReadonlySet<string>,\n stamps: ReadonlyMap<string, number> | null,\n ttlMs: number | undefined,\n): ReadonlySet<string> {\n if (ttlMs === undefined) return ids;\n if (stamps === null) return new Set();\n const now = Date.now();\n const fresh = new Set<string>();\n for (const [id, ms] of stamps) if (stampAgeMs(ms, now) <= ttlMs) fresh.add(id);\n return fresh;\n}\n\n/**\n * Discard the per-session seen set, so subsequent recalls re-inject as if fresh.\n * Called when the model's context was actually reset — a `SessionStart`\n * `compact`/`clear` — so dedup (which assumes a delivered lesson stays in context)\n * does not keep suppressing lessons the summarization dropped. Best-effort: a\n * failed remove just leaves the stale set, degrading to today's behavior.\n */\nexport function clearSeen(sessionId: string, projectRoot?: string): void {\n removeSeenStore(seenStorePath(sessionId, projectRoot));\n}\n\n/**\n * Apply a harness `SessionStart` to dedup state. `resume` is the ONLY source\n * that keeps the sets, because it is the only one where the prior context comes\n * back; `compact`, `clear`, `startup`, and any source this build does not model\n * (or a harness that omits the field) all mean the context those suppressions\n * were based on is gone. Both the harness session store AND the CLI/MCP\n * correlator stores are cleared: they are separate files, and clearing only the\n * first left an agent's own `--session auto` recalls suppressed after a\n * compaction. Re-showing a rule costs tokens; hiding one from a context that\n * never saw it defeats the recall gate, so this errs toward clearing.\n */\nexport function clearSeenForSessionStart(\n source: string | undefined,\n sessionId: string | undefined,\n projectRoot: string,\n): void {\n if (source === 'resume') return;\n if (sessionId !== undefined) clearSeen(sessionId, projectRoot);\n // The CLI/MCP correlators live in other stores, resolved in other processes\n // whose environments need not match this one — clear every key they could\n // have used rather than assuming they agreed with us.\n for (const id of new Set([autoSessionId(), dayBucketId()])) clearSeen(id, projectRoot);\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 (see seen-store).\n *\n * The written SHAPE follows the shape that was read, never the caller's mode:\n * one correlator can be shared by a TTL writer (CLI `--session auto`) and an\n * untimed one (hook/MCP), which happens whenever `AGENTSMESH_SESSION_ID` is\n * exported. An untimed commit that downgraded a stamped store back to the bare\n * array would discard every timestamp, and the next TTL read — which treats an\n * unstamped store as fully expired — would suppress nothing, silently zeroing\n * dedup for the rest of the session. So a stamped store stays stamped; only a\n * session that never saw one keeps writing the legacy array (an older binary\n * must still be able to read what this one writes).\n */\nexport function commitSeen(dedup: SessionDedup, returnedIds: readonly string[]): void {\n updateSeenStore(dedup.path, (latest) => {\n const store =\n dedup.resetAt !== undefined && (latest.lastAt ?? 0) <= dedup.resetAt ? EMPTY : latest;\n // A recall that delivered nothing still proves the session is ALIVE. Record\n // that (cheaply, and only for stamped sessions, which are the ones whose idle\n // gap can reset them) so steady work is not mistaken for an abandoned chat.\n if (returnedIds.length === 0) {\n return dedup.ttlMs !== undefined && store.stamps !== null ? { data: store.stamps } : null;\n }\n if (dedup.ttlMs !== undefined || store.stamps !== null) {\n const now = Date.now();\n const merged = new Map<string, number>();\n // Prune expired siblings only when this session actually has a TTL; an\n // untimed session preserves every stamp it read.\n for (const [id, ms] of store.stamps ?? []) {\n if (dedup.ttlMs === undefined || now - ms <= dedup.ttlMs) merged.set(id, ms);\n }\n for (const id of returnedIds) merged.set(id, now);\n return { data: merged };\n }\n const union = new Set(store.ids);\n for (const id of returnedIds) union.add(id);\n return union.size === store.ids.size ? null : { data: [...union] };\n });\n}\n\nconst EMPTY: StoredSeen = { ids: new Set(), stamps: null };\n","import { maybeAutoMigrateLessons } from './auto-migrate.js';\nimport { currentGraphStamp, refreshCommandFastpath } from './cmd-fastpath.js';\nimport { loadLessonsGraphResilient } from './graph-store.js';\nimport { normalizeRecallFile } from './normalize-query-file.js';\nimport { matchLessons } from './lexical-retrieval.js';\nimport type { LessonsQuery } from './query.js';\nimport { rankLessons, type RankedLesson } from './ranking.js';\nimport { loadRecallConfig } from './recall-config.js';\nimport { recordRecallTelemetry } from './recall-telemetry.js';\nimport { loadEffectiveness } from './outcome-log.js';\nimport { commitSeen, filterUnseen, openSessionDedup } from './seen-cache.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` (capture.ts) is the symmetric capture entry\n * point. Prefer these application APIs; reach for the read primitives only\n * 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 * Expire suppressions this long after delivery. Set by callers that have NO\n * context-reset signal (the MCP server never sees the client compact), so a\n * lesson dropped from a summarized context cannot stay hidden forever. The\n * hook path leaves this unset on purpose: it resets on SessionStart\n * compact/clear, which is the exact signal a wall-clock TTL only approximates.\n */\n readonly ttlMs?: number;\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 // Stamp BEFORE the read: refreshCommandFastpath only writes when the file\n // still carries this stamp, so a graph write landing inside the read window\n // can never be cached under stale patterns (see cmd-fastpath.ts).\n const preReadStamp = currentGraphStamp(projectRoot);\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 // Freshen the command fast-path cache while the graph is in hand (no-op when fresh).\n refreshCommandFastpath(projectRoot, graph, preReadStamp);\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 // Task text (prompt submit, task-start keyword recall) also reaches lessons by\n // their wording; a file/command query never does — see lexical-retrieval.ts.\n const { matches, lexicalCount } = matchLessons(graph, matchQuery);\n // Dedup BEFORE ranking so the caps fill with fresh lessons (see seen-cache).\n const dedup = openSessionDedup({\n explicit: options.sessionId,\n disabled: options.noDedup,\n projectRoot,\n ...(options.ttlMs !== undefined ? { ttlMs: options.ttlMs } : {}),\n });\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 // Down-rank proven fire-but-fail lessons (empty ⇒ neutral, so recall is\n // unchanged until the outcome log has real signal). Read from the side-channel\n // only when something survived matching+dedup — a no-match recall must not pay\n // the (up to 2MB) outcome-log read for a ranking of nothing.\n effectiveness:\n forRank.length === 0\n ? new Map()\n : loadEffectiveness(projectRoot, graph, new Set(forRank.map((m) => m.id))),\n });\n if (dedup !== null)\n commitSeen(\n dedup,\n lessons.map((l) => l.id),\n );\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, {\n bypassed: false,\n session: options.sessionId,\n lexical: lexicalCount,\n });\n return { lessons, totalMatches: matches.length, suppressed: matches.length - forRank.length };\n}\n","import { MAX_RECOMMENDED_TRIGGERS } from './capture-guardrails.js';\nimport type { LessonsGraph } from './graph-schema.js';\nimport { buildFanout } from './ranking-signals.js';\nimport { fileGlobLiveness } 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), normally from\n * `listProjectFiles` so it carries git evidence. When provided, prune also GCs\n * `file_glob` triggers git history proves dead; pending ones are never touched,\n * and a plain set (no evidence) detaches nothing. Omitted → no liveness pruning,\n * so 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 } = fileGlobLiveness(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 {\n removedTriggerIds,\n removedTopicIds,\n trimmedLessons,\n removedDeadGlobs,\n unreachableLessons,\n cap,\n };\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 { tryLoadLessonsGraph } from './graph-store.js';\nimport { mutateLessonsGraph } from './mutate.js';\nimport { applyPruneToGraph, isEmptyPrunePlan, planPrune } from './prune.js';\nimport { configFlag } from './telemetry.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. A glob\n * is dead only when git history renamed or deleted its path (see\n * `missingGlobState`): a glob for a file not created yet, ignored build output, a\n * non-git project or a capped walk is never detached. 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 return configFlag(projectRoot, 'autoPrune') === true;\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, with its git evidence) enables dead-glob\n * detachment; `undefined` (no walk, or the walk hit its cap) GCs orphans only.\n * 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 { join } from 'node:path';\nimport type { AddLessonResult } from './add.js';\nimport { appendJsonl, logExists, readJsonl } from './jsonl-log.js';\nimport { isCaptureRecord } from './log-record-guards.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 opt-in switch (`\"telemetry\": true`\n * in the lessons config, or `AGENTSMESH_LESSONS_TELEMETRY=1`), recording\n * presence/counts ONLY (never the rule text) so it leaks no source content.\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, projectRoot)) 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 every well-formed capture record. Returns [] when absent or unreadable. */\nexport function readCaptureLog(projectRoot: string): CaptureTelemetryRecord[] {\n return readJsonl(captureLogPath(projectRoot), isCaptureRecord, {\n maxBytes: CAPTURE_LOG_TRIM_TRIGGER_BYTES,\n });\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, projectRoot)) 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 {\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 { listProjectFiles } from './project-files.js';\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 * The symmetric counterpart of `recallLessons` (recall.ts), split out for the\n * 200-line limit.\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 { union } from './add-helpers.js';\nimport 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(`Cannot merge lesson \"${loserId}\" into itself.`);\n }\n const loser = graph.lessons[loserId];\n if (loser === undefined) throw new Error(`Unknown lesson \"${loserId}\".`);\n const keeper = graph.lessons[keeperId];\n if (keeper === undefined) throw new Error(`Unknown lesson \"${keeperId}\".`);\n\n if (keeper.status !== 'active') {\n throw new Error(`Keeper \"${keeperId}\" is not active (status: ${keeper.status}).`);\n }\n if (loser.status !== 'active') {\n throw new Error(`Loser \"${loserId}\" is already ${loser.status}; nothing to merge.`);\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\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 * Only the \"See L1.\" sentence form owns its period; a period after \"(L5)\" or\n * \"[L5]\" belongs to the surrounding sentence and is kept.\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 { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst LOCAL_FIRST = 'npx --no --offline agentsmesh';\nconst BARE = 'agentsmesh';\nconst DEPENDENCY_FIELDS = ['dependencies', 'devDependencies', 'optionalDependencies'] as const;\n\n/** A parsed package.json; the JSON may not be an object at all. */\ntype Manifest = Record<string, Record<string, unknown> | undefined> | null;\n\n/**\n * The command a generated hook or git merge driver uses to launch the CLI.\n *\n * `npx --no --offline` prefers the project's own copy, falls back to a global\n * install and never downloads. That fixes a teammate who has agentsmesh only\n * as a project dependency, and a stale global install beating the pinned\n * version. It also roughly doubles the per-call cost for a global-only user,\n * and the recall hook runs before every edit and command, so it is used only\n * when the project depends on agentsmesh, which is when it pays off.\n */\nexport function agentsmeshInvocation(projectRoot: string): string {\n return dependsOnAgentsmesh(projectRoot) ? LOCAL_FIRST : BARE;\n}\n\nfunction dependsOnAgentsmesh(projectRoot: string): boolean {\n try {\n const manifest = JSON.parse(\n readFileSync(join(projectRoot, 'package.json'), 'utf8'),\n ) as Manifest;\n return DEPENDENCY_FIELDS.some((field) => manifest?.[field]?.agentsmesh !== undefined);\n } catch {\n return false;\n }\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Document, parseDocument, YAMLMap, YAMLSeq } from 'yaml';\nimport { agentsmeshInvocation } from './cli-invocation.js';\n\n/**\n * Auto-wire hook-mode recall: inject `agentsmesh lessons hook` into canonical\n * `.agentsmesh/hooks.yaml`, so `generate` projects it to every hook-capable target\n * and recall becomes deterministic (no extra model turn, no compliance dependence):\n *\n * - `PreToolUse` — recall injects BEFORE every mutating tool call. It fires on each\n * call, not only the first touch, so it is the whole tool-call story.\n * - `UserPromptSubmit` — the ONLY event that carries the task text (no `tool_input`),\n * so it is the sole moment a keyword/conceptual (\"general\") lesson can recall\n * against task INTENT rather than a file path / command token. Uses matcher `*`\n * (prompt events have no tool to match).\n *\n * `PostToolUse` is deliberately NOT wired, and a previously scaffolded entry there\n * is removed. Alongside PreToolUse it re-ran recall for the same action after the\n * fact: a second process and a second context block per tool call, carrying\n * advice that could no longer be applied. Field data showed 63% of recalls\n * arriving within 3s of a same-shaped one. Cursor, Copilot and Gemini CLI can\n * inject on PostToolUse but not PreToolUse, so they get no tool-call recall from\n * hooks; their agents recall through the always-on paragraph instead.\n *\n * Generate keeps a recall entry only on the events where a target's hook output\n * reaches the model (`TargetDescriptor.hookContextEvents`), so wiring these\n * everywhere is safe; targets without such an event keep relying on the\n * always-on lessons paragraph in their root instruction — the universal fallback.\n *\n * The command comes from `agentsmeshInvocation`: `npx --no --offline` when the\n * project depends on agentsmesh (a teammate without a global install still\n * gets recall, and the pinned version wins), else the faster bare command.\n *\n * Each event carries exactly ONE managed entry (the recall hook, bare or\n * npx-launched, with no extra args). A re-run rewrites its command and matcher\n * in place when they drift — e.g. after agentsmesh becomes a devDependency —\n * and never touches user entries. Edited via the YAML Document API so the\n * file's `# yaml-language-server` schema directive and comments survive (a\n * parse()→stringify() round-trip 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\nconst RECALL_SUBCOMMAND = 'lessons hook';\n/** The recall hook as a bare command; every launcher form contains it. */\nexport const RECALL_HOOK_COMMAND = `agentsmesh ${RECALL_SUBCOMMAND}`;\n/**\n * Mutating tools the PreToolUse recall guards. Claude Code compares a `|` list\n * by exact tool name, so notebook edits and PowerShell need their own names.\n */\nconst RECALL_HOOK_TOOL_MATCHER = 'Edit|Write|NotebookEdit|Bash|PowerShell';\n/** A scaffold-written entry: the recall hook, bare or npx-launched, no extra args. */\nconst MANAGED_COMMAND = new RegExp(`^(?:npx(?: --?[\\\\w-]+)* )?${RECALL_HOOK_COMMAND}$`);\n\n/** The recall hook command for this project (see `agentsmeshInvocation`). */\nexport function recallHookCommand(projectRoot: string): string {\n return `${agentsmeshInvocation(projectRoot)} ${RECALL_SUBCOMMAND}`;\n}\n\n/** True for any command that runs the recall hook, however it is launched. */\nexport function isRecallHookCommand(command: unknown): boolean {\n return typeof command === 'string' && command.includes(RECALL_HOOK_COMMAND);\n}\n\n/** True for a recall hook command the scaffold wrote: bare or npx-launched, no extra args. */\nexport function isManagedRecallCommand(command: unknown): command is string {\n return typeof command === 'string' && MANAGED_COMMAND.test(command.trim());\n}\n\nfunction isManaged(item: unknown): item is YAMLMap {\n return item instanceof YAMLMap && isManagedRecallCommand(item.get('command'));\n}\n\n/**\n * Events the recall hook wires, each with the matcher that event needs. Tool-call\n * events match the mutating tools; `UserPromptSubmit` fires on every prompt (`*`).\n */\nconst RECALL_EVENTS: ReadonlyArray<{ readonly event: string; readonly matcher: string }> = [\n { event: 'PreToolUse', matcher: RECALL_HOOK_TOOL_MATCHER },\n { event: 'UserPromptSubmit', matcher: '*' },\n // Capture-on-failure nudge (see capture-nudge.ts). BEST-EFFORT: targets with\n // no failure event drop it without warning (BEST_EFFORT_HOOK_EVENTS).\n // PostToolUse is success-only, so failures need this.\n { event: 'PostToolUseFailure', matcher: '*' },\n // Reset recall dedup after a context compaction/clear (see hook.ts SessionStart).\n // BEST-EFFORT: targets that can't represent SessionStart just keep dedup as-is.\n { event: 'SessionStart', matcher: '*' },\n];\n\n/** Events an older scaffold wired that recall must no longer ride (see above). */\nconst RETIRED_EVENTS: readonly string[] = ['PostToolUse'];\n\n/**\n * Remove the managed recall entry from one event, leaving the user's own hooks\n * there untouched; drop the key when nothing remains. Returns true when changed.\n */\nfunction removeEvent(doc: Document, event: string): boolean {\n const existing = doc.get(event);\n if (!(existing instanceof YAMLSeq)) return false;\n const kept = existing.items.filter((item) => !isManaged(item));\n if (kept.length === existing.items.length) return false;\n if (kept.length === 0) doc.delete(event);\n else existing.items = kept;\n return true;\n}\n\n/**\n * Leave exactly one managed recall entry on `event`, carrying `matcher` and\n * `command`: add it when missing, rewrite a drifted one in place (other keys\n * such as `timeout` stay), drop duplicates. Returns true when anything changed.\n */\nfunction upsertEvent(doc: Document, event: string, matcher: string, command: string): boolean {\n const existing = doc.get(event);\n const seq = existing instanceof YAMLSeq ? existing : new YAMLSeq();\n const [first, ...extra] = seq.items.filter(isManaged);\n if (first === undefined) {\n seq.add(doc.createNode({ matcher, type: 'command', command }));\n doc.set(event, seq);\n return true;\n }\n let changed = extra.length > 0;\n if (changed) seq.items = seq.items.filter((item) => !extra.includes(item as YAMLMap));\n const desired = { matcher, type: 'command', command } as const;\n for (const [key, value] of Object.entries(desired)) {\n if (first.get(key) === value) continue;\n first.set(key, value);\n changed = true;\n }\n return changed;\n}\n\n/**\n * Returns true when any managed entry was added, rewritten or removed; false\n * when everything is already current or there is no hooks.yaml.\n */\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 command = recallHookCommand(projectRoot);\n let changed = false;\n for (const { event, matcher } of RECALL_EVENTS) {\n if (upsertEvent(doc, event, matcher, command)) changed = true;\n }\n for (const event of RETIRED_EVENTS) {\n if (removeEvent(doc, event)) changed = true;\n }\n if (changed) writeFileSync(path, String(doc), 'utf8');\n return changed;\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\n/** First word of a shell command, without surrounding quotes. */\nexport function commandProgram(command: string): string {\n const m = /^\\s*(?:\"([^\"]*)\"|'([^']*)'|(\\S+))/.exec(command);\n return m?.[1] ?? m?.[2] ?? m?.[3] ?? '';\n}\n\n/**\n * A bin folder that is on PATH only while npx (its `_npx` cache) or a package\n * script (`node_modules/.bin`) runs. Git runs a merge driver later, without it.\n */\nfunction isTransientBinDir(dir: string): boolean {\n const parts = dir.split(/[\\\\/]+/).filter((p) => p !== '');\n const [parent, last] = parts.slice(-2);\n return parts.includes('_npx') || (parent === 'node_modules' && last === '.bin');\n}\n\n/**\n * True when the program a command starts with can be found: an existing path,\n * or a name on PATH (trying PATHEXT on Windows), not counting transient bin\n * folders. A merge driver git cannot start is worse than none: git then keeps\n * our side as-is, with no conflict markers.\n */\nexport function commandLauncherExists(\n command: string,\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n): boolean {\n const program = commandProgram(command);\n if (program === '') return false;\n if (program.includes('/') || program.includes('\\\\')) return existsSync(program);\n const win = platform === 'win32';\n const exts = win ? ['', ...(env.PATHEXT ?? '.EXE;.CMD;.BAT;.COM').split(';')] : [''];\n const dirs = (env.PATH ?? env.Path ?? '')\n .split(win ? ';' : ':')\n .filter((d) => d !== '' && !isTransientBinDir(d));\n return dirs.some((dir) => exts.some((ext) => existsSync(join(dir, program + ext))));\n}\n\n/** True when `node_modules/.bin/<name>` (or `<name>.cmd`) exists in `fromDir` or an ancestor. */\nexport function localBinExists(fromDir: string, name: string): boolean {\n for (let dir = resolve(fromDir); ; dir = dirname(dir)) {\n const bin = join(dir, 'node_modules', '.bin');\n if (existsSync(join(bin, name)) || existsSync(join(bin, `${name}.cmd`))) return true;\n if (dirname(dir) === dir) return false;\n }\n}\n","/**\n * Setup for the lessons.json git merge driver (see\n * lessons-merge-driver-handler.ts).\n *\n * A merge driver has two halves: a COMMITTABLE `.gitattributes` line that binds\n * lessons.json to the driver — one dev commits it, the whole team inherits it —\n * and a PER-CLONE `git config` pair. Git never runs config from a clone (that\n * would be a remote-code-execution vector), so without the second half every\n * other clone falls back to a line merge and conflicts. `init --lessons` writes\n * the first half; {@link ensureLessonsMergeDriver} writes the second when a user\n * runs agentsmesh in their own clone.\n */\nimport { agentsmeshInvocation } from './cli-invocation.js';\nimport { runGit, type GitRunner } from './git-exec.js';\nimport { commandLauncherExists, commandProgram, localBinExists } from './launcher.js';\nimport { LESSONS_GRAPH_PATH } from './graph-store.js';\n\nconst LESSONS_MERGE_DRIVER = 'agentsmesh-lessons';\n\n/** Committable `.gitattributes` entry binding the graph to the union merge driver. */\nexport const LESSONS_GITATTRIBUTES_ENTRY = `${LESSONS_GRAPH_PATH} merge=${LESSONS_MERGE_DRIVER}`;\n\nconst DRIVER_KEY = `merge.${LESSONS_MERGE_DRIVER}.driver`;\nconst NAME_KEY = `merge.${LESSONS_MERGE_DRIVER}.name`;\nconst DRIVER_NAME = 'agentsmesh lessons union';\n\n/** The driver command git runs. Forward slashes only: git runs it through `sh`. */\nfunction lessonsMergeDriverCommand(invocation: string): string {\n return `${invocation.replaceAll('\\\\', '/')} lessons merge-driver %O %A %B`;\n}\n\nconst NPX_INVOCATION = 'npx --no --offline agentsmesh';\nconst NPX_COMMAND = lessonsMergeDriverCommand(NPX_INVOCATION);\nconst BARE_COMMAND = lessonsMergeDriverCommand('agentsmesh');\n\n/** Values agentsmesh itself configured or suggested; safe to replace. */\nconst OWN_COMMANDS = new Set([BARE_COMMAND, NPX_COMMAND]);\n\n/** Without npx (standalone pnpm or bun), an agentsmesh on PATH still runs the driver. */\nfunction launchable(command: string, env: NodeJS.ProcessEnv): string {\n const npxMissing = command === NPX_COMMAND && !commandLauncherExists(NPX_COMMAND, env);\n return npxMissing && commandLauncherExists(BARE_COMMAND, env) ? BARE_COMMAND : command;\n}\n\nexport type MergeDriverSetup =\n | {\n readonly status: 'configured' | 'updated' | 'unchanged' | 'skipped';\n readonly command: string;\n }\n | { readonly status: 'custom'; readonly command: string; readonly existing: string }\n | { readonly status: 'failed'; readonly command: string; readonly reason: string };\n\ninterface MergeDriverSetupOptions {\n /** How the driver launches the CLI; defaults to {@link agentsmeshInvocation}. */\n readonly invocation?: string;\n readonly git?: GitRunner;\n /** Environment whose PATH must hold the launcher; defaults to process.env. */\n readonly env?: NodeJS.ProcessEnv;\n}\n\nfunction configValue(git: GitRunner, root: string, key: string): string | null {\n const r = git(root, ['config', '--get', key]);\n return r.status === 0 ? r.stdout.trim() : null;\n}\n\n/**\n * Why git could not start `command` at merge time, or null when it can. Git\n * runs the driver from the repository root, so the npx form needs agentsmesh\n * installed there (or an ancestor) or globally.\n */\nfunction launchProblem(\n git: GitRunner,\n projectRoot: string,\n command: string,\n env: NodeJS.ProcessEnv,\n): string | null {\n if (!commandLauncherExists(command, env)) {\n return (\n `\\`${commandProgram(command)}\\` is not installed on PATH (npx and package-script bin ` +\n 'folders do not count), so git could not start the driver; install agentsmesh globally ' +\n 'or as a project devDependency'\n );\n }\n if (command !== NPX_COMMAND) return null;\n const top = git(projectRoot, ['rev-parse', '--show-toplevel']);\n const repoRoot = top.status === 0 ? top.stdout.trim() : projectRoot;\n if (localBinExists(repoRoot, 'agentsmesh') || commandLauncherExists('agentsmesh', env)) {\n return null;\n }\n return (\n `git runs the driver from the repository root (${repoRoot.replaceAll('\\\\', '/')}), where ` +\n `\\`${NPX_INVOCATION}\\` cannot find agentsmesh; add agentsmesh to the devDependencies of ` +\n 'the root package.json and install, or install agentsmesh globally'\n );\n}\n\n/**\n * In a git work tree whose attributes bind lessons.json to the driver, set the\n * per-clone driver config when it is missing (or is an older agentsmesh value).\n * Never throws; a user's own driver value is kept and reported.\n */\nexport function ensureLessonsMergeDriver(\n projectRoot: string,\n options: MergeDriverSetupOptions = {},\n): MergeDriverSetup {\n const git = options.git ?? runGit;\n const env = options.env ?? process.env;\n const command = launchable(\n lessonsMergeDriverCommand(options.invocation ?? agentsmeshInvocation(projectRoot)),\n env,\n );\n // Exits non-zero outside a work tree, so this is also the \"is this git?\" check.\n const attr = git(projectRoot, ['check-attr', 'merge', '--', LESSONS_GRAPH_PATH]);\n if (attr.status !== 0 || !attr.stdout.trim().endsWith(`: merge: ${LESSONS_MERGE_DRIVER}`)) {\n return { status: 'skipped', command };\n }\n const existing = configValue(git, projectRoot, DRIVER_KEY);\n if (existing !== null && existing !== command && !OWN_COMMANDS.has(existing)) {\n return { status: 'custom', command, existing };\n }\n // A driver git cannot start leaves our side as-is with no markers: worse than none.\n const reason = existing === command ? null : launchProblem(git, projectRoot, command, env);\n if (reason !== null) return { status: 'failed', command, reason };\n const writes: Array<[string, string]> = [];\n if (existing !== command) writes.push([DRIVER_KEY, command]);\n if (configValue(git, projectRoot, NAME_KEY) === null) writes.push([NAME_KEY, DRIVER_NAME]);\n for (const [key, value] of writes) {\n const r = git(projectRoot, ['config', '--local', key, value]);\n if (r.status !== 0) {\n const detail = r.stderr.trim() || `exit ${r.status}`;\n const reason = `git config failed (${detail}); run: git config ${DRIVER_KEY} \"${command}\"`;\n return { status: 'failed', command, reason };\n }\n }\n if (existing === command) return { status: 'unchanged', command };\n return { status: existing === null ? 'configured' : 'updated', command };\n}\n\n/** One line for a renderer, or null when there is nothing worth saying. */\nexport function mergeDriverSetupLine(setup: MergeDriverSetup): string | null {\n const set = `git config ${DRIVER_KEY} \"${setup.command}\"`;\n switch (setup.status) {\n case 'configured':\n return `Enabled the lessons.json merge driver for this clone (${set}).`;\n case 'updated':\n return `Updated the lessons.json merge driver for this clone (${set}).`;\n case 'custom':\n return `Kept your own lessons.json merge driver (${DRIVER_KEY} = \"${setup.existing}\"); the agentsmesh one is \"${setup.command}\".`;\n case 'failed':\n return `Could not enable the lessons.json merge driver: ${setup.reason}.`;\n default:\n return null;\n }\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport {\n isManagedRecallCommand,\n RECALL_HOOK_COMMAND,\n recallHookCommand,\n} from './recall-hook-scaffold.js';\n\nexport const RECALL_HOOK_TEAM_HINT =\n 'Lessons recall hooks call a global agentsmesh: teammates without a global install will ' +\n \"not get lesson recall; add agentsmesh as a devDependency and re-run 'agentsmesh init --lessons'.\";\n\n/**\n * One-line hint for `init` and `generate`, or null. When the recall hook in\n * hooks.yaml runs another launcher than this project now uses (agentsmesh was\n * added to or removed from the devDependencies; `generate` already switched the\n * merge driver), it asks to re-run init. Otherwise it warns when the hook calls\n * a global agentsmesh in a Node project, which fails silently for teammates\n * without one. Projects without a package.json get no dependency hint.\n */\nexport function recallHookTeamHint(projectRoot: string): string | null {\n const wired = wiredRecallCommands(projectRoot);\n if (wired.length === 0) return null;\n const expected = recallHookCommand(projectRoot);\n const stale = wired.find((command) => command !== expected);\n if (stale !== undefined) {\n return (\n `Lessons recall hooks run \\`${stale}\\`, but this project now calls \\`${expected}\\`; ` +\n \"re-run 'agentsmesh init --lessons' to update them.\"\n );\n }\n if (!existsSync(join(projectRoot, 'package.json'))) return null;\n return expected === RECALL_HOOK_COMMAND ? RECALL_HOOK_TEAM_HINT : null;\n}\n\n/** The scaffold-written recall hook commands in hooks.yaml. */\nfunction wiredRecallCommands(projectRoot: string): string[] {\n try {\n const hooks: unknown = parseYaml(\n readFileSync(join(projectRoot, '.agentsmesh', 'hooks.yaml'), 'utf8'),\n );\n return Object.values(hooks ?? {})\n .filter(Array.isArray)\n .flat()\n .map((entry: unknown) => (entry as { command?: unknown } | null)?.command)\n .filter(isManagedRecallCommand)\n .map((command) => command.trim());\n } catch {\n return [];\n }\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 { readFile, open, access, mkdir, rm, lstat, type FileHandle } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { dirname } from 'node:path';\nimport { constants, readFileSync } from 'node:fs';\nimport { FileSystemError } from '../../core/errors.js';\nimport {\n UTF8_BOM,\n executableModeFor,\n isBinaryPayloadPath,\n normalizeLineEndings,\n payloadEncodingFor,\n shouldNormalizeLineEndings,\n} from './fs-text-encoding.js';\nimport { renameWithRetry } from './rename-retry.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 // Binary payloads (skill images, fonts, archives) are read as latin1 so\n // every byte survives; a UTF-8 decode would replace invalid bytes with\n // U+FFFD and corrupt the file before generation ever runs.\n const data = await readFile(path, payloadEncodingFor(path));\n if (isBinaryPayloadPath(path)) return data;\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 * Uses an exclusively created temporary file; rename replaces a destination symlink.\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 } 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-${randomUUID()}`;\n const payload = shouldNormalizeLineEndings(path) ? normalizeLineEndings(content) : content;\n const mode = options?.mode ?? executableModeFor(path);\n let handle: FileHandle | undefined;\n let ownsTemporaryFile = false;\n try {\n handle = await open(tmpPath, 'wx', mode);\n ownsTemporaryFile = true;\n await handle.writeFile(payload, payloadEncodingFor(path));\n if (mode !== undefined) await handle.chmod(mode);\n await handle.close();\n handle = undefined;\n // Retrying rename, not a plain one: on Windows, replacing a destination\n // fails with EPERM while another process is mid-replace of the same path.\n // Unique temp names (the fix for torn content) removed the accidental\n // serialization writers used to get from sharing one `<path>.tmp`, so\n // concurrent writers now genuinely race here. POSIX is a single rename.\n await renameWithRetry(tmpPath, path);\n } catch (err) {\n await handle?.close().catch(() => {});\n if (ownsTemporaryFile) 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/** Read a UTF-8 file synchronously; '' when it cannot be read. */\nexport function readTextOrEmpty(path: string): string {\n try {\n return readFileSync(path, 'utf8');\n } catch {\n return '';\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 `.gitattributes` unless already present. Returns\n * true when the file was modified, false when every entry was already there.\n * Idempotent: safe to call on each re-run. Unlike `.gitignore`, attribute lines\n * have no ancestor coverage, so matching is exact-line only (after trim); comment\n * and blank lines are ignored, and existing content plus its trailing newline are\n * preserved.\n */\nexport async function ensureGitattributesEntries(\n projectRoot: string,\n entries: readonly string[],\n): Promise<boolean> {\n const path = join(projectRoot, '.gitattributes');\n const current = (await readFileSafe(path)) ?? '';\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) => !existing.has(e.trim()));\n if (toAdd.length === 0) return false;\n const suffix = current.endsWith('\\n') || current === '' ? '' : '\\n';\n await writeFileAtomic(path, current + suffix + toAdd.join('\\n') + '\\n');\n return 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","// 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 split = splitFrontmatter(content);\n if (split === null) return { frontmatter: {}, body: content.trim() };\n const yamlStr = split.yaml.trim();\n const frontmatter = yamlStr === '' ? {} : ((yamlParse(yamlStr) as Record<string, unknown>) ?? {});\n return { frontmatter, body: split.body };\n}\n\nconst OPENER = /^---[ \\t]*\\r?\\n/;\nconst CLOSER = /^---[ \\t]*\\r?$/m;\n\nexport interface FrontmatterSplit {\n /** Raw YAML between the delimiters (may be empty). */\n yaml: string;\n /** Trimmed content after the closing delimiter line. */\n body: string;\n /** Byte-exact `---…---` block, for callers that re-emit it verbatim. */\n prefix: string;\n}\n\n/**\n * Locate a leading frontmatter block. Both delimiters must be lines of their\n * own: a `---` inside a value (`description: a --- b`) is content, not a close.\n * Returns null when there is no complete block.\n */\nexport function splitFrontmatter(content: string): FrontmatterSplit | null {\n const opener = OPENER.exec(content);\n if (opener === null) return null;\n const yamlStart = opener[0].length;\n const closer = CLOSER.exec(content.slice(yamlStart));\n if (closer === null) return null;\n const closeStart = yamlStart + closer.index;\n const closeEnd = closeStart + closer[0].length;\n return {\n yaml: content.slice(yamlStart, closeStart),\n body: content.slice(closeEnd).trim(),\n prefix: content.slice(0, closeEnd),\n };\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 return splitFrontmatter(content)?.body ?? content.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 { splitFrontmatter } from '../../utils/text/markdown.js';\nimport { basename, join } from 'node:path';\nimport type { CanonicalRule, CanonicalFiles } 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 const split = splitFrontmatter(content);\n return split === null\n ? { prefix: '', body: content.trim() }\n : { prefix: split.prefix, body: split.body };\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\n/**\n * The embedded-root-rule generator: the root rule's body plus a managed block\n * holding every non-root rule that targets `target`, written to `rootFile`.\n * Targets with no native per-rule file all project rules this way.\n */\nexport function embeddedRootRule(\n canonical: CanonicalFiles,\n target: string,\n rootFile: string,\n): { path: string; content: string }[] {\n const rootBody = canonical.rules.find((rule) => rule.root)?.body.trim() ?? '';\n const nonRootRules = canonical.rules.filter(\n (rule) => !rule.root && (rule.targets.length === 0 || rule.targets.includes(target)),\n );\n const content = appendEmbeddedRulesBlock(rootBody, nonRootRules);\n return content ? [{ path: rootFile, content }] : [];\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\nconst LEGACY_RAW_FORMS = [\n // Pre-`--session auto` wording (2026-07): strip sentinel-less copies so a\n // project scaffolded before the dedup correlator dedups on the next scaffold.\n `## Lessons (BLOCKING)\n\nGraph \\`.agentsmesh/lessons/lessons.json\\` is canonical; never hand-edit it. Manual: \\`lessons\\` skill.\n\n**Recall:** before every file edit or state-changing command, MUST run \\`agentsmesh lessons query --file <path> --cmd <command>\\` and obey matches; at task start, ALSO run \\`agentsmesh lessons query --keyword \"<task terms>\" --always\\` for conceptual + universal rules no path/command names. Pure-read commands and recall itself are exempt.\n\n**Capture:** after any failure, user correction, regression, wrong assumption, useful surprise, repeated friction, or non-obvious fix, MUST self-critique and run \\`agentsmesh lessons add \"<imperative rule>\" --topic <id> --trigger-file <glob> --evidence <sha|lesson-id>\\`.\n\n**Before final:** report \\`Lesson: captured <id>\\` or \\`Lesson: none\\`. No recall/capture gate = task incomplete. No shell: use \\`lessons_query\\` / \\`lessons_add\\`.`,\n `## 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];\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 a procedural rule, so a hand-pasted\n * or merge-mangled raw paragraph de-duplicates on the next scaffold instead of\n * leaving a second copy beside the managed block.\n */\nfunction stripRawProceduralRule(content: string): string {\n return [LESSONS_PROCEDURAL_RULE, ...LEGACY_RAW_FORMS].reduce(\n (next, rule) => next.replace(`\\n\\n${rule}`, '').replace(rule, ''),\n content,\n );\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 rest: the Iron\n * Law gates, the rationalization table, and the capture how-to. It is kept short\n * on purpose — full command/flag reference lives in `agentsmesh lessons --help`,\n * not here (skill best practice: move details to tool help).\n *\n * Borrowed from the superpowers pattern (minimal always-on bootstrap + a\n * progressive-disclosure skill manual, plus its rigid \"Iron Law\" gate framing),\n * but realized with agentsmesh's NATIVE primitives: the trigger rides canonical\n * rules (native on every target) and the manual rides a canonical skill (native\n * on every skill-supporting target), rather than a SessionStart hook (not a\n * canonical event; unsupported on most targets). A target without skills still\n * gets the trigger — graceful fallback.\n */\nexport const LESSONS_SKILL_NAME = 'lessons';\n\n// Skill best practice (superpowers writing-skills / Anthropic): the description\n// is the DISCOVERY signal — third-person, \"Use when…\", TRIGGERS ONLY, short, and\n// NEVER a workflow summary (a summarized workflow makes the agent follow the\n// description instead of reading the body). The two triggers below ARE the recall\n// moment (about to mutate) and the capture moment (after a failure), so the skill\n// self-surfaces as the fallback for the always-on rule. Subcommands live in the body.\nexport const LESSONS_SKILL_DESCRIPTION =\n 'Use when about to edit a file or run a state-changing command, or after any ' +\n 'failure, correction, or surprising result.';\n\nexport const LESSONS_SKILL_BODY = `# Lessons — operating manual (Iron Law)\n\n## The Iron Law\n\n**NO MUTATION WITHOUT RECALL. NO COMPLETION WITHOUT A CAPTURE DECISION.**\n\nViolating the letter is violating the spirit. Edited a file or ran a state-changing\ncommand without recall? Process violation. Did the turn hit a failure / correction /\nregression / wrong assumption / surprise and you have not captured (nor stated\n\\`Lesson: none\\`)? The task is INCOMPLETE — and the user will check. The graph\n\\`.agentsmesh/lessons/lessons.json\\` is canonical — never hand-edit.\n\n## Recall — before each edit/command, and at task start\n\n\\`agentsmesh lessons query --file <path> --cmd <command> --session auto\\`, then apply every\nrule. Pure-read commands (read-only) and the query itself are exempt. **keyword-only recall\nfor a specific edit is the anti-pattern** — anchor those to \\`--file\\`/\\`--cmd\\`. But at the\nSTART of a task (or when planning), run \\`agentsmesh lessons query --keyword \"<the task's\nkey terms>\" --always --session auto\\`: that surfaces the conceptual rules no file/command\nnames PLUS the universal always-on lessons — the manual equivalent of the automatic prompt\nrecall on hook-capable tools. **Always pass \\`--session auto\\`**: it suppresses rules already\nshown this session so repeat recalls stay quiet (without it every recall re-delivers the\nwhole matched set); \\`--no-dedup\\` re-shows everything after a context reset. Author a\n\\`keyword\\` trigger beside a \\`file_glob\\` on conceptual lessons so they are reachable both\nways. No shell → MCP \\`lessons_query\\` (\\`file\\`/\\`command\\`/\\`keyword\\`/\\`always\\`; session dedup\nis on by default there — \\`no_dedup:true\\` to re-show).\n\n## Capture — Gate Function (before any completion claim)\n\n1. **SELF-CRITIQUE**: any failure, correction, regression, wrong assumption,\n useful surprise, repeated friction, or non-obvious fix? Failing\n tests/lint/typecheck and user/review corrections — yours or anyone's — all count.\n PROCESS/TOOLING surprises count too (a sandbox command that silently no-op'd, a port\n already in use, a library's argument shape) — trigger those with \\`--trigger-cmd\\`. So\n does a review finding you REVIEWED then deliberately REJECTED: capture it as a \"do NOT\n refactor\" guard so the reasoning survives the session.\n2. **CAPTURE** a reusable imperative rule with an effective trigger (else say so):\n \\`agentsmesh lessons add \"<rule>\" --topic <id> --trigger-file <glob>\\`. Trigger on the\n file-CLASS where it will RECUR (e.g. \\`**/lib/use*Form*.ts\\`), NOT the single file you\n discovered it in — and NOT a broad \\`src/**\\`. If the rule is a UNIVERSAL standard that\n applies to EVERY task (a comment/test/style convention no file or command names),\n capture it with \\`--scope always\\` instead — it needs no trigger and is delivered on\n every task.\n3. **RECEIPT**: emit \\`Lesson: captured <id>\\` or \\`Lesson: none\\`.\n\nAt least one _effective_ trigger is required (or \\`--scope always\\` for a universal rule) or\nthe capture is rejected (\\`UNRECALLABLE_LESSON\\`); prefer \\`--trigger-file\\`. No shell → MCP \\`lessons_query\\`,\n\\`lessons_add\\`, \\`lessons_topics\\`, \\`lessons_show\\`, \\`lessons_deprecate\\`. Run\n\\`agentsmesh lessons --help\\` for every subcommand and flag: query, add, topics, show,\ndeprecate, merge, untrigger, strip-markers, prune, journal, validate, resolve, stats, import-md.\nA git merge conflict in \\`lessons.json\\` → run \\`agentsmesh lessons resolve\\`; never hand-edit it.\n\n### Rationalization Prevention — these excuses mean STOP\n\n| Excuse | Reality |\n| --- | --- |\n| \"Small edit / I already know this / later\" | Query first — skipping recall is a process violation |\n| \"Nothing reusable here\" | You hit a failure/surprise — name it or capture it |\n| \"My own TDD red, not a real failure\" | A red you did not predict IS a lesson |\n| \"I fixed one site; the twin is obvious\" | Capture it — the unfixed twin is what gets missed |\n| \"Different words, so the rule doesn't apply\" | Spirit over letter |\n\n## Lesson gate — before final response\n\nThe final response MUST carry the receipt: \\`Lesson: captured <id>\\` or \\`Lesson: none\\`.\nNo receipt = task incomplete. Do not capture one-off facts, task summaries, or project\ncontext — only reusable imperative rules with an effective trigger.`;\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 { lessonsLockPath } from './lessons-lock.js';\nimport { outcomeLogPath } from './outcome-log.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 {\n ensureLessonsMergeDriver,\n LESSONS_GITATTRIBUTES_ENTRY,\n type MergeDriverSetup,\n} from './merge-driver-setup.js';\nimport { recallHookTeamHint as teamHintFor } from './recall-hook-hint.js';\nimport { recallLogPath } from './telemetry.js';\nimport { ensureGitattributesEntries } from '../utils/filesystem/gitattributes.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 any lessons runtime-artifact entry was added to `.gitignore`. */\n readonly gitignoreUpdated: boolean;\n /** True when the lessons.json merge-driver entry was added to `.gitattributes`. */\n readonly gitattributesUpdated: boolean;\n /** True when the lessons recall hook was injected into `hooks.yaml`. */\n readonly recallHookInjected: boolean;\n /** What this clone's merge-driver setup did; teammates get it on `generate`. */\n readonly mergeDriver: MergeDriverSetup;\n /** Set when recall hooks still need a global install to reach teammates. */\n readonly recallHookTeamHint: string | null;\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 every lessons runtime artifact out of git: the three logs, the lock\n // directory, and the `*.tmp` files an atomic write leaves behind when killed.\n // Paths come from their owning modules; the append is idempotent and\n // coverage-aware, so a re-run or a broader `.agentsmesh/` ignore is a no-op.\n const gitignoreUpdated = await ensureGitignoreEntries(projectRoot, [\n toRelPath(projectRoot, recallLogPath(projectRoot)),\n toRelPath(projectRoot, captureLogPath(projectRoot)),\n toRelPath(projectRoot, outcomeLogPath(projectRoot)),\n `${toRelPath(projectRoot, lessonsLockPath(projectRoot))}/`,\n `${toRelPath(projectRoot, paths.base)}/*.tmp`,\n ]);\n // Commit the merge-driver binding for the shared graph so a team's concurrent\n // captures union-merge instead of leaving conflict markers. Idempotent and\n // preserves any existing .gitattributes content.\n const gitattributesUpdated = await ensureGitattributesEntries(projectRoot, [\n LESSONS_GITATTRIBUTES_ENTRY,\n ]);\n // The per-clone half: set this clone's driver now instead of printing it.\n const mergeDriver = ensureLessonsMergeDriver(projectRoot);\n return {\n created,\n updated,\n skipped,\n rootRuleUpdated,\n gitignoreUpdated,\n gitattributesUpdated,\n recallHookInjected,\n mergeDriver,\n recallHookTeamHint: teamHintFor(projectRoot),\n };\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"]}
|