agent-recall-core 3.4.18 → 3.4.21

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.
Files changed (125) hide show
  1. package/README.md +404 -981
  2. package/dist/index.d.ts +45 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +33 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/naming.d.ts +109 -0
  7. package/dist/naming.d.ts.map +1 -0
  8. package/dist/naming.js +198 -0
  9. package/dist/naming.js.map +1 -0
  10. package/dist/palace/awareness.d.ts +6 -0
  11. package/dist/palace/awareness.d.ts.map +1 -1
  12. package/dist/palace/awareness.js +19 -0
  13. package/dist/palace/awareness.js.map +1 -1
  14. package/dist/palace/fsrs.d.ts +64 -0
  15. package/dist/palace/fsrs.d.ts.map +1 -0
  16. package/dist/palace/fsrs.js +86 -0
  17. package/dist/palace/fsrs.js.map +1 -0
  18. package/dist/palace/hopfield.d.ts +108 -0
  19. package/dist/palace/hopfield.d.ts.map +1 -0
  20. package/dist/palace/hopfield.js +237 -0
  21. package/dist/palace/hopfield.js.map +1 -0
  22. package/dist/palace/obsidian.d.ts.map +1 -1
  23. package/dist/palace/obsidian.js +25 -1
  24. package/dist/palace/obsidian.js.map +1 -1
  25. package/dist/palace/pipeline.d.ts +61 -0
  26. package/dist/palace/pipeline.d.ts.map +1 -0
  27. package/dist/palace/pipeline.js +289 -0
  28. package/dist/palace/pipeline.js.map +1 -0
  29. package/dist/palace/skills.d.ts +71 -0
  30. package/dist/palace/skills.d.ts.map +1 -0
  31. package/dist/palace/skills.js +225 -0
  32. package/dist/palace/skills.js.map +1 -0
  33. package/dist/storage/behavior-policies.d.ts +54 -0
  34. package/dist/storage/behavior-policies.d.ts.map +1 -0
  35. package/dist/storage/behavior-policies.js +98 -0
  36. package/dist/storage/behavior-policies.js.map +1 -0
  37. package/dist/storage/corrections.d.ts +54 -0
  38. package/dist/storage/corrections.d.ts.map +1 -1
  39. package/dist/storage/corrections.js +93 -4
  40. package/dist/storage/corrections.js.map +1 -1
  41. package/dist/storage/cwd-allowlist.d.ts +33 -0
  42. package/dist/storage/cwd-allowlist.d.ts.map +1 -0
  43. package/dist/storage/cwd-allowlist.js +106 -0
  44. package/dist/storage/cwd-allowlist.js.map +1 -0
  45. package/dist/storage/dream-health.d.ts +19 -0
  46. package/dist/storage/dream-health.d.ts.map +1 -0
  47. package/dist/storage/dream-health.js +79 -0
  48. package/dist/storage/dream-health.js.map +1 -0
  49. package/dist/storage/paths.d.ts +12 -0
  50. package/dist/storage/paths.d.ts.map +1 -1
  51. package/dist/storage/paths.js +37 -15
  52. package/dist/storage/paths.js.map +1 -1
  53. package/dist/storage/project.d.ts +6 -0
  54. package/dist/storage/project.d.ts.map +1 -1
  55. package/dist/storage/project.js +26 -1
  56. package/dist/storage/project.js.map +1 -1
  57. package/dist/storage/session.d.ts.map +1 -1
  58. package/dist/storage/session.js +16 -1
  59. package/dist/storage/session.js.map +1 -1
  60. package/dist/tools-logic/bootstrap.d.ts.map +1 -1
  61. package/dist/tools-logic/bootstrap.js +69 -6
  62. package/dist/tools-logic/bootstrap.js.map +1 -1
  63. package/dist/tools-logic/check-action.d.ts +55 -0
  64. package/dist/tools-logic/check-action.d.ts.map +1 -0
  65. package/dist/tools-logic/check-action.js +152 -0
  66. package/dist/tools-logic/check-action.js.map +1 -0
  67. package/dist/tools-logic/dashboard-export.d.ts +75 -0
  68. package/dist/tools-logic/dashboard-export.d.ts.map +1 -0
  69. package/dist/tools-logic/dashboard-export.js +271 -0
  70. package/dist/tools-logic/dashboard-export.js.map +1 -0
  71. package/dist/tools-logic/pipeline-close.d.ts +22 -0
  72. package/dist/tools-logic/pipeline-close.d.ts.map +1 -0
  73. package/dist/tools-logic/pipeline-close.js +66 -0
  74. package/dist/tools-logic/pipeline-close.js.map +1 -0
  75. package/dist/tools-logic/pipeline-current.d.ts +11 -0
  76. package/dist/tools-logic/pipeline-current.d.ts.map +1 -0
  77. package/dist/tools-logic/pipeline-current.js +8 -0
  78. package/dist/tools-logic/pipeline-current.js.map +1 -0
  79. package/dist/tools-logic/pipeline-list.d.ts +11 -0
  80. package/dist/tools-logic/pipeline-list.d.ts.map +1 -0
  81. package/dist/tools-logic/pipeline-list.js +8 -0
  82. package/dist/tools-logic/pipeline-list.js.map +1 -0
  83. package/dist/tools-logic/pipeline-open.d.ts +23 -0
  84. package/dist/tools-logic/pipeline-open.d.ts.map +1 -0
  85. package/dist/tools-logic/pipeline-open.js +109 -0
  86. package/dist/tools-logic/pipeline-open.js.map +1 -0
  87. package/dist/tools-logic/pipeline-show.d.ts +34 -0
  88. package/dist/tools-logic/pipeline-show.d.ts.map +1 -0
  89. package/dist/tools-logic/pipeline-show.js +134 -0
  90. package/dist/tools-logic/pipeline-show.js.map +1 -0
  91. package/dist/tools-logic/register-rule.d.ts +15 -0
  92. package/dist/tools-logic/register-rule.d.ts.map +1 -0
  93. package/dist/tools-logic/register-rule.js +13 -0
  94. package/dist/tools-logic/register-rule.js.map +1 -0
  95. package/dist/tools-logic/session-end-reflect.d.ts +57 -0
  96. package/dist/tools-logic/session-end-reflect.d.ts.map +1 -0
  97. package/dist/tools-logic/session-end-reflect.js +117 -0
  98. package/dist/tools-logic/session-end-reflect.js.map +1 -0
  99. package/dist/tools-logic/session-end.d.ts +29 -0
  100. package/dist/tools-logic/session-end.d.ts.map +1 -1
  101. package/dist/tools-logic/session-end.js +34 -0
  102. package/dist/tools-logic/session-end.js.map +1 -1
  103. package/dist/tools-logic/session-start-lite.d.ts +26 -0
  104. package/dist/tools-logic/session-start-lite.d.ts.map +1 -0
  105. package/dist/tools-logic/session-start-lite.js +46 -0
  106. package/dist/tools-logic/session-start-lite.js.map +1 -0
  107. package/dist/tools-logic/session-start.d.ts +26 -0
  108. package/dist/tools-logic/session-start.d.ts.map +1 -1
  109. package/dist/tools-logic/session-start.js +53 -7
  110. package/dist/tools-logic/session-start.js.map +1 -1
  111. package/dist/tools-logic/skill-list.d.ts +19 -0
  112. package/dist/tools-logic/skill-list.d.ts.map +1 -0
  113. package/dist/tools-logic/skill-list.js +20 -0
  114. package/dist/tools-logic/skill-list.js.map +1 -0
  115. package/dist/tools-logic/skill-recall.d.ts +26 -0
  116. package/dist/tools-logic/skill-recall.d.ts.map +1 -0
  117. package/dist/tools-logic/skill-recall.js +32 -0
  118. package/dist/tools-logic/skill-recall.js.map +1 -0
  119. package/dist/tools-logic/skill-write.d.ts +23 -0
  120. package/dist/tools-logic/skill-write.d.ts.map +1 -0
  121. package/dist/tools-logic/skill-write.js +46 -0
  122. package/dist/tools-logic/skill-write.js.map +1 -0
  123. package/dist/types.d.ts +1 -1
  124. package/dist/types.js +1 -1
  125. package/package.json +1 -1
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Pipeline layer — project milestone narrative spine.
3
+ * Stored under palace/pipeline/NNNN-phase-slug.md, one file per phase.
4
+ * Distinct from journal (chronology), palace/rooms (facts), awareness (cross-project).
5
+ *
6
+ * Hardening notes:
7
+ * - Order numbers sorted numerically (lex sort breaks at 10).
8
+ * - Atomic writes via tmp+rename (writeFileSync is not crash-safe).
9
+ * - Section parser only ends at the four KNOWN headings, so user-supplied
10
+ * "## Anything" inside a section body cannot break it.
11
+ * - Frontmatter parser accepts both quoted (JSON-encoded) and bare scalars.
12
+ */
13
+ import * as fs from "node:fs";
14
+ import * as path from "node:path";
15
+ import { palaceDir, sanitizeSlug } from "../storage/paths.js";
16
+ import { ensureDir } from "../storage/fs-utils.js";
17
+ import { generateFrontmatter } from "./obsidian.js";
18
+ const PLACEHOLDER = "(in progress)";
19
+ const ORDER_PAD = 4;
20
+ const KNOWN_SECTIONS = ["Goal", "What was hard", "How solved", "Synthesis"];
21
+ export function pipelineDir(project) {
22
+ return path.join(palaceDir(project), "pipeline");
23
+ }
24
+ export function zeroPad(n, width = ORDER_PAD) {
25
+ return n.toString().padStart(width, "0");
26
+ }
27
+ export function milestoneFileName(order, phase) {
28
+ return `${zeroPad(order)}-${sanitizeSlug(phase)}.md`;
29
+ }
30
+ /**
31
+ * Parse a quoted YAML scalar back to its native string.
32
+ * Handles both JSON-encoded (`"with \n escapes"`) and bare values.
33
+ */
34
+ function parseScalar(raw) {
35
+ const trimmed = raw.trim();
36
+ if (trimmed === "" || trimmed === "null" || trimmed === "~")
37
+ return null;
38
+ if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
39
+ try {
40
+ return JSON.parse(trimmed);
41
+ }
42
+ catch {
43
+ // Fall through — return raw stripped quotes
44
+ return trimmed.slice(1, -1);
45
+ }
46
+ }
47
+ if (/^-?\d+$/.test(trimmed))
48
+ return Number(trimmed);
49
+ return trimmed;
50
+ }
51
+ function parseFrontmatter(raw) {
52
+ // Accept LF or CRLF after the closing ---
53
+ const match = raw.match(/^---\s*\r?\n([\s\S]*?)\r?\n---\s*\r?\n([\s\S]*)$/);
54
+ if (!match)
55
+ return { meta: {}, body: raw };
56
+ const meta = {};
57
+ for (const line of match[1].split(/\r?\n/)) {
58
+ const idx = line.indexOf(":");
59
+ if (idx < 0)
60
+ continue;
61
+ const key = line.slice(0, idx).trim();
62
+ const rawValue = line.slice(idx + 1).trim();
63
+ if (!key)
64
+ continue;
65
+ if (rawValue.startsWith("[") && rawValue.endsWith("]")) {
66
+ const inner = rawValue.slice(1, -1).trim();
67
+ if (!inner) {
68
+ meta[key] = [];
69
+ }
70
+ else {
71
+ // Split on commas that are NOT inside quoted strings
72
+ const items = [];
73
+ let depth = 0;
74
+ let cur = "";
75
+ let inQuote = false;
76
+ for (const ch of inner) {
77
+ if (ch === '"' && cur[cur.length - 1] !== "\\")
78
+ inQuote = !inQuote;
79
+ if (ch === "," && !inQuote && depth === 0) {
80
+ items.push(cur.trim());
81
+ cur = "";
82
+ }
83
+ else {
84
+ cur += ch;
85
+ }
86
+ }
87
+ if (cur.trim())
88
+ items.push(cur.trim());
89
+ meta[key] = items.map((s) => {
90
+ const scalar = parseScalar(s);
91
+ return scalar === null ? "" : String(scalar);
92
+ });
93
+ }
94
+ }
95
+ else {
96
+ meta[key] = parseScalar(rawValue);
97
+ }
98
+ }
99
+ return { meta, body: match[2] };
100
+ }
101
+ /**
102
+ * Extract a section body by name via line-walk. Boundary is the next KNOWN
103
+ * section heading exactly matching one of Goal / What was hard / How solved /
104
+ * Synthesis. Anything else — including `## SomeOtherHeading` that the user
105
+ * (or an attacker) wrote inside a section body — is preserved verbatim.
106
+ */
107
+ function extractSection(body, heading) {
108
+ const known = new Set(KNOWN_SECTIONS);
109
+ const lines = body.split(/\r?\n/);
110
+ let capturing = false;
111
+ const captured = [];
112
+ for (const line of lines) {
113
+ const m = line.match(/^##\s+(.+?)\s*$/);
114
+ if (m && known.has(m[1])) {
115
+ if (capturing)
116
+ break; // reached next KNOWN section — stop
117
+ if (m[1] === heading) {
118
+ capturing = true;
119
+ }
120
+ continue;
121
+ }
122
+ if (capturing)
123
+ captured.push(line);
124
+ }
125
+ // Trim trailing blank lines but preserve internal blank lines.
126
+ while (captured.length > 0 && captured[captured.length - 1].trim() === "")
127
+ captured.pop();
128
+ return captured.join("\n").trim();
129
+ }
130
+ function parseMeta(raw, fallbackOrder) {
131
+ const statusRaw = String(raw.status ?? "");
132
+ const status = statusRaw === "closed" || statusRaw === "abandoned" || statusRaw === "active" ? statusRaw : "active";
133
+ return {
134
+ phase: String(raw.phase ?? ""),
135
+ order: typeof raw.order === "number" ? raw.order : fallbackOrder,
136
+ status,
137
+ opened: String(raw.opened ?? ""),
138
+ closed: raw.closed === null || raw.closed === undefined ? null : String(raw.closed),
139
+ related_journal: Array.isArray(raw.related_journal) ? raw.related_journal : undefined,
140
+ related_insights: Array.isArray(raw.related_insights) ? raw.related_insights : undefined,
141
+ auto: raw.auto === true,
142
+ };
143
+ }
144
+ export function parseMilestoneFile(filePath) {
145
+ const raw = fs.readFileSync(filePath, "utf-8");
146
+ const { meta: rawMeta, body } = parseFrontmatter(raw);
147
+ const base = path.basename(filePath, ".md");
148
+ const inferredOrder = Number(base.split("-")[0]) || 0;
149
+ return {
150
+ meta: parseMeta(rawMeta, inferredOrder),
151
+ sections: {
152
+ goal: extractSection(body, "Goal"),
153
+ what_was_hard: extractSection(body, "What was hard"),
154
+ how_solved: extractSection(body, "How solved"),
155
+ synthesis: extractSection(body, "Synthesis"),
156
+ },
157
+ file_path: filePath,
158
+ };
159
+ }
160
+ /**
161
+ * Validate a parsed milestone. Returns null if file is too broken to trust,
162
+ * which causes listMilestones to skip it (rather than promote junk to "active").
163
+ */
164
+ function isWellFormed(m) {
165
+ if (!m.meta.phase)
166
+ return false;
167
+ if (!m.meta.opened)
168
+ return false;
169
+ return true;
170
+ }
171
+ export function listMilestones(project) {
172
+ const dir = pipelineDir(project);
173
+ if (!fs.existsSync(dir))
174
+ return [];
175
+ const files = fs.readdirSync(dir).filter((f) => f.endsWith(".md") && /^\d+-/.test(f));
176
+ const milestones = [];
177
+ for (const f of files) {
178
+ try {
179
+ const m = parseMilestoneFile(path.join(dir, f));
180
+ if (isWellFormed(m))
181
+ milestones.push(m);
182
+ }
183
+ catch {
184
+ // Skip unreadable files — don't crash list
185
+ }
186
+ }
187
+ // Numeric sort by order (lex sort breaks at order=10)
188
+ milestones.sort((a, b) => a.meta.order - b.meta.order);
189
+ return milestones;
190
+ }
191
+ export function findActiveMilestone(project) {
192
+ const all = listMilestones(project);
193
+ return all.find((m) => m.meta.status === "active") ?? null;
194
+ }
195
+ export function nextOrder(project) {
196
+ const all = listMilestones(project);
197
+ if (all.length === 0)
198
+ return 1;
199
+ return Math.max(...all.map((m) => m.meta.order)) + 1;
200
+ }
201
+ /**
202
+ * Strip carriage returns, collapse newlines to spaces, and trim — for embedding
203
+ * user content into a single-line context (markdown heading, frontmatter).
204
+ */
205
+ function singleLine(s) {
206
+ return s.replace(/\r/g, "").replace(/\n+/g, " ").trim();
207
+ }
208
+ /**
209
+ * Escape body sections so that no user-supplied "## Known Heading" line can
210
+ * end a section prematurely. We prefix any such line with a zero-width-joiner
211
+ * marker that survives display but breaks the parser's regex.
212
+ *
213
+ * Cheap, reversible enough for human reading: the markdown renders normally
214
+ * except `## Goal` → `## ​Goal` (with U+200B). Most viewers show identically.
215
+ */
216
+ function escapeSectionBody(s) {
217
+ return s.replace(/^(##\s+)(Goal|What was hard|How solved|Synthesis)\b/gim, "$1​$2");
218
+ }
219
+ export function renderMilestone(meta, sections) {
220
+ const fm = generateFrontmatter({
221
+ phase: meta.phase,
222
+ order: meta.order,
223
+ status: meta.status,
224
+ opened: meta.opened,
225
+ closed: meta.closed ?? null,
226
+ auto: meta.auto === true ? true : false,
227
+ related_journal: meta.related_journal ?? [],
228
+ related_insights: meta.related_insights ?? [],
229
+ });
230
+ const safePhase = singleLine(meta.phase);
231
+ const g = escapeSectionBody(sections.goal || PLACEHOLDER);
232
+ const h = escapeSectionBody(sections.what_was_hard || PLACEHOLDER);
233
+ const s = escapeSectionBody(sections.how_solved || PLACEHOLDER);
234
+ const sy = escapeSectionBody(sections.synthesis || PLACEHOLDER);
235
+ return (fm +
236
+ `# Phase ${zeroPad(meta.order)} — ${safePhase}\n\n` +
237
+ `## Goal\n${g}\n\n` +
238
+ `## What was hard\n${h}\n\n` +
239
+ `## How solved\n${s}\n\n` +
240
+ `## Synthesis\n${sy}\n`);
241
+ }
242
+ /**
243
+ * Write a milestone file atomically via tmp + rename.
244
+ * Refuses to follow symlinks at the target path.
245
+ */
246
+ export function writeMilestone(project, meta, sections, existingFilePath) {
247
+ const dir = pipelineDir(project);
248
+ ensureDir(dir);
249
+ const filePath = existingFilePath ?? path.join(dir, milestoneFileName(meta.order, meta.phase));
250
+ // Symlink guard: if the target already exists and is a symlink, refuse.
251
+ try {
252
+ const lst = fs.lstatSync(filePath);
253
+ if (lst.isSymbolicLink()) {
254
+ throw new Error(`Refusing to write through symlink: ${filePath}`);
255
+ }
256
+ }
257
+ catch (err) {
258
+ if (err.code !== "ENOENT")
259
+ throw err;
260
+ }
261
+ // Same check on parent dir
262
+ try {
263
+ const dirStat = fs.lstatSync(dir);
264
+ if (dirStat.isSymbolicLink()) {
265
+ throw new Error(`Refusing to write into symlinked dir: ${dir}`);
266
+ }
267
+ }
268
+ catch (err) {
269
+ if (err.code !== "ENOENT")
270
+ throw err;
271
+ }
272
+ const tmp = `${filePath}.tmp.${process.pid}.${Date.now()}`;
273
+ fs.writeFileSync(tmp, renderMilestone(meta, sections), { encoding: "utf-8", mode: 0o600 });
274
+ fs.renameSync(tmp, filePath); // atomic on same filesystem
275
+ return filePath;
276
+ }
277
+ export function summarize(m) {
278
+ return {
279
+ order: m.meta.order,
280
+ phase: m.meta.phase,
281
+ status: m.meta.status,
282
+ opened: m.meta.opened,
283
+ closed: m.meta.closed ?? null,
284
+ synthesis: m.meta.status === "closed" ? m.sections.synthesis : null,
285
+ file_path: m.file_path,
286
+ };
287
+ }
288
+ export { PLACEHOLDER };
289
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/palace/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Skills — procedural memory layer (5th memory type).
3
+ *
4
+ * Closes the V10 (formal taxonomy) gap: AgentRecall today covers episodic
5
+ * (journal), semantic (palace/rooms + awareness), and narrative (pipeline)
6
+ * but has NO procedural store. Agents re-derive the same multi-step
7
+ * procedure every session — Cloudflare 4-step DNS+Proxy+OriginRule+SSL,
8
+ * git rm --cached for untracked file cleanup, OAuth refresh pre-check, etc.
9
+ *
10
+ * A Skill is a typed production rule:
11
+ * IF trigger matches AND preconditions hold THEN follow steps
12
+ *
13
+ * Storage: ~/.agent-recall/projects/<slug>/palace/skills/<NN>-<slug>.md
14
+ * (or global/procedural/<slug>.md for cross-project)
15
+ *
16
+ * Frontmatter shape conforms to naming.ts canonical schema for
17
+ * indexability + grep-friendly retrieval.
18
+ */
19
+ import { type FsrsState } from "./fsrs.js";
20
+ export interface SkillMeta {
21
+ /** Stable kebab-case slug, unique within project. */
22
+ slug: string;
23
+ /** Short human-readable name. */
24
+ name: string;
25
+ /** Topic / category (e.g. "deploy", "git", "auth"). */
26
+ topic: string;
27
+ /** Keywords that match user intent — used for trigger lookup. */
28
+ triggers: string[];
29
+ /** Optional file-path globs that increase relevance. */
30
+ file_globs?: string[];
31
+ created: string;
32
+ updated: string;
33
+ /** Where this came from. */
34
+ source?: "manual" | "promoted_from_correction" | "promoted_from_pipeline" | "auto_reflection";
35
+ /** Embedded FSRS state for reinforcement-on-use. */
36
+ fsrs?: FsrsState;
37
+ }
38
+ export interface SkillBody {
39
+ /** When to use this skill (the IF). */
40
+ when: string;
41
+ /** Preconditions to check before applying (zero or more). */
42
+ preconditions: string[];
43
+ /** Ordered steps (the THEN). */
44
+ steps: string[];
45
+ /** What success looks like — falsifiable. */
46
+ postconditions: string[];
47
+ /** Failure modes / things that went wrong before. */
48
+ pitfalls?: string[];
49
+ /** Evidence refs — journal dates / commit SHAs / corrections that led to this. */
50
+ evidence?: string[];
51
+ }
52
+ export interface Skill {
53
+ meta: SkillMeta;
54
+ body: SkillBody;
55
+ file_path: string;
56
+ }
57
+ export declare function skillsDir(project: string): string;
58
+ export declare function parseSkillFile(filePath: string): Skill;
59
+ export declare function listSkills(project: string): Skill[];
60
+ export declare function nextSkillOrder(project: string): number;
61
+ export declare function writeSkill(project: string, meta: SkillMeta, body: SkillBody, order?: number): string;
62
+ /**
63
+ * Trigger-match: rank skills by overlap of intent keywords against the skill's
64
+ * declared `triggers` + topic + name. Returns top N. Pure scoring — no LLM call.
65
+ */
66
+ export declare function recallSkillsByIntent(project: string, intent: string, limit?: number): Array<{
67
+ skill: Skill;
68
+ score: number;
69
+ matched_triggers: string[];
70
+ }>;
71
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/palace/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,QAAQ,GAAG,0BAA0B,GAAG,wBAAwB,GAAG,iBAAiB,CAAC;IAC9F,oDAAoD;IACpD,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gCAAgC;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,6CAA6C;IAC7C,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAiDD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CA4BtD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,CAanD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQtD;AA2BD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAuBpG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,SAAI,GACR,KAAK,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAiCpE"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Skills — procedural memory layer (5th memory type).
3
+ *
4
+ * Closes the V10 (formal taxonomy) gap: AgentRecall today covers episodic
5
+ * (journal), semantic (palace/rooms + awareness), and narrative (pipeline)
6
+ * but has NO procedural store. Agents re-derive the same multi-step
7
+ * procedure every session — Cloudflare 4-step DNS+Proxy+OriginRule+SSL,
8
+ * git rm --cached for untracked file cleanup, OAuth refresh pre-check, etc.
9
+ *
10
+ * A Skill is a typed production rule:
11
+ * IF trigger matches AND preconditions hold THEN follow steps
12
+ *
13
+ * Storage: ~/.agent-recall/projects/<slug>/palace/skills/<NN>-<slug>.md
14
+ * (or global/procedural/<slug>.md for cross-project)
15
+ *
16
+ * Frontmatter shape conforms to naming.ts canonical schema for
17
+ * indexability + grep-friendly retrieval.
18
+ */
19
+ import * as fs from "node:fs";
20
+ import * as path from "node:path";
21
+ import { palaceDir, sanitizeSlug } from "../storage/paths.js";
22
+ import { ensureDir } from "../storage/fs-utils.js";
23
+ import { generateFrontmatter } from "./obsidian.js";
24
+ import { initFsrs } from "./fsrs.js";
25
+ const ORDER_PAD = 4;
26
+ export function skillsDir(project) {
27
+ return path.join(palaceDir(project), "skills");
28
+ }
29
+ function zeroPad(n, width = ORDER_PAD) {
30
+ return n.toString().padStart(width, "0");
31
+ }
32
+ function parseFrontmatter(raw) {
33
+ const match = raw.match(/^---\s*\r?\n([\s\S]*?)\r?\n---\s*\r?\n([\s\S]*)$/);
34
+ if (!match)
35
+ return { meta: {}, body: raw };
36
+ const meta = {};
37
+ for (const line of match[1].split(/\r?\n/)) {
38
+ const idx = line.indexOf(":");
39
+ if (idx < 0)
40
+ continue;
41
+ const key = line.slice(0, idx).trim();
42
+ const raw = line.slice(idx + 1).trim();
43
+ if (!key)
44
+ continue;
45
+ if (raw.startsWith("[") && raw.endsWith("]")) {
46
+ const inner = raw.slice(1, -1).trim();
47
+ meta[key] = inner ? inner.split(",").map((s) => s.trim().replace(/^"|"$/g, "")) : [];
48
+ }
49
+ else if (raw.startsWith("{") && raw.endsWith("}")) {
50
+ try {
51
+ meta[key] = JSON.parse(raw);
52
+ }
53
+ catch {
54
+ meta[key] = raw;
55
+ }
56
+ }
57
+ else if (raw === "null" || raw === "") {
58
+ meta[key] = null;
59
+ }
60
+ else if (/^-?\d+(\.\d+)?$/.test(raw)) {
61
+ meta[key] = Number(raw);
62
+ }
63
+ else {
64
+ meta[key] = raw.replace(/^"|"$/g, "");
65
+ }
66
+ }
67
+ return { meta, body: match[2] };
68
+ }
69
+ function extractList(body, heading) {
70
+ const re = new RegExp(`^##\\s+${heading}\\s*\\r?\\n([\\s\\S]*?)(?=\\n##\\s+|\\s*$)`, "mi");
71
+ const m = body.match(re);
72
+ if (!m)
73
+ return [];
74
+ return m[1]
75
+ .split("\n")
76
+ .map((l) => l.trim())
77
+ .filter((l) => l.startsWith("- ") || l.startsWith("* "))
78
+ .map((l) => l.replace(/^[-*]\s+/, ""));
79
+ }
80
+ function extractParagraph(body, heading) {
81
+ const re = new RegExp(`^##\\s+${heading}\\s*\\r?\\n([\\s\\S]*?)(?=\\n##\\s+|\\s*$)`, "mi");
82
+ const m = body.match(re);
83
+ return m ? m[1].trim() : "";
84
+ }
85
+ export function parseSkillFile(filePath) {
86
+ const raw = fs.readFileSync(filePath, "utf-8");
87
+ const { meta: m, body } = parseFrontmatter(raw);
88
+ const meta = {
89
+ slug: String(m.slug ?? path.basename(filePath, ".md").split("-").slice(1).join("-")),
90
+ name: String(m.name ?? ""),
91
+ topic: String(m.topic ?? ""),
92
+ triggers: Array.isArray(m.triggers) ? m.triggers : [],
93
+ file_globs: Array.isArray(m.file_globs) ? m.file_globs : undefined,
94
+ created: String(m.created ?? ""),
95
+ updated: String(m.updated ?? ""),
96
+ source: m.source ?? "manual",
97
+ fsrs: m.fsrs && typeof m.fsrs === "object" ? m.fsrs : undefined,
98
+ };
99
+ return {
100
+ meta,
101
+ body: {
102
+ when: extractParagraph(body, "When"),
103
+ preconditions: extractList(body, "Preconditions"),
104
+ steps: extractList(body, "Steps"),
105
+ postconditions: extractList(body, "Postconditions"),
106
+ pitfalls: extractList(body, "Pitfalls"),
107
+ evidence: extractList(body, "Evidence"),
108
+ },
109
+ file_path: filePath,
110
+ };
111
+ }
112
+ export function listSkills(project) {
113
+ const dir = skillsDir(project);
114
+ if (!fs.existsSync(dir))
115
+ return [];
116
+ const files = fs.readdirSync(dir).filter((f) => f.endsWith(".md") && /^\d+-/.test(f));
117
+ const skills = [];
118
+ for (const f of files) {
119
+ try {
120
+ skills.push(parseSkillFile(path.join(dir, f)));
121
+ }
122
+ catch {
123
+ // skip unreadable
124
+ }
125
+ }
126
+ return skills.sort((a, b) => a.meta.slug.localeCompare(b.meta.slug));
127
+ }
128
+ export function nextSkillOrder(project) {
129
+ const dir = skillsDir(project);
130
+ if (!fs.existsSync(dir))
131
+ return 1;
132
+ const orders = fs
133
+ .readdirSync(dir)
134
+ .filter((f) => /^\d+-/.test(f))
135
+ .map((f) => parseInt(f.split("-")[0], 10) || 0);
136
+ return orders.length === 0 ? 1 : Math.max(...orders) + 1;
137
+ }
138
+ function renderSkill(meta, body) {
139
+ const fm = generateFrontmatter({
140
+ slug: meta.slug,
141
+ name: meta.name,
142
+ topic: meta.topic,
143
+ triggers: meta.triggers,
144
+ file_globs: meta.file_globs ?? [],
145
+ created: meta.created,
146
+ updated: meta.updated,
147
+ source: meta.source ?? "manual",
148
+ fsrs: meta.fsrs ?? null,
149
+ });
150
+ const renderList = (xs) => xs.length ? xs.map((x) => `- ${x}`).join("\n") : "- _(none)_";
151
+ return (fm +
152
+ `# ${meta.name}\n\n` +
153
+ `## When\n${body.when || "_(describe the trigger condition)_"}\n\n` +
154
+ `## Preconditions\n${renderList(body.preconditions)}\n\n` +
155
+ `## Steps\n${renderList(body.steps)}\n\n` +
156
+ `## Postconditions\n${renderList(body.postconditions)}\n\n` +
157
+ (body.pitfalls && body.pitfalls.length > 0 ? `## Pitfalls\n${renderList(body.pitfalls)}\n\n` : "") +
158
+ (body.evidence && body.evidence.length > 0 ? `## Evidence\n${renderList(body.evidence)}\n` : ""));
159
+ }
160
+ export function writeSkill(project, meta, body, order) {
161
+ const dir = skillsDir(project);
162
+ ensureDir(dir);
163
+ const finalMeta = {
164
+ ...meta,
165
+ slug: sanitizeSlug(meta.slug || meta.name),
166
+ fsrs: meta.fsrs ?? initFsrs(meta.created || new Date().toISOString()),
167
+ };
168
+ const ord = order ?? nextSkillOrder(project);
169
+ const filename = `${zeroPad(ord)}-${finalMeta.slug}.md`;
170
+ const filePath = path.join(dir, filename);
171
+ // Symlink guard
172
+ try {
173
+ const lst = fs.lstatSync(filePath);
174
+ if (lst.isSymbolicLink())
175
+ throw new Error(`Refusing to write symlinked skill file: ${filePath}`);
176
+ }
177
+ catch (e) {
178
+ if (e.code !== "ENOENT")
179
+ throw e;
180
+ }
181
+ // Atomic write
182
+ const tmp = `${filePath}.tmp.${process.pid}.${Date.now()}`;
183
+ fs.writeFileSync(tmp, renderSkill(finalMeta, body), { encoding: "utf-8", mode: 0o600 });
184
+ fs.renameSync(tmp, filePath);
185
+ return filePath;
186
+ }
187
+ /**
188
+ * Trigger-match: rank skills by overlap of intent keywords against the skill's
189
+ * declared `triggers` + topic + name. Returns top N. Pure scoring — no LLM call.
190
+ */
191
+ export function recallSkillsByIntent(project, intent, limit = 5) {
192
+ const skills = listSkills(project);
193
+ if (skills.length === 0)
194
+ return [];
195
+ const intentWords = new Set(intent
196
+ .toLowerCase()
197
+ .normalize("NFKD")
198
+ .replace(/[^a-z0-9 ]+/g, " ")
199
+ .split(/\s+/)
200
+ .filter((w) => w.length >= 3));
201
+ const ranked = skills
202
+ .map((s) => {
203
+ const haystack = [s.meta.name, s.meta.topic, ...s.meta.triggers].join(" ").toLowerCase();
204
+ const haystackWords = new Set(haystack.split(/[^a-z0-9]+/).filter((w) => w.length >= 3));
205
+ const matched = [];
206
+ let score = 0;
207
+ for (const w of intentWords) {
208
+ if (haystackWords.has(w)) {
209
+ matched.push(w);
210
+ score += 1;
211
+ }
212
+ }
213
+ // Boost: explicit trigger keyword matches count double
214
+ for (const t of s.meta.triggers) {
215
+ if (intent.toLowerCase().includes(t.toLowerCase()))
216
+ score += 1;
217
+ }
218
+ return { skill: s, score, matched_triggers: matched };
219
+ })
220
+ .filter((x) => x.score > 0)
221
+ .sort((a, b) => b.score - a.score)
222
+ .slice(0, limit);
223
+ return ranked;
224
+ }
225
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/palace/skills.ts"],"names":[],"mappings":"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"}