agent-recall-core 3.4.18 → 3.4.20

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 (101) hide show
  1. package/README.md +404 -981
  2. package/dist/index.d.ts +35 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +28 -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/corrections.d.ts +54 -0
  34. package/dist/storage/corrections.d.ts.map +1 -1
  35. package/dist/storage/corrections.js +93 -4
  36. package/dist/storage/corrections.js.map +1 -1
  37. package/dist/storage/paths.d.ts +12 -0
  38. package/dist/storage/paths.d.ts.map +1 -1
  39. package/dist/storage/paths.js +37 -15
  40. package/dist/storage/paths.js.map +1 -1
  41. package/dist/storage/session.d.ts.map +1 -1
  42. package/dist/storage/session.js +16 -1
  43. package/dist/storage/session.js.map +1 -1
  44. package/dist/tools-logic/bootstrap.d.ts.map +1 -1
  45. package/dist/tools-logic/bootstrap.js +69 -6
  46. package/dist/tools-logic/bootstrap.js.map +1 -1
  47. package/dist/tools-logic/dashboard-export.d.ts +75 -0
  48. package/dist/tools-logic/dashboard-export.d.ts.map +1 -0
  49. package/dist/tools-logic/dashboard-export.js +271 -0
  50. package/dist/tools-logic/dashboard-export.js.map +1 -0
  51. package/dist/tools-logic/pipeline-close.d.ts +22 -0
  52. package/dist/tools-logic/pipeline-close.d.ts.map +1 -0
  53. package/dist/tools-logic/pipeline-close.js +66 -0
  54. package/dist/tools-logic/pipeline-close.js.map +1 -0
  55. package/dist/tools-logic/pipeline-current.d.ts +11 -0
  56. package/dist/tools-logic/pipeline-current.d.ts.map +1 -0
  57. package/dist/tools-logic/pipeline-current.js +8 -0
  58. package/dist/tools-logic/pipeline-current.js.map +1 -0
  59. package/dist/tools-logic/pipeline-list.d.ts +11 -0
  60. package/dist/tools-logic/pipeline-list.d.ts.map +1 -0
  61. package/dist/tools-logic/pipeline-list.js +8 -0
  62. package/dist/tools-logic/pipeline-list.js.map +1 -0
  63. package/dist/tools-logic/pipeline-open.d.ts +23 -0
  64. package/dist/tools-logic/pipeline-open.d.ts.map +1 -0
  65. package/dist/tools-logic/pipeline-open.js +109 -0
  66. package/dist/tools-logic/pipeline-open.js.map +1 -0
  67. package/dist/tools-logic/pipeline-show.d.ts +34 -0
  68. package/dist/tools-logic/pipeline-show.d.ts.map +1 -0
  69. package/dist/tools-logic/pipeline-show.js +134 -0
  70. package/dist/tools-logic/pipeline-show.js.map +1 -0
  71. package/dist/tools-logic/session-end-reflect.d.ts +57 -0
  72. package/dist/tools-logic/session-end-reflect.d.ts.map +1 -0
  73. package/dist/tools-logic/session-end-reflect.js +117 -0
  74. package/dist/tools-logic/session-end-reflect.js.map +1 -0
  75. package/dist/tools-logic/session-end.d.ts +29 -0
  76. package/dist/tools-logic/session-end.d.ts.map +1 -1
  77. package/dist/tools-logic/session-end.js +34 -0
  78. package/dist/tools-logic/session-end.js.map +1 -1
  79. package/dist/tools-logic/session-start-lite.d.ts +26 -0
  80. package/dist/tools-logic/session-start-lite.d.ts.map +1 -0
  81. package/dist/tools-logic/session-start-lite.js +46 -0
  82. package/dist/tools-logic/session-start-lite.js.map +1 -0
  83. package/dist/tools-logic/session-start.d.ts +12 -0
  84. package/dist/tools-logic/session-start.d.ts.map +1 -1
  85. package/dist/tools-logic/session-start.js +30 -2
  86. package/dist/tools-logic/session-start.js.map +1 -1
  87. package/dist/tools-logic/skill-list.d.ts +19 -0
  88. package/dist/tools-logic/skill-list.d.ts.map +1 -0
  89. package/dist/tools-logic/skill-list.js +20 -0
  90. package/dist/tools-logic/skill-list.js.map +1 -0
  91. package/dist/tools-logic/skill-recall.d.ts +26 -0
  92. package/dist/tools-logic/skill-recall.d.ts.map +1 -0
  93. package/dist/tools-logic/skill-recall.js +32 -0
  94. package/dist/tools-logic/skill-recall.js.map +1 -0
  95. package/dist/tools-logic/skill-write.d.ts +23 -0
  96. package/dist/tools-logic/skill-write.d.ts.map +1 -0
  97. package/dist/tools-logic/skill-write.js +46 -0
  98. package/dist/tools-logic/skill-write.js.map +1 -0
  99. package/dist/types.d.ts +1 -1
  100. package/dist/types.js +1 -1
  101. package/package.json +1 -1
@@ -16,6 +16,50 @@ export interface CorrectionRecord {
16
16
  kind?: "correction" | "insight" | "hunch" | "fact";
17
17
  weight?: number;
18
18
  active?: boolean;
19
+ /**
20
+ * Outcome KPIs — closes the learning loop.
21
+ * V9 (research vantage 9, 2026-05-30): the only KPI that matters is
22
+ * "does the same bug recur after this correction was retrieved?"
23
+ */
24
+ retrieved_count?: number;
25
+ heeded_count?: number;
26
+ recurrence_count?: number;
27
+ precision?: number;
28
+ last_retrieved?: string;
29
+ last_outcome?: string;
30
+ }
31
+ export interface CorrectionOutcome {
32
+ correction_id: string;
33
+ project: string;
34
+ /** "heeded" = agent's action honored the warning. "recurred" = same bug happened again. */
35
+ kind: "retrieved" | "heeded" | "recurred";
36
+ /** ISO timestamp */
37
+ at: string;
38
+ /** Free-text evidence — what made you decide. */
39
+ evidence?: string;
40
+ }
41
+ export interface CorrectionKPI {
42
+ project: string;
43
+ total: number;
44
+ active: number;
45
+ retrieved: number;
46
+ heeded: number;
47
+ recurred: number;
48
+ /** Aggregate precision = sum(heeded) / sum(retrieved). NaN if retrieved=0. */
49
+ precision: number;
50
+ /** Insights below 0.3 precision — archive candidates. */
51
+ noise_candidates: Array<{
52
+ id: string;
53
+ rule: string;
54
+ precision: number;
55
+ }>;
56
+ /** Insights above 0.8 precision with ≥3 retrievals — promote candidates. */
57
+ high_signal: Array<{
58
+ id: string;
59
+ rule: string;
60
+ precision: number;
61
+ retrieved: number;
62
+ }>;
19
63
  }
20
64
  /**
21
65
  * Write a correction to persistent storage.
@@ -35,4 +79,14 @@ export declare function readActiveCorrections(project: string): CorrectionRecord
35
79
  * Respects active field — archived corrections (active:false) are excluded.
36
80
  */
37
81
  export declare function readP0Corrections(project: string): CorrectionRecord[];
82
+ /**
83
+ * Record an outcome event for a correction (retrieved / heeded / recurred).
84
+ * Appends to _outcomes.jsonl and also updates the correction JSON's counters
85
+ * + precision cache. Atomic per-write.
86
+ */
87
+ export declare function recordOutcome(outcome: CorrectionOutcome): void;
88
+ /**
89
+ * Aggregate KPIs over all corrections for a project — the "is this learning loop working?" view.
90
+ */
91
+ export declare function getCorrectionKPIs(project: string): CorrectionKPI;
38
92
  //# sourceMappingURL=corrections.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"corrections.d.ts","sourceRoot":"","sources":["../../src/storage/corrections.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAqDD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAYnF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAqBnE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAEzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAErE"}
1
+ {"version":3,"file":"corrections.d.ts","sourceRoot":"","sources":["../../src/storage/corrections.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,IAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC1C,oBAAoB;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,gBAAgB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,4EAA4E;IAC5E,WAAW,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxF;AA8DD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAenF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAqBnE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAEzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAErE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAqC9D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAkChE"}
@@ -12,14 +12,22 @@ import { ensureDir } from "./fs-utils.js";
12
12
  // Internal helpers
13
13
  // ---------------------------------------------------------------------------
14
14
  function correctionsDir(project) {
15
- const safe = project.replace(/[^a-zA-Z0-9_\-\.]/g, "-");
15
+ // Hardened sanitizer — same rule as storage/paths.ts. No dots (prevents ".." escape).
16
+ const safe = (project || "unnamed")
17
+ .replace(/[^a-zA-Z0-9_\-]/g, "-")
18
+ .replace(/^-+|-+$/g, "")
19
+ .slice(0, 100) || "unnamed";
16
20
  const root = getRoot();
17
21
  const resolved = path.join(root, "projects", safe, "corrections");
18
- if (!resolved.startsWith(root)) {
19
- throw new Error(`Invalid project: ${project}`);
22
+ const rootSep = root.endsWith(path.sep) ? root : root + path.sep;
23
+ if (!resolved.startsWith(rootSep)) {
24
+ throw new Error(`Invalid project (path escape): ${project}`);
20
25
  }
21
26
  return resolved;
22
27
  }
28
+ function outcomesPath(project) {
29
+ return path.join(correctionsDir(project), "_outcomes.jsonl");
30
+ }
23
31
  /** Auto-detect severity: p0 if uses strong negation/mandate language, else p1. */
24
32
  function detectSeverity(text) {
25
33
  const p0Patterns = /\bnever\b|\balways\b|\bdon'?t\b|\bdo not\b|\bmust not\b|\bforbid\b|\bprohibit\b/i;
@@ -63,7 +71,10 @@ export function writeCorrection(project, correction) {
63
71
  const record = applyCorrectionDefaults({ ...correction, severity }, todayDate());
64
72
  const filename = `${record.date}-${slugify(record.rule || record.id)}.json`;
65
73
  const filepath = path.join(dir, filename);
66
- fs.writeFileSync(filepath, JSON.stringify(record, null, 2), "utf-8");
74
+ // Atomic write — tmp + rename, mode 0600
75
+ const tmp = `${filepath}.tmp.${process.pid}.${Date.now()}`;
76
+ fs.writeFileSync(tmp, JSON.stringify(record, null, 2), { encoding: "utf-8", mode: 0o600 });
77
+ fs.renameSync(tmp, filepath);
67
78
  }
68
79
  /**
69
80
  * Read all corrections for a project, sorted newest first.
@@ -102,4 +113,82 @@ export function readActiveCorrections(project) {
102
113
  export function readP0Corrections(project) {
103
114
  return readCorrections(project).filter((r) => r.severity === "p0" && r.active !== false);
104
115
  }
116
+ /**
117
+ * Record an outcome event for a correction (retrieved / heeded / recurred).
118
+ * Appends to _outcomes.jsonl and also updates the correction JSON's counters
119
+ * + precision cache. Atomic per-write.
120
+ */
121
+ export function recordOutcome(outcome) {
122
+ const dir = correctionsDir(outcome.project);
123
+ ensureDir(dir);
124
+ // Append jsonl event (audit trail).
125
+ const line = JSON.stringify(outcome) + "\n";
126
+ fs.appendFileSync(outcomesPath(outcome.project), line, "utf-8");
127
+ // Update the per-correction file's counters.
128
+ const target = readCorrections(outcome.project).find((r) => r.id === outcome.correction_id);
129
+ if (!target)
130
+ return; // outcome can still be replayed later if record is restored
131
+ const updated = {
132
+ ...target,
133
+ retrieved_count: target.retrieved_count ?? 0,
134
+ heeded_count: target.heeded_count ?? 0,
135
+ recurrence_count: target.recurrence_count ?? 0,
136
+ };
137
+ if (outcome.kind === "retrieved") {
138
+ updated.retrieved_count = (updated.retrieved_count ?? 0) + 1;
139
+ updated.last_retrieved = outcome.at;
140
+ }
141
+ else if (outcome.kind === "heeded") {
142
+ updated.heeded_count = (updated.heeded_count ?? 0) + 1;
143
+ updated.last_outcome = outcome.at;
144
+ }
145
+ else if (outcome.kind === "recurred") {
146
+ updated.recurrence_count = (updated.recurrence_count ?? 0) + 1;
147
+ updated.last_outcome = outcome.at;
148
+ }
149
+ const r = updated.retrieved_count ?? 0;
150
+ updated.precision = r > 0 ? Number(((updated.heeded_count ?? 0) / r).toFixed(3)) : undefined;
151
+ // Re-write the JSON file atomically (tmp + rename — prevents truncation on SIGTERM).
152
+ const filename = `${updated.date}-${slugify(updated.rule || updated.id)}.json`;
153
+ const filepath = path.join(dir, filename);
154
+ const tmp = `${filepath}.tmp.${process.pid}.${Date.now()}`;
155
+ fs.writeFileSync(tmp, JSON.stringify(updated, null, 2), { encoding: "utf-8", mode: 0o600 });
156
+ fs.renameSync(tmp, filepath);
157
+ }
158
+ /**
159
+ * Aggregate KPIs over all corrections for a project — the "is this learning loop working?" view.
160
+ */
161
+ export function getCorrectionKPIs(project) {
162
+ const all = readCorrections(project);
163
+ const active = all.filter((r) => r.active !== false);
164
+ let retrieved = 0;
165
+ let heeded = 0;
166
+ let recurred = 0;
167
+ const noise = [];
168
+ const hot = [];
169
+ for (const r of all) {
170
+ retrieved += r.retrieved_count ?? 0;
171
+ heeded += r.heeded_count ?? 0;
172
+ recurred += r.recurrence_count ?? 0;
173
+ const p = r.precision ?? null;
174
+ const ret = r.retrieved_count ?? 0;
175
+ if (p !== null && ret >= 3 && p < 0.3) {
176
+ noise.push({ id: r.id, rule: r.rule, precision: p });
177
+ }
178
+ if (p !== null && ret >= 3 && p >= 0.8) {
179
+ hot.push({ id: r.id, rule: r.rule, precision: p, retrieved: ret });
180
+ }
181
+ }
182
+ return {
183
+ project,
184
+ total: all.length,
185
+ active: active.length,
186
+ retrieved,
187
+ heeded,
188
+ recurred,
189
+ precision: retrieved > 0 ? Number((heeded / retrieved).toFixed(3)) : NaN,
190
+ noise_candidates: noise,
191
+ high_signal: hot,
192
+ };
193
+ }
105
194
  //# sourceMappingURL=corrections.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"corrections.js","sourceRoot":"","sources":["../../src/storage/corrections.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"corrections.js","sourceRoot":"","sources":["../../src/storage/corrections.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAyD1C,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,cAAc,CAAC,OAAe;IACrC,sFAAsF;IACtF,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;SAChC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC;SAChC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;IAC9B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;IACjE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,CAAC;AAC/D,CAAC;AAED,kFAAkF;AAClF,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,UAAU,GAAG,kFAAkF,CAAC;IACtG,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,uEAAuE;AACvE,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CAAC,QAAqB;IAC1C,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AACvC,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,uBAAuB,CAAC,MAAwB,EAAE,aAAqB;IAC9E,OAAO;QACL,GAAG,MAAM;QACT,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,aAAa;QACtC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,YAAY;QACjC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC;QACvD,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;KAC9B,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,UAA4B;IAC3E,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACpC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEf,0CAA0C;IAC1C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,IAAI,cAAc,CAAC,GAAG,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;IACnG,MAAM,MAAM,GAAG,uBAAuB,CAAC,EAAE,GAAG,UAAU,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAEjF,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC;IAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAE1C,yCAAyC;IACzC,MAAM,GAAG,GAAG,GAAG,QAAQ,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAC3D,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3F,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC;SAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;SAClC,IAAI,EAAE;SACN,OAAO,EAAE,CAAC;IAEb,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AAC3F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,OAA0B;IACtD,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,SAAS,CAAC,GAAG,CAAC,CAAC;IAEf,oCAAoC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,EAAE,CAAC,cAAc,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAEhE,6CAA6C;IAC7C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5F,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,4DAA4D;IAEjF,MAAM,OAAO,GAAqB;QAChC,GAAG,MAAM;QACT,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,CAAC;QAC5C,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC;QACtC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,IAAI,CAAC;KAC/C,CAAC;IACF,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACjC,OAAO,CAAC,eAAe,GAAG,CAAC,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,EAAE,CAAC;IACtC,CAAC;SAAM,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,CAAC,YAAY,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACvD,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC;IACpC,CAAC;SAAM,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACvC,OAAO,CAAC,gBAAgB,GAAG,CAAC,OAAO,CAAC,gBAAgB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC/D,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,CAAC,GAAG,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC;IACvC,OAAO,CAAC,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE7F,qFAAqF;IACrF,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC;IAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,GAAG,QAAQ,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAC3D,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5F,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;IACrD,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,MAAM,KAAK,GAAsC,EAAE,CAAC;IACpD,MAAM,GAAG,GAAiC,EAAE,CAAC;IAE7C,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,SAAS,IAAI,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;QACpC,MAAM,IAAI,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC;QAC9B,QAAQ,IAAI,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC;QAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;YACvC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,KAAK,EAAE,GAAG,CAAC,MAAM;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS;QACT,MAAM;QACN,QAAQ;QACR,SAAS,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;QACxE,gBAAgB,EAAE,KAAK;QACvB,WAAW,EAAE,GAAG;KACjB,CAAC;AACJ,CAAC"}
@@ -1,6 +1,18 @@
1
1
  /**
2
2
  * Journal and palace directory path resolution.
3
+ *
4
+ * Security: every project-name sanitizer strips dots (preventing ".." traversal)
5
+ * AND verifies the resolved path stays under root with a trailing-separator check
6
+ * (preventing `~/.agent-recallEVIL` prefix bypass).
3
7
  */
8
+ /**
9
+ * Sanitize a project name for safe use in path.join().
10
+ * Strips ALL non-alphanumeric chars (including dots) to prevent ".." traversal.
11
+ *
12
+ * Exported so other modules (bootstrap, etc.) share the same hardened slug
13
+ * grammar instead of rolling their own. Future-proofing against drift.
14
+ */
15
+ export declare function sanitizeProject(project: string): string;
4
16
  /**
5
17
  * Resolve the journal directory for a project.
6
18
  * For writes, always use the new location.
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA6BrD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOvD;AAaD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA6BrD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
@@ -1,20 +1,48 @@
1
1
  /**
2
2
  * Journal and palace directory path resolution.
3
+ *
4
+ * Security: every project-name sanitizer strips dots (preventing ".." traversal)
5
+ * AND verifies the resolved path stays under root with a trailing-separator check
6
+ * (preventing `~/.agent-recallEVIL` prefix bypass).
3
7
  */
4
8
  import * as fs from "node:fs";
5
9
  import * as path from "node:path";
6
10
  import { getRoot, getLegacyRoot } from "../types.js";
11
+ /**
12
+ * Sanitize a project name for safe use in path.join().
13
+ * Strips ALL non-alphanumeric chars (including dots) to prevent ".." traversal.
14
+ *
15
+ * Exported so other modules (bootstrap, etc.) share the same hardened slug
16
+ * grammar instead of rolling their own. Future-proofing against drift.
17
+ */
18
+ export function sanitizeProject(project) {
19
+ if (!project)
20
+ return "unnamed";
21
+ const safe = project
22
+ .replace(/[^a-zA-Z0-9_\-]/g, "-")
23
+ .replace(/^-+|-+$/g, "")
24
+ .slice(0, 100);
25
+ return safe || "unnamed";
26
+ }
27
+ /**
28
+ * Check that `resolved` is strictly inside `root` (rejects prefix matches like
29
+ * "/foo/bar" being inside "/foo/ba"). Throws if not.
30
+ */
31
+ function assertInsideRoot(resolved, root, project) {
32
+ const rootWithSep = root.endsWith(path.sep) ? root : root + path.sep;
33
+ if (!resolved.startsWith(rootWithSep) && resolved !== root) {
34
+ throw new Error(`Invalid project name (path escape): ${project}`);
35
+ }
36
+ }
7
37
  /**
8
38
  * Resolve the journal directory for a project.
9
39
  * For writes, always use the new location.
10
40
  */
11
41
  export function journalDir(project) {
12
- const safe = project.replace(/[^a-zA-Z0-9_\-\.]/g, "-");
42
+ const safe = sanitizeProject(project);
13
43
  const root = getRoot();
14
44
  const resolved = path.join(root, "projects", safe, "journal");
15
- if (!resolved.startsWith(root)) {
16
- throw new Error(`Invalid project name: ${project}`);
17
- }
45
+ assertInsideRoot(resolved, root, project);
18
46
  return resolved;
19
47
  }
20
48
  /**
@@ -49,12 +77,10 @@ export function journalDirs(project) {
49
77
  * Resolve the palace directory for a project.
50
78
  */
51
79
  export function palaceDir(project) {
52
- const safe = project.replace(/[^a-zA-Z0-9_\-\.]/g, "-");
80
+ const safe = sanitizeProject(project);
53
81
  const root = getRoot();
54
82
  const resolved = path.join(root, "projects", safe, "palace");
55
- if (!resolved.startsWith(root)) {
56
- throw new Error(`Invalid project name: ${project}`);
57
- }
83
+ assertInsideRoot(resolved, root, project);
58
84
  return resolved;
59
85
  }
60
86
  /**
@@ -63,9 +89,7 @@ export function palaceDir(project) {
63
89
  export function roomDir(project, roomSlug) {
64
90
  const safeSlug = roomSlug.replace(/[^a-zA-Z0-9_\-]/g, "-");
65
91
  const resolved = path.join(palaceDir(project), "rooms", safeSlug);
66
- if (!resolved.startsWith(getRoot())) {
67
- throw new Error(`Invalid room slug: ${roomSlug}`);
68
- }
92
+ assertInsideRoot(resolved, getRoot(), `${project}/${roomSlug}`);
69
93
  return resolved;
70
94
  }
71
95
  /**
@@ -86,12 +110,10 @@ export function sanitizeSlug(input) {
86
110
  * Resolve the digest directory for a project.
87
111
  */
88
112
  export function digestDir(project) {
89
- const safe = project.replace(/[^a-zA-Z0-9_\-\.]/g, "-");
113
+ const safe = sanitizeProject(project);
90
114
  const root = getRoot();
91
115
  const resolved = path.join(root, "projects", safe, "digest");
92
- if (!resolved.startsWith(root)) {
93
- throw new Error(`Invalid project name: ${project}`);
94
- }
116
+ assertInsideRoot(resolved, root, project);
95
117
  return resolved;
96
118
  }
97
119
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/storage/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAQjF,0CAA0C;AAC1C,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wCAAwC;AACxC,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAE3F,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAUjF;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAgD7G;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBhH;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/storage/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAQjF,0CAA0C;AAC1C,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wCAAwC;AACxC,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAE3F,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAUjF;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CA+D7G;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBhH;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -43,7 +43,22 @@ function topicSlug(content) {
43
43
  export function journalFileName(date, baseExists, opts, dir) {
44
44
  // New intelligent naming
45
45
  if (opts?.saveType && opts?.content) {
46
- // SAME-DAY RULE: one file per day per project.
46
+ // SESSION-SCOPED EXCEPTION (arsaveall):
47
+ // When multiple parallel sessions all touch the same project today,
48
+ // the SAME-DAY rule would collapse them into one file and silently
49
+ // drop content. For arsaveall specifically we bypass it and generate
50
+ // a unique per-call session-scoped filename so every session survives.
51
+ if (opts.saveType === "arsaveall") {
52
+ const slug = topicSlug(opts.content);
53
+ const sigTag = opts.sig ?? "none";
54
+ const themeTag = opts.theme ?? "none";
55
+ const uniq = crypto.randomBytes(3).toString("hex"); // per-call random — unique across iterations
56
+ const name = `${date}--arsaveall--${sigTag}--${themeTag}--${slug}--${uniq}.md`;
57
+ if (dir)
58
+ ownedFiles.add(`smart:${name}`);
59
+ return name;
60
+ }
61
+ // SAME-DAY RULE: one file per day per project (other saveTypes only).
47
62
  // If ANY file for today already exists (smart or legacy), append to it.
48
63
  if (dir) {
49
64
  const existingToday = fs.readdirSync(dir)
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/storage/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/storage/session.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/tools-logic/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsBH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,KAAK,GAAG,eAAe,GAAG,UAAU,GAAG,cAAc,CAAC;QAC5D,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,cAAc,GAAG,YAAY,CAAC;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,KAAK,EAAE;QACL,cAAc,EAAE,MAAM,CAAC;QACvB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,WAAW,EAAE,MAAM,CAAC;CACrB;AAqPD,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE;IAC5C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA8P/B;AAMD,wBAAsB,eAAe,CACnC,IAAI,EAAE,mBAAmB,EACzB,SAAS,CAAC,EAAE,eAAe,GAC1B,OAAO,CAAC,YAAY,CAAC,CA6QvB"}
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/tools-logic/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiEH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,KAAK,GAAG,eAAe,GAAG,UAAU,GAAG,cAAc,CAAC;QAC5D,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,cAAc,GAAG,YAAY,CAAC;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,KAAK,EAAE;QACL,cAAc,EAAE,MAAM,CAAC;QACvB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,WAAW,EAAE,MAAM,CAAC;CACrB;AAqPD,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE;IAC5C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA2Q/B;AAMD,wBAAsB,eAAe,CACnC,IAAI,EAAE,mBAAmB,EACzB,SAAS,CAAC,EAAE,eAAe,GAC1B,OAAO,CAAC,YAAY,CAAC,CAmRvB"}
@@ -18,9 +18,54 @@ import { todayISO } from "../storage/fs-utils.js";
18
18
  import { palaceWrite } from "./palace-write.js";
19
19
  import { journalWrite } from "./journal-write.js";
20
20
  import { awarenessUpdate } from "./awareness-update.js";
21
- import { palaceDir } from "../storage/paths.js";
21
+ import { palaceDir, sanitizeProject } from "../storage/paths.js";
22
22
  const execFileAsync = promisify(execFile);
23
23
  // ---------------------------------------------------------------------------
24
+ // Denylist — parent / system / cache directories that should NEVER be imported
25
+ // as projects. AutoMemory encoded paths like "-Users-tongwu-Downloads" decode
26
+ // to basename "Downloads", which without filtering becomes a phantom project.
27
+ // ---------------------------------------------------------------------------
28
+ const SYSTEM_DIR_DENYLIST = new Set([
29
+ // Standard macOS home directories
30
+ "Downloads", "Documents", "Desktop", "Library", "Applications",
31
+ "Movies", "Music", "Pictures", "Public", "Sites",
32
+ // Common code-root containers (containers, not actual projects)
33
+ "Projects", "Code", "Codebases", "Repos", "GitHub", "Repositories",
34
+ "Source", "Sources", "src", "work", "Work", "dev", "Dev",
35
+ // Build / vendor / cache directories
36
+ "node_modules", "dist", "build", ".next", ".turbo", ".cache",
37
+ "tmp", "temp", ".tmp",
38
+ // Tool / IDE / agent directories
39
+ "claude", "Claude", ".cursor", ".vscode", ".idea", ".git",
40
+ ]);
41
+ function isSystemDir(name) {
42
+ if (!name)
43
+ return true;
44
+ if (name.length < 2)
45
+ return true;
46
+ if (name.startsWith("."))
47
+ return true; // dotfiles / hidden
48
+ if (name.includes("paperclip-instances"))
49
+ return true; // UUID-suffixed pattern
50
+ if (/^[0-9a-f-]{20,}$/i.test(name))
51
+ return true; // bare UUIDs
52
+ return SYSTEM_DIR_DENYLIST.has(name);
53
+ }
54
+ /**
55
+ * Strip prompt-injection patterns from imported user content before writing it
56
+ * to palace. CLAUDE.md and AutoMemory files frequently contain
57
+ * `<system-reminder>` markers etc. that, once in palace, would surface to future
58
+ * agents as if they were system instructions.
59
+ */
60
+ function scrubPromptInjection(s) {
61
+ return s
62
+ .replace(/<\/?\s*(system[-_]?(reminder|prompt|message|instruction)|important|critical)\b[^>]*>/gi, "[stripped tag]")
63
+ .replace(/<\|im_(start|end)\|>/gi, "[stripped]")
64
+ .replace(/\b(ignore|disregard|forget)\s+(all\s+)?(previous|prior|above)\s+(instructions?|prompts?|messages?)/gi, "[stripped injection attempt]")
65
+ .replace(/[‪-‮⁦-⁩]/g, "") // bidi override
66
+ .replace(/\0/g, "");
67
+ }
68
+ // ---------------------------------------------------------------------------
24
69
  // Constants
25
70
  // ---------------------------------------------------------------------------
26
71
  const DEFAULT_SCAN_DIRS = [
@@ -289,7 +334,14 @@ export async function bootstrapScan(options) {
289
334
  const pkgInfo = readPackageInfo(repoDir);
290
335
  const remoteName = remoteUrl ? path.basename(remoteUrl, ".git") : "";
291
336
  const name = pkgInfo.name ?? (remoteName || path.basename(repoDir));
292
- const slug = toSlug(name);
337
+ // Skip if this resolved to a system / container directory.
338
+ // Throw a sentinel — Promise.allSettled will reject this one;
339
+ // downstream `.filter(r => r.status === "fulfilled")` drops it.
340
+ if (isSystemDir(name)) {
341
+ throw new Error(`SKIP_SYSTEM_DIR:${name}`);
342
+ }
343
+ // Hardened slug — same grammar as paths.ts (no dots, no traversal).
344
+ const slug = sanitizeProject(toSlug(name));
293
345
  const language = detectLanguage(repoDir);
294
346
  const lastActivity = lastCommitIso || undefined;
295
347
  const description = pkgInfo.description ?? readReadmeDescription(repoDir);
@@ -395,7 +447,12 @@ export async function bootstrapScan(options) {
395
447
  // Decode encoded path: "-Users-tongwu-Projects-myapp" → last segment
396
448
  const decoded = encodedName.replace(/^-/, "").replace(/-/g, "/");
397
449
  const projectName = path.basename(decoded) || encodedName;
398
- const slug = toSlug(projectName);
450
+ // SKIP system/parent/cache dirs — AutoMemory may have indexed
451
+ // things like ~/Downloads or ~/Projects; those aren't real projects.
452
+ if (isSystemDir(projectName))
453
+ continue;
454
+ // Hardened slug — matches paths.ts sanitizer (no dots, no path chars).
455
+ const slug = sanitizeProject(toSlug(projectName));
399
456
  // List .md files in memory/ (skip > 5KB, skip secrets)
400
457
  let mdFiles = [];
401
458
  try {
@@ -624,7 +681,10 @@ export async function bootstrapImport(scan, selection) {
624
681
  continue;
625
682
  }
626
683
  const raw = fs.readFileSync(item.source_path, "utf-8");
627
- const claudemdContent = raw.slice(0, 3000);
684
+ // Scrub prompt-injection patterns before importing user-controlled
685
+ // content into palace. CLAUDE.md often contains <system-reminder>
686
+ // tags etc. that would surface to future agents as if real.
687
+ const claudemdContent = scrubPromptInjection(raw.slice(0, 3000));
628
688
  await palaceWrite({
629
689
  room: "architecture",
630
690
  topic: "project-conventions",
@@ -649,7 +709,9 @@ export async function bootstrapImport(scan, selection) {
649
709
  continue;
650
710
  }
651
711
  const rawContent = fs.readFileSync(item.source_path, "utf-8");
652
- const { body, meta } = stripFrontmatter(rawContent);
712
+ const { body: rawBody, meta } = stripFrontmatter(rawContent);
713
+ // Scrub prompt-injection patterns before storing imported content.
714
+ const body = scrubPromptInjection(rawBody);
653
715
  const rawTopic = (meta["name"] ?? item.id.replace("claude-memory:", "")).replace(/\.md$/, "");
654
716
  const topic = rawTopic.replace(/[^a-zA-Z0-9_\-]/g, "-");
655
717
  if (meta["type"] === "user") {
@@ -727,7 +789,8 @@ export async function bootstrapImport(scan, selection) {
727
789
  continue;
728
790
  }
729
791
  const rawContent = fs.readFileSync(item.source_path, "utf-8");
730
- const { body, meta } = stripFrontmatter(rawContent);
792
+ const { body: rawBody, meta } = stripFrontmatter(rawContent);
793
+ const body = scrubPromptInjection(rawBody);
731
794
  const rawTopic2 = (meta["name"] ?? item.id.replace("global:", "")).replace(/\.md$/, "");
732
795
  const topic = rawTopic2.replace(/[^a-zA-Z0-9_\-]/g, "-");
733
796
  if (meta["type"] === "user") {