agentsmesh 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lessons.d.ts CHANGED
@@ -1,155 +1,106 @@
1
- import { z } from 'zod';
2
-
3
- declare function hashBullet(bullet: string): string;
4
-
5
- interface ParsedBullet {
6
- text: string;
7
- lineNumber: number;
8
- }
9
- declare function parseBullets(markdown: string): ParsedBullet[];
10
-
11
- declare const ClusterSchema: z.ZodObject<{
12
- topic: z.ZodString;
13
- file: z.ZodString;
14
- summary: z.ZodString;
15
- triggers: z.ZodObject<{
16
- file_globs: z.ZodArray<z.ZodString>;
17
- command_patterns: z.ZodArray<z.ZodString>;
18
- keywords: z.ZodArray<z.ZodString>;
19
- }, z.core.$strip>;
20
- }, z.core.$strip>;
21
- declare const LessonsIndexSchema: z.ZodObject<{
22
- version: z.ZodLiteral<1>;
23
- clusters: z.ZodArray<z.ZodObject<{
24
- topic: z.ZodString;
25
- file: z.ZodString;
26
- summary: z.ZodString;
27
- triggers: z.ZodObject<{
28
- file_globs: z.ZodArray<z.ZodString>;
29
- command_patterns: z.ZodArray<z.ZodString>;
30
- keywords: z.ZodArray<z.ZodString>;
31
- }, z.core.$strip>;
32
- }, z.core.$strip>>;
33
- }, z.core.$strip>;
34
- type LessonsIndex = z.infer<typeof LessonsIndexSchema>;
35
- type LessonsCluster = z.infer<typeof ClusterSchema>;
36
- declare function parseIndex(raw: unknown): LessonsIndex;
37
-
38
- type ToolEvent = {
39
- kind: 'edit' | 'write';
40
- filePath: string;
41
- } | {
42
- kind: 'bash';
43
- command: string;
44
- } | {
45
- kind: 'task';
46
- text: string;
47
- };
48
- declare function matchTriggers(clusters: readonly LessonsCluster[], event: ToolEvent): LessonsCluster[];
49
-
50
- declare const LedgerSchema: z.ZodObject<{
51
- version: z.ZodLiteral<1>;
52
- assignments: z.ZodRecord<z.ZodString, z.ZodString>;
53
- }, z.core.$strip>;
54
- type Ledger = z.infer<typeof LedgerSchema>;
55
- declare function loadLedger(path: string): Ledger;
56
- declare function saveLedger(path: string, ledger: Ledger): void;
57
-
58
- interface ScoredCluster {
59
- cluster: LessonsCluster;
60
- score: number;
61
- }
62
- declare function scoreBullet(bullet: string, clusters: readonly LessonsCluster[]): ScoredCluster[];
63
-
64
- interface TriggeredLesson {
65
- readonly cluster: LessonsCluster;
66
- readonly relativePath: string;
67
- readonly filePath: string;
68
- readonly content: string;
69
- }
70
- interface LessonCaptureInput {
71
- readonly heading: string;
72
- readonly whatWentWrong: string;
73
- readonly rootCause: string;
74
- readonly rule: string;
75
- }
76
- interface AppendLessonResult {
77
- readonly journalPath: string;
78
- readonly bullet: string;
79
- readonly lineNumber: number;
80
- }
81
- declare function loadLessonsIndex(projectRoot: string): LessonsIndex;
82
- declare function readTriggeredLessons(projectRoot: string, event: ToolEvent): TriggeredLesson[];
83
- declare function formatLessonBullet(input: LessonCaptureInput): string;
84
- declare function appendLessonToJournal(projectRoot: string, input: LessonCaptureInput): AppendLessonResult;
1
+ import { o as RankedLesson, A as AddLessonInput, a as AddLessonOptions, b as AddLessonResult, j as LessonsQuery } from './init-YKxF2zpQ.js';
2
+ export { c as AddLessonTriggers, D as DEFAULT_RECALL_LIMIT, X as DEFAULT_RECALL_MAX_TOKENS, I as ImportLegacyOptions, d as ImportLegacyReport, Y as LESSONS_LOCK_FILENAME, L as LESSONS_PROCEDURAL_RULE, e as Lesson, f as LessonStatus, g as LessonsGraph, Z as LessonsGraphExistsError, h as LessonsGraphSchema, i as LessonsPaths, M as MatchedLesson, k as MergeLessonsOptions, l as MergeLessonsResult, m as MutateOptions, R as RankOptions, n as RankReason, S as ScaffoldLessonsResult, p as StripMarkersOptions, q as StripMarkersReport, T as Topic, r as Trigger, s as TriggerKind, U as UnknownTopicError, V as ValidationFinding, t as ValidationLevel, u as ValidationReport, v as acquireLessonsLock, w as addLesson, x as graphFilePath, y as importLegacyLessons, _ as lessonsLockPath, z as lessonsPaths, B as loadLessonsGraph, C as mergeLessons, E as mutateLessonsGraph, F as parseGraph, G as queryLessons, H as rankLessons, J as scaffoldLessons, K as serializeGraph, N as stripLegacyMarkers, O as stripMarkersInGraph, P as toRelPath, Q as tryLoadLessonsGraph, W as validateLessonsGraph } from './init-YKxF2zpQ.js';
3
+ import 'zod';
85
4
 
86
5
  /**
87
- * Default on-disk locations for the lessons subsystem.
6
+ * Migration-aware application APIs for the lessons subsystem.
88
7
  *
89
- * All artifacts live under `<projectRoot>/.agentsmesh/lessons/`, so the lessons
90
- * subsystem is a self-contained canonical feature `agentsmesh init --lessons`
91
- * scaffolds this directory and the procedural rule, and removal is a single
92
- * directory delete.
8
+ * The WRITE path migrates automatically: `mutateLessonsGraph` (and everything
9
+ * built on it `addLesson`, `mergeLessons`, deprecate, strip-markers) runs the
10
+ * legacy→JSON migration before mutating, so even a first raw write can never
11
+ * create an empty `lessons.json` over an unmigrated `index.yaml`. (The migrator
12
+ * and scaffolding use the internal `mutateLessonsGraphLocked` to avoid
13
+ * recursing.)
93
14
  *
94
- * Path values are absolute; `*Rel` helpers return forward-slash project-relative
95
- * paths suitable for embedding in markdown rules consumed by any agent target.
15
+ * The low-level READ primitives (`tryLoadLessonsGraph`, `loadLessonsGraph`,
16
+ * `queryLessons`) do NOT migrate a first read through them on a legacy project
17
+ * would see no graph. `recallLessons` closes that: it migrates first, then
18
+ * loads + ranks. `captureLesson` is the symmetric capture entry point. Prefer
19
+ * these application APIs; reach for the read primitives only post-migration.
96
20
  */
97
- interface LessonsPaths {
98
- /** Directory containing every lessons artifact. */
99
- readonly base: string;
100
- /** Append-only journal — point of capture for new lessons. */
101
- readonly journal: string;
102
- /** Trigger index maps file_globs / command_patterns / keywords to topic files. */
103
- readonly index: string;
104
- /** Distill ledger bullet hash → assigned topic (or "skip"). */
105
- readonly ledger: string;
106
- /** Distill proposal file generated by `distill`, consumed by `distill:apply`. */
107
- readonly proposal: string;
108
- /** Directory holding one markdown file per topic cluster. */
109
- readonly topicsDir: string;
21
+ interface RecallOptions {
22
+ /** Max ranked lessons to return. Defaults to {@link DEFAULT_RECALL_LIMIT}. */
23
+ readonly limit?: number;
24
+ /**
25
+ * Cumulative rule-token budget. Defaults to {@link DEFAULT_RECALL_MAX_TOKENS};
26
+ * pass `null` to disable the budget (return up to `limit` results).
27
+ */
28
+ readonly maxTokens?: number | null;
29
+ /**
30
+ * Session correlator for recall dedup. Defaults to `AGENTSMESH_SESSION_ID`;
31
+ * when set, lessons already delivered this session are suppressed.
32
+ */
33
+ readonly sessionId?: string;
34
+ /** Force dedup off even when a session correlator is present. */
35
+ readonly noDedup?: boolean;
36
+ }
37
+ interface RecallResult {
38
+ /** Relevance-ranked, capped lessons (compact metadata lives on each entry). */
39
+ readonly lessons: RankedLesson[];
40
+ /** How many active lessons matched the query before the caps were applied. */
41
+ readonly totalMatches: number;
42
+ /**
43
+ * True when the canonical graph existed but could not be read (corrupt JSON /
44
+ * schema drift). Recall degrades to empty instead of throwing; callers surface
45
+ * this so a corrupt graph is a visible warning, not silent zero recall.
46
+ */
47
+ readonly corrupt?: boolean;
48
+ /**
49
+ * Set to the on-disk schema version when the graph is newer than this build
50
+ * understands. Recall degrades to empty (like `corrupt`) but callers surface
51
+ * an upgrade hint rather than a "corrupt" warning.
52
+ */
53
+ readonly newerVersion?: number;
54
+ /**
55
+ * Count of matched lessons suppressed because they were already delivered
56
+ * earlier in this session (dedup). 0 when dedup is off or nothing repeated.
57
+ */
58
+ readonly suppressed: number;
110
59
  }
111
- declare function lessonsPaths(projectRoot: string): LessonsPaths;
112
- /**
113
- * Project-relative path for a given absolute path, normalized to forward
114
- * slashes for cross-platform consistency in markdown rule files.
115
- */
116
- declare function toRelPath(projectRoot: string, absolute: string): string;
117
60
  /**
118
- * Empty-journal contents used by init scaffolding. The journal grows from here
119
- * as failures get recorded.
61
+ * Recall primitive for applications: migrate if needed, then return the active
62
+ * lessons matching `query`, relevance-ranked and capped by limit + token budget.
120
63
  */
121
- declare const LESSONS_JOURNAL_TEMPLATE = "# Lessons Learned\n\n";
64
+ declare function recallLessons(projectRoot: string, query: LessonsQuery, options?: RecallOptions): Promise<RecallResult>;
122
65
  /**
123
- * Empty index used by init scaffolding. Schema allows zero clusters; topics
124
- * accumulate via `distill:apply` as failures are captured.
66
+ * Capture primitive for applications: migrate if needed, then add the lesson
67
+ * through the transactional write path. Idempotent on repeat (same rule+topic).
68
+ *
69
+ * Both CLI `lessons add` and MCP `lessons_add` route through here, so capture
70
+ * telemetry is recorded once at this single entry point (mirroring how every
71
+ * recall records through `recallLessons`). Every rejection — a dead trigger, an
72
+ * unknown topic, a write-barrier failure — is recorded as a BLOCKED capture
73
+ * before being rethrown, so `stats` never undercounts blocks.
125
74
  */
126
- declare const LESSONS_INDEX_TEMPLATE = "version: 1\nclusters: []\n";
75
+ declare function captureLesson(projectRoot: string, input: AddLessonInput, options?: AddLessonOptions): Promise<AddLessonResult>;
76
+
127
77
  /**
128
- * Procedural rule paragraph that must live in the project's root rule
129
- * (`.agentsmesh/rules/_root.md`) for both recall and capture to be enforced.
130
- *
131
- * Universal across every agent target: only requires the ability to read
132
- * project files. No `Skill` tool, no description-match, no per-target
133
- * projection.
78
+ * One-shot legacy→JSON migration on first access. Shared by the CLI dispatcher
79
+ * AND the MCP handlers so that an MCP-only agent (query/add) does not strand a
80
+ * legacy store: if it added first it would create `lessons.json`, which then
81
+ * permanently blocks the absent-graph auto-migration. Returns true if it
82
+ * migrated. No-op when a graph already exists or no legacy index is present.
134
83
  */
135
- declare const LESSONS_PROCEDURAL_RULE = "## Lessons (MUST do \u2014 non-negotiable)\n\nTwo rituals. Universal across every agent harness \u2014 described in tool-agnostic action verbs (\"read a file\", \"edit a file\", \"run a shell command\"); use whatever read / write-patch / shell-exec tool your harness exposes. Skipping either ritual is a process violation; the same paid-for failure recurs next session.\n\n**Recall \u2014 BEFORE editing any file or running any shell command:**\n\n1. Read `.agentsmesh/lessons/index.yaml`.\n2. For every cluster whose triggers match \u2014 `file_globs` against the target file path, `command_patterns` (regex) against the shell command, or `keywords` (case-insensitive substring) against the active task description \u2014 read its `file` (e.g. `.agentsmesh/lessons/topics/<topic>.md`).\n3. Apply the loaded rules to the action.\n4. Then \u2014 and only then \u2014 perform the edit or run the command.\n\nRejected excuses: *\"the edit is small\"* \u2192 apply it. *\"I read this earlier in the session\"* \u2192 context may have compacted; re-read. *\"no trigger fires\"* \u2192 proceed; you've done your part.\n\n**Capture \u2014 IMMEDIATELY after any failure** (test, CI, lint, code review, user correction, regression you spotted yourself, OR any mistake by anyone in the loop):\n\n1. Append one bullet to `.agentsmesh/lessons/journal.md` in this exact shape:\n `- **<short heading>**: <what went wrong>. <root cause>. <imperative rule that prevents recurrence>.`\n2. Read `.agentsmesh/lessons/index.yaml` and identify which topic the lesson belongs to (use the `summary:` fields).\n3. If the lesson teaches a NEW rule: edit that topic's `## Rules` section to add it, citing `(Evidence: L<journal-line>)`. If it only reinforces an existing rule, the journal entry alone suffices.\n\nRejected excuses: *\"it wasn't really a failure\"* \u2192 if you fixed something, it was. *\"I'll capture it later\"* \u2192 no; do it now while context is fresh. *\"no topic fits\"* \u2192 still record in journal; an unrouted bullet is recoverable, a forgotten one is not.\n\n**These two rituals are load-bearing. Treat them with the same discipline as TDD.**";
84
+ declare function maybeAutoMigrateLessons(projectRoot: string): Promise<boolean>;
136
85
 
137
- interface ScaffoldLessonsResult {
138
- readonly created: string[];
139
- readonly skipped: string[];
140
- readonly rootRuleUpdated: boolean;
141
- }
142
86
  /**
143
- * Idempotent scaffolder for the lessons subsystem. Intended for a future
144
- * `agentsmesh init --lessons` flag (project mode); safe to call repeatedly.
87
+ * Safety gate for `command_pattern` triggers.
145
88
  *
146
- * Creates `.agentsmesh/lessons/` with an empty journal, an empty index, and a
147
- * `topics/` directory. Appends the procedural rule to
148
- * `.agentsmesh/rules/_root.md` if not already present.
89
+ * Recall is mandatory (it runs before every edit/command) and matches
90
+ * author-supplied patterns against the command string. A backtracking `RegExp`
91
+ * can be driven super-linear by a crafted pattern — `(a+)+`, `(a|aa)+`, `a+a+`,
92
+ * or even `a+b` (quadratic on a long non-matching input) — so one lesson could
93
+ * hang recall. Local inspection of quantifier shape CANNOT prove a backtracking
94
+ * regex linear, so we do not try: command patterns are matched by an in-repo
95
+ * non-backtracking engine ({@link compileLinearMatcher}), which is provably
96
+ * linear in the input length for any pattern it can compile.
149
97
  *
150
- * Never overwrites existing files. The ledger and proposal are not created
151
- * they are auto-managed by the distill tool on first run.
98
+ * A pattern is "safe" iff the linear engine can compile it. Patterns it cannot
99
+ * evaluate (invalid syntax, backreferences, lookarounds) are rejected at capture
100
+ * (UNSAFE_TRIGGER_PATTERN) and skipped at read time — fail closed.
152
101
  */
153
- declare function scaffoldLessons(projectRoot: string): ScaffoldLessonsResult;
154
102
 
155
- export { type AppendLessonResult, LESSONS_INDEX_TEMPLATE, LESSONS_JOURNAL_TEMPLATE, LESSONS_PROCEDURAL_RULE, type Ledger, type LessonCaptureInput, type LessonsCluster, type LessonsIndex, LessonsIndexSchema, type LessonsPaths, type ParsedBullet, type ScaffoldLessonsResult, type ScoredCluster, type ToolEvent, type TriggeredLesson, appendLessonToJournal, formatLessonBullet, hashBullet, lessonsPaths, loadLedger, loadLessonsIndex, matchTriggers, parseBullets, parseIndex, readTriggeredLessons, saveLedger, scaffoldLessons, scoreBullet, toRelPath };
103
+ /** True when `pattern` can be matched by the linear engine (no ReDoS risk). */
104
+ declare function isSafeRegexPattern(pattern: string): boolean;
105
+
106
+ export { AddLessonInput, AddLessonOptions, AddLessonResult, LessonsQuery, RankedLesson, type RecallOptions, type RecallResult, captureLesson, isSafeRegexPattern, maybeAutoMigrateLessons, recallLessons };