hippo-memory 1.24.0 → 1.24.1

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/src/cli.js CHANGED
@@ -34,6 +34,7 @@ import { execFileSync, execSync, spawn } from 'child_process';
34
34
  import { installJsonHooks, uninstallJsonHooks, resolveJsonHookPaths, detectInstalledTools, defaultSleepLogPath, ensureCodexWrapperInstalled, installCodexWrapper, uninstallCodexWrapper, resolveCodexSessionTranscript, resolveCodexWrapperPaths, installOpencodePlugin, uninstallOpencodePlugin, resolveOpencodePluginPath, } from './hooks.js';
35
35
  import { createMemory, calculateStrength, calculateRewardFactor, deriveHalfLife, resolveConfidence, computeSchemaFit, Layer, } from './memory.js';
36
36
  import { resolveProjectIdentity } from './project-identity.js';
37
+ import { detectSecret } from './secret-detect.js';
37
38
  import { getHippoRoot, isInitialized, initStore, writeEntry, readEntry, deleteEntry, loadAllEntries, loadSearchEntries, loadIndex, saveIndex, loadStats, updateStats, saveActiveTaskSnapshot, loadActiveTaskSnapshot, clearActiveTaskSnapshot, appendSessionEvent, listSessionEvents, listMemoryConflicts, resolveConflict, saveSessionHandoff, loadLatestHandoff, loadHandoffById, RECALL_DEFAULT_DENY_SCOPES, } from './store.js';
38
39
  import { markRetrieved, hybridSearch, physicsSearch, explainMatch, textOverlap } from './search.js';
39
40
  import { renderTraceContent, parseSteps } from './trace.js';
@@ -2224,8 +2225,8 @@ async function cmdRefine(hippoRoot, flags) {
2224
2225
  * Scan for Claude Code MEMORY.md files and import new entries into hippo.
2225
2226
  * Looks in ~/.claude/projects/<project>/memory/ for .md files with YAML frontmatter.
2226
2227
  */
2227
- function learnFromMemoryMd(hippoRoot) {
2228
- const home = os.homedir();
2228
+ export function learnFromMemoryMd(hippoRoot, homeDir = os.homedir()) {
2229
+ const home = homeDir;
2229
2230
  const memoryDirs = [];
2230
2231
  // Claude Code project memories
2231
2232
  const claudeProjectsDir = path.join(home, '.claude', 'projects');
@@ -2243,6 +2244,7 @@ function learnFromMemoryMd(hippoRoot) {
2243
2244
  return 0;
2244
2245
  const existing = loadAllEntries(hippoRoot);
2245
2246
  let imported = 0;
2247
+ let skippedSecret = 0;
2246
2248
  for (const memDir of memoryDirs) {
2247
2249
  try {
2248
2250
  const files = fs.readdirSync(memDir).filter(f => f.endsWith('.md') && f !== 'MEMORY.md');
@@ -2257,6 +2259,15 @@ function learnFromMemoryMd(hippoRoot) {
2257
2259
  continue;
2258
2260
  // Truncate to reasonable size
2259
2261
  const content = body.length > 1500 ? body.slice(0, 1500) + ' [truncated]' : body;
2262
+ // Never ingest secret-bearing memory files. Some Claude Code memory
2263
+ // files exist purely to hold a live credential (e.g. an API-key
2264
+ // reference). The scope-isolation secret veto (v1.24.0) gated
2265
+ // share/promote/sync/ambient but missed this import path, so a live
2266
+ // key could land in the store here. Veto it at ingest. (v1.24.1)
2267
+ if (detectSecret({ content, tags: ['claude-code-memory'] }).flagged) {
2268
+ skippedSecret++;
2269
+ continue;
2270
+ }
2260
2271
  // Dedup: check if substantially similar content already exists
2261
2272
  const isDup = existing.some(e => {
2262
2273
  const overlap = textOverlap(content.slice(0, 200), e.content.slice(0, 200));
@@ -2277,6 +2288,9 @@ function learnFromMemoryMd(hippoRoot) {
2277
2288
  }
2278
2289
  catch { /* skip broken dirs */ }
2279
2290
  }
2291
+ if (skippedSecret > 0) {
2292
+ console.log(`Skipped ${skippedSecret} secret-bearing memory file${skippedSecret === 1 ? '' : 's'} (not ingested).`);
2293
+ }
2280
2294
  return imported;
2281
2295
  }
2282
2296
  function cmdDedup(hippoRoot, flags) {