create-claude-cabinet 0.9.0 → 0.10.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/lib/cli.js CHANGED
@@ -103,7 +103,7 @@ const MODULES = {
103
103
  default: true,
104
104
  lean: false,
105
105
  needsOmega: true,
106
- templates: ['skills/memory', 'hooks/memory-session-start.sh', 'hooks/memory-post-compact.sh', 'scripts/cabinet-memory-adapter.py', 'rules/memory-capture.md'],
106
+ templates: ['skills/memory', 'scripts/cabinet-memory-adapter.py', 'rules/memory-capture.md'],
107
107
  },
108
108
  };
109
109
 
@@ -558,8 +558,7 @@ async function run() {
558
558
 
559
559
  // --- Merge hooks into settings.json ---
560
560
  if (selectedModules.includes('hooks') && !flags.dryRun) {
561
- const includeMemory = selectedModules.includes('memory');
562
- const settingsPath = mergeSettings(projectDir, { includeDb, includeMemory });
561
+ const settingsPath = mergeSettings(projectDir, { includeDb });
563
562
  console.log(` ⚙️ Merged hooks into ${path.relative(projectDir, settingsPath)}`);
564
563
  }
565
564
 
package/lib/copy.js CHANGED
@@ -75,6 +75,7 @@ async function walkAndCopy(srcRoot, destRoot, currentSrc, results, dryRun, skipC
75
75
  if (!dryRun) fs.copyFileSync(srcPath, destPath);
76
76
  results.overwritten.push(relPath);
77
77
  results.manifest[relPath] = incomingHash;
78
+ console.log(` Updated: ${displayPath}`);
78
79
  } else {
79
80
  results.skipped.push(relPath);
80
81
  // Record the hash of what's actually on disk, not the template —
@@ -106,6 +106,21 @@ function setupOmega() {
106
106
  try {
107
107
  execSync(`"${VENV_PYTHON}" -c "import omega"`, { stdio: 'pipe' });
108
108
  results.push('Existing omega venv is valid');
109
+ // Ensure cross-encoder model is downloaded (added in v0.9.1)
110
+ try {
111
+ const hasReranker = execSync(
112
+ `"${VENV_PYTHON}" -c "from omega.reranker import _get_model_dir; print('yes' if _get_model_dir() else 'no')"`,
113
+ { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
114
+ ).trim();
115
+ if (hasReranker === 'no') {
116
+ console.log(' Downloading cross-encoder model...');
117
+ execSync(`"${VENV_PYTHON}" -c "from omega.reranker import download_model; download_model()"`, {
118
+ stdio: 'pipe',
119
+ timeout: 120000,
120
+ });
121
+ results.push('Downloaded cross-encoder reranker model');
122
+ }
123
+ } catch { /* non-fatal */ }
109
124
  return results;
110
125
  } catch {
111
126
  // Venv is broken — nuke and rebuild (D5)
@@ -135,6 +150,35 @@ function setupOmega() {
135
150
  });
136
151
  results.push('Downloaded ONNX embedding model (bge-small-en-v1.5)');
137
152
 
153
+ // 6. Download cross-encoder reranker model (improves query result ranking)
154
+ console.log(' Downloading cross-encoder model...');
155
+ try {
156
+ execSync(`"${VENV_PYTHON}" -c "from omega.reranker import download_model; download_model()"`, {
157
+ stdio: 'pipe',
158
+ timeout: 120000,
159
+ });
160
+ results.push('Downloaded cross-encoder reranker model');
161
+ } catch {
162
+ // Non-fatal — queries work without it, just less accurate ranking
163
+ results.push('Cross-encoder model download skipped (optional)');
164
+ }
165
+
166
+ // 7. Configure omega native hooks in global settings
167
+ // Omega hooks live in ~/.claude/settings.json (global) — they run for all
168
+ // projects and handle memory capture/recall natively. This is idempotent:
169
+ // omega checks if hooks already exist before adding them.
170
+ console.log(' Configuring omega hooks...');
171
+ try {
172
+ execSync(`"${VENV_PYTHON}" -m omega.cli hooks setup`, {
173
+ stdio: 'pipe',
174
+ timeout: 30000,
175
+ });
176
+ results.push('Configured omega native hooks (global settings)');
177
+ } catch {
178
+ // Non-fatal — hooks can be set up manually with `omega hooks setup`
179
+ results.push('Omega hooks setup skipped (run `omega hooks setup` manually)');
180
+ }
181
+
138
182
  return results;
139
183
  }
140
184
 
@@ -1,31 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
- const MEMORY_HOOKS = {
5
- SessionStart: [
6
- {
7
- matcher: 'startup|resume|compact',
8
- hooks: [
9
- {
10
- type: 'command',
11
- command: '.claude/hooks/memory-session-start.sh',
12
- },
13
- ],
14
- },
15
- ],
16
- PostCompact: [
17
- {
18
- matcher: '',
19
- hooks: [
20
- {
21
- type: 'command',
22
- command: '.claude/hooks/memory-post-compact.sh',
23
- },
24
- ],
25
- },
26
- ],
27
- };
28
-
29
4
  const DEFAULT_HOOKS = {
30
5
  PreToolUse: [
31
6
  {
@@ -75,7 +50,7 @@ const DEFAULT_HOOKS = {
75
50
  * Merge PIB hooks into the project's .claude/settings.json.
76
51
  * Creates the file if it doesn't exist. Preserves existing hooks.
77
52
  */
78
- function mergeSettings(projectDir, { includeDb = true, includeMemory = false } = {}) {
53
+ function mergeSettings(projectDir, { includeDb = true } = {}) {
79
54
  const settingsDir = path.join(projectDir, '.claude');
80
55
  const settingsPath = path.join(settingsDir, 'settings.json');
81
56
 
@@ -90,16 +65,24 @@ function mergeSettings(projectDir, { includeDb = true, includeMemory = false } =
90
65
 
91
66
  if (!settings.hooks) settings.hooks = {};
92
67
 
93
- // Build the complete hook set for this install
94
- const allHooks = { ...DEFAULT_HOOKS };
95
- if (includeMemory) {
96
- for (const [event, hooks] of Object.entries(MEMORY_HOOKS)) {
97
- allHooks[event] = [...(allHooks[event] || []), ...hooks];
98
- }
68
+ // Remove legacy CC memory hooks (v0.9.x and earlier).
69
+ // These are now handled by omega's native hooks in global settings.
70
+ const LEGACY_MEMORY_COMMANDS = [
71
+ 'memory-session-start.sh',
72
+ 'memory-post-compact.sh',
73
+ ];
74
+ for (const [event, entries] of Object.entries(settings.hooks)) {
75
+ if (!Array.isArray(entries)) continue;
76
+ settings.hooks[event] = entries.filter(entry => {
77
+ if (!entry.hooks || !Array.isArray(entry.hooks)) return true;
78
+ return !entry.hooks.some(h =>
79
+ LEGACY_MEMORY_COMMANDS.some(cmd => (h.command || '').includes(cmd))
80
+ );
81
+ });
99
82
  }
100
83
 
101
84
  // Merge each hook event type
102
- for (const [event, newHooks] of Object.entries(allHooks)) {
85
+ for (const [event, newHooks] of Object.entries(DEFAULT_HOOKS)) {
103
86
  if (!settings.hooks[event]) {
104
87
  settings.hooks[event] = newHooks;
105
88
  } else {
@@ -123,4 +106,4 @@ function mergeSettings(projectDir, { includeDb = true, includeMemory = false } =
123
106
  return settingsPath;
124
107
  }
125
108
 
126
- module.exports = { mergeSettings, DEFAULT_HOOKS, MEMORY_HOOKS };
109
+ module.exports = { mergeSettings, DEFAULT_HOOKS };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-cabinet",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Claude Cabinet — opinionated process scaffolding for Claude Code projects",
5
5
  "bin": {
6
6
  "create-claude-cabinet": "bin/create-claude-cabinet.js"
@@ -1,43 +1,42 @@
1
1
  # Memory Capture Rules
2
2
 
3
- When omega memory is active (check: `~/.claude-cabinet/omega-venv/bin/python3`
4
- exists and `scripts/cabinet-memory-adapter.py` exists), these rules govern
5
- what gets captured and when.
3
+ When omega memory is active (check: `omega hooks doctor` reports OK),
4
+ these rules govern what gets captured and when.
6
5
 
7
- ## During Sessions — What to Capture
6
+ ## How Capture Works
8
7
 
9
- Capture to omega when you observe any of these during a session:
8
+ Omega handles memory capture natively through its hooks in
9
+ `~/.claude/settings.json` (global). No project-level hook scripts needed.
10
10
 
11
- **Decisions with reasoning.** When the user makes a non-obvious choice
12
- (architecture, naming, tradeoffs, tool selection), capture the decision
13
- AND the reasoning. "Chose SQLite over Postgres because single-user,
14
- no server dependency"not just "uses SQLite."
11
+ **Automatic capture (omega native hooks):**
12
+ - `auto_capture` (UserPromptSubmit) detects decisions/lessons from user messages in real time
13
+ - `assistant_capture` (Stop) extracts insights from assistant responses at session end
14
+ - `session_stop` (Stop)session summary, activity report, auto-reflection
15
+ - `surface_memories` (PostToolUse) — surfaces relevant memories before file edits
15
16
 
16
- **Discovered constraints.** When something that seemed possible turns
17
- out to have a limitation, gotcha, or prerequisite. "Python venv on
18
- Debian requires separate python3-venv package" the kind of thing
19
- that wastes 30 minutes if you don't know it.
17
+ **Manual capture (adapter or omega MCP tools):**
18
+ - Use `omega_store()` MCP tool directly, or
19
+ - Use the adapter for project-scoped storage:
20
+ ```bash
21
+ echo '{"text": "the memory", "type": "decision"}' | \
22
+ ~/.claude-cabinet/omega-venv/bin/python3 scripts/cabinet-memory-adapter.py store
23
+ ```
20
24
 
21
- **User preferences revealed through correction.** When the user says
22
- "no, not like that" or redirects your approach, capture what they
23
- actually want. "User prefers single bundled PRs for refactors, not
24
- many small ones."
25
+ **Memory types:** `decision`, `lesson_learned`, `user_preference`, `constraint`, `error_pattern`
25
26
 
26
- **Pattern establishment.** When a convention is established for the
27
- first time — naming pattern, file organization, workflow step. Not
28
- the convention itself (that's in the code), but that it was a
29
- deliberate choice.
27
+ ## What to Capture Manually
30
28
 
31
- ## How to Capture
29
+ Omega's auto_capture hook catches many decisions and lessons from
30
+ conversation flow. Manual capture is for things the hooks miss:
32
31
 
33
- Use the adapter never call omega directly from shell:
32
+ **Decisions with reasoning.** Non-obvious architectural choices where
33
+ the "why" matters as much as the "what."
34
34
 
35
- ```bash
36
- echo '{"text": "the memory", "type": "decision"}' | \
37
- ~/.claude-cabinet/omega-venv/bin/python3 scripts/cabinet-memory-adapter.py store
38
- ```
35
+ **Discovered constraints.** Limitations or gotchas that waste time
36
+ if you don't know them in advance.
39
37
 
40
- Memory types: `decision`, `lesson`, `preference`, `constraint`, `pattern`
38
+ **User preferences revealed through correction.** When the user
39
+ redirects your approach — capture what they actually want.
41
40
 
42
41
  ## What NOT to Capture
43
42
 
@@ -49,17 +48,11 @@ Memory types: `decision`, `lesson`, `preference`, `constraint`, `pattern`
49
48
 
50
49
  ## Capture Cadence
51
50
 
52
- Do NOT capture after every interaction. Capture when something worth
53
- remembering actually happens. Most messages in a session produce nothing
54
- worth storing.
55
-
56
- Cadence scales with session length and discovery density. A short
57
- focused session might produce 0-1 memories. A long session with
58
- multiple discoveries, corrections, and decisions could produce 5-10+.
59
- The right number is however many genuinely worth-remembering things
60
- happened — no artificial cap.
51
+ Omega's native hooks handle most capture automatically. Manual capture
52
+ should be rare only when something important happened that the hooks
53
+ wouldn't detect (e.g., a nuanced architectural decision discussed
54
+ verbally, or a constraint discovered through external research).
61
55
 
62
56
  Over-capturing degrades retrieval quality. The test: *"Would a future
63
57
  session benefit from knowing this?"* If yes, capture it. If it's just
64
- noise or ephemera, skip it. The debrief sweep catches anything
65
- important that was missed during the session.
58
+ noise or ephemera, skip it.
@@ -1,21 +1,23 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- Cabinet Memory Adapter — single Python file wrapping all omega interaction.
3
+ Cabinet Memory Adapter — single Python file wrapping omega interaction.
4
4
 
5
- Called by hook scripts via the venv Python. All omega calls go through here.
5
+ Called by skills and scripts via the venv Python. Provides project-scoped
6
+ tiered retrieval (omega's main gap) and a stable JSON-in/JSON-out interface.
6
7
  Designed for D2 (never block Claude Code) and D3 (graceful degradation).
7
8
 
9
+ Note: Session-level hooks (welcome, capture, session start/stop) are handled
10
+ by omega's native hooks configured in ~/.claude/settings.json (global).
11
+ This adapter handles skill-invoked operations only.
12
+
8
13
  Usage:
9
14
  cabinet-memory-adapter.py <command> [options]
10
15
 
11
16
  Commands:
12
- welcome Surface relevant memories for session start
13
- capture Store a memory from hook input (PostCompact)
14
- store Store a memory directly (called by debrief)
15
- query Query memories by text
17
+ store Store a memory directly (called by debrief, /memory)
18
+ query Query memories by text (with project-scoped tiering)
16
19
  delete Delete a memory by full node_id
17
20
  list List all memories with full node_ids
18
- status Check omega health
19
21
 
20
22
  All commands read JSON from stdin when applicable.
21
23
  All commands output JSON to stdout.
@@ -59,87 +61,15 @@ def _import_omega():
59
61
  return None
60
62
 
61
63
 
62
- def cmd_welcome():
63
- """Surface relevant memories for session start.
64
-
65
- Reads session context from stdin (session_id, cwd, source).
66
- Calls omega.welcome() to get relevant memories.
67
- Outputs memories as context text for SessionStart hook stdout.
68
- """
69
- data = _read_stdin()
70
- omega = _import_omega()
71
- if not omega:
72
- _error("omega not available")
73
- return
74
-
75
- try:
76
- cwd = data.get("cwd", os.getcwd())
77
- project_name = os.path.basename(cwd)
78
-
79
- result = omega.welcome(project=project_name)
80
- if not result:
81
- _output({"ok": True, "context": ""})
82
- return
83
-
84
- # welcome() returns a dict with memory count, recent memories, etc.
85
- if isinstance(result, dict):
86
- context = (
87
- result.get("observation_prefix", "")
88
- or result.get("summary", "")
89
- or result.get("context", "")
90
- )
91
- if not context and result.get("memory_count", 0) == 0:
92
- _output({"ok": True, "context": ""})
93
- return
94
- if not context:
95
- context = json.dumps(result, indent=2)
96
- _output({"ok": True, "context": context})
97
- elif isinstance(result, str):
98
- _output({"ok": True, "context": result})
99
- else:
100
- _output({"ok": True, "context": str(result)})
101
- except Exception as e:
102
- _error(f"welcome failed: {e}")
103
-
104
-
105
- def cmd_capture():
106
- """Capture context from PostCompact summary.
107
-
108
- Reads compact_summary from stdin.
109
- Extracts key decisions, lessons, and reasoning chains.
110
- Stores them in omega.
111
- """
112
- data = _read_stdin()
113
- omega = _import_omega()
114
- if not omega:
115
- _error("omega not available")
116
- return
117
-
118
- summary = data.get("compact_summary", "")
119
- if not summary:
120
- _output({"ok": True, "stored": 0, "reason": "no summary"})
121
- return
122
-
123
- session_id = data.get("session_id", "unknown")
124
- cwd = data.get("cwd", os.getcwd())
125
- project_name = os.path.basename(cwd)
126
-
127
- try:
128
- result = omega.auto_capture(
129
- summary,
130
- event_type="compaction",
131
- session_id=session_id,
132
- project=project_name,
133
- )
134
- count = 0
135
- if isinstance(result, dict):
136
- count = result.get("stored", 0)
137
- elif isinstance(result, (list, tuple)):
138
- count = len(result)
139
-
140
- _output({"ok": True, "stored": count})
141
- except Exception as e:
142
- _error(f"capture failed: {e}")
64
+ # Map friendly type names to omega's native event_type values.
65
+ # This ensures permanent TTL for types that should never expire.
66
+ _TYPE_MAP = {
67
+ "lesson": "lesson_learned",
68
+ "preference": "user_preference",
69
+ "error": "error_pattern",
70
+ # These already match omega's native types:
71
+ # "decision", "constraint", "error_pattern", "lesson_learned", "user_preference"
72
+ }
143
73
 
144
74
 
145
75
  def cmd_store():
@@ -147,7 +77,9 @@ def cmd_store():
147
77
 
148
78
  Reads JSON from stdin with fields:
149
79
  text: the memory content (required)
150
- type: event_type for omega (default: "lesson")
80
+ type: event_type for omega (default: "lesson_learned")
81
+ Accepts friendly names: lesson, preference, error
82
+ which are mapped to omega native types.
151
83
  tags: list of tags (stored in metadata, optional)
152
84
  project: project name (default: basename of cwd)
153
85
  """
@@ -163,7 +95,8 @@ def cmd_store():
163
95
  return
164
96
 
165
97
  try:
166
- event_type = data.get("type", "lesson")
98
+ raw_type = data.get("type", "lesson")
99
+ event_type = _TYPE_MAP.get(raw_type, raw_type)
167
100
  project = data.get("project", os.path.basename(os.getcwd()))
168
101
  metadata = {}
169
102
  if data.get("tags"):
@@ -335,23 +268,6 @@ def cmd_query():
335
268
  _error(f"query failed: {e}")
336
269
 
337
270
 
338
- def cmd_status():
339
- """Check omega health status."""
340
- omega = _import_omega()
341
- if not omega:
342
- _output({"ok": False, "status": "omega not available"})
343
- return
344
-
345
- try:
346
- result = omega.status()
347
- if isinstance(result, dict):
348
- _output({"ok": True, **result})
349
- else:
350
- _output({"ok": True, "status": str(result)})
351
- except Exception as e:
352
- _error(f"status failed: {e}")
353
-
354
-
355
271
  def cmd_delete():
356
272
  """Delete a memory by its full node_id.
357
273
 
@@ -433,13 +349,10 @@ def cmd_list():
433
349
 
434
350
 
435
351
  COMMANDS = {
436
- "welcome": cmd_welcome,
437
- "capture": cmd_capture,
438
352
  "store": cmd_store,
439
353
  "query": cmd_query,
440
354
  "delete": cmd_delete,
441
355
  "list": cmd_list,
442
- "status": cmd_status,
443
356
  }
444
357
 
445
358
  if __name__ == "__main__":
@@ -397,17 +397,16 @@ If the memory module is installed (check `.ccrc.json` modules list for
397
397
  A broken venv means all memory hooks silently degrade.
398
398
 
399
399
  - **Adapter availability.** Does `scripts/cabinet-memory-adapter.py`
400
- exist in the project? Without it, hooks have nothing to call.
400
+ exist in the project? Skills use it for project-scoped queries.
401
401
 
402
- - **Hook registration.** Check `.claude/settings.json` for:
403
- - `memory-session-start.sh` in `SessionStart` hooks
404
- - `memory-post-compact.sh` in `PostCompact` hooks
405
- Missing hooks mean omega was installed but never wired in.
402
+ - **Hook registration.** Check `~/.claude/settings.json` (global) for
403
+ omega native hooks (`fast_hook.py session_start`, etc.). Run
404
+ `omega hooks doctor` to verify. Missing hooks mean omega was installed
405
+ but `omega hooks setup` was never run.
406
406
 
407
- - **Omega database.** Run the adapter's `status` command:
407
+ - **Omega database.** Run `omega status` to check health:
408
408
  ```bash
409
- echo '{}' | ~/.claude-cabinet/omega-venv/bin/python3 \
410
- scripts/cabinet-memory-adapter.py status
409
+ ~/.claude-cabinet/omega-venv/bin/omega status
411
410
  ```
412
411
  Check: is the database growing? Zero memories after multiple sessions
413
412
  suggests capture isn't working.
@@ -105,6 +105,28 @@ to help you do your job.
105
105
  Omega data lives at `~/.omega/omega.db` (SQLite). The `/memory` skill
106
106
  gives users self-serve access to browse, search, and manage memories.
107
107
 
108
+ **Graph traversal** (follow connections from a memory):
109
+ ```bash
110
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
111
+ from omega import traverse
112
+ result = traverse('MEM_ID', max_hops=2)
113
+ print(result)
114
+ "
115
+ ```
116
+ After finding a relevant memory, traverse its graph connections to
117
+ discover related decisions, contradictions, or how understanding evolved.
118
+ Edge types: `related`, `evolution`, `contradicts`, `temporal_cluster`.
119
+
120
+ **Contradiction detection** (find conflicting memories):
121
+ ```bash
122
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
123
+ from omega import SQLiteStore
124
+ s = SQLiteStore()
125
+ edges = s.get_edges_by_type('contradicts')
126
+ for e in edges: print(f\"{e['source_id']} <-> {e['target_id']} ({e['weight']:.2f})\")
127
+ "
128
+ ```
129
+
108
130
  Omega returns memories ranked by relevance. This is the richest source
109
131
  of institutional memory when available. If omega queries return nothing
110
132
  or fail, fall through to source 1 (flat memory files).
@@ -190,10 +212,10 @@ what was about to happen next. This is the historian's moment.
190
212
  in a session should survive compaction because it's been written
191
213
  down *during* the session, not just summarized after truncation.
192
214
 
193
- **Omega and compaction:** If omega memory is active, the PostCompact
194
- hook (`memory-post-compact.sh`) automatically captures key context from
195
- the compaction summary. After compaction, query omega to see what was
196
- preserved:
215
+ **Omega and compaction:** If omega memory is active, omega's native hooks
216
+ automatically capture key context at session boundaries (session_stop,
217
+ auto_capture, assistant_capture). After compaction, query omega to see
218
+ what was preserved:
197
219
 
198
220
  ```bash
199
221
  echo '{"text": "session context before compaction", "limit": 5}' | \
@@ -229,11 +251,64 @@ You are responsible for the health of the memory system:
229
251
  they can be catalogued — if the team keeps re-deriving solutions, if
230
252
  memory files are growing too large to scan, if conversation history
231
253
  search isn't surfacing what it should — advocate for better tooling.
232
- This might mean:
233
- - A new skill for structured lesson capture
234
- - Better memory file organization (by domain, by date, by type)
235
- - Improving search strategies or adding new query patterns
236
- - A periodic "memory review" to prune, consolidate, and re-index
254
+
255
+ ### Memory Health Measurement
256
+
257
+ When activated during audit or review, evaluate omega memory health:
258
+
259
+ **Growth & Coverage:**
260
+ ```bash
261
+ ~/.claude-cabinet/omega-venv/bin/omega stats --json 2>&1
262
+ ```
263
+ Check: Is the memory count growing session over session? Are all
264
+ permanent types represented (decision, lesson_learned, user_preference,
265
+ constraint, error_pattern)? Gaps suggest capture isn't working for
266
+ certain categories.
267
+
268
+ **Graph Connectivity:**
269
+ ```bash
270
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
271
+ from omega import SQLiteStore
272
+ s = SQLiteStore()
273
+ import sqlite3
274
+ conn = sqlite3.connect(s.db_path)
275
+ total = conn.execute('SELECT COUNT(*) FROM memories').fetchone()[0]
276
+ edges = s.edge_count()
277
+ connected = conn.execute('SELECT COUNT(DISTINCT source_id) + COUNT(DISTINCT target_id) FROM memory_relationships').fetchone()[0]
278
+ print(f'Memories: {total}, Edges: {edges}, Connected: {connected}/{total} ({100*connected//max(total,1)}%)')
279
+ "
280
+ ```
281
+ Target: >50% of memories should participate in at least one edge.
282
+ Below 30% means discover_connections isn't running or memories are
283
+ too diverse to auto-relate.
284
+
285
+ **Contradiction Health:**
286
+ ```bash
287
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
288
+ from omega import SQLiteStore
289
+ s = SQLiteStore()
290
+ contradictions = s.get_edges_by_type('contradicts')
291
+ print(f'{len(contradictions)} contradiction(s) detected')
292
+ for c in contradictions:
293
+ print(f' {c[\"source_id\"]} <-> {c[\"target_id\"]} (confidence: {c[\"weight\"]:.2f})')
294
+ "
295
+ ```
296
+ Unresolved contradictions are technical debt in the knowledge graph.
297
+ Surface them and recommend resolution.
298
+
299
+ **Consolidation Effectiveness:**
300
+ ```bash
301
+ ~/.claude-cabinet/omega-venv/bin/omega consolidate --prune-days 30 2>&1
302
+ ```
303
+ Check: Are duplicates accumulating? Are zero-access memories growing?
304
+ If consolidation consistently prunes many entries, capture quality
305
+ may need improvement (storing noise instead of signal).
306
+
307
+ **Retrieval Quality (spot check):**
308
+ Pick 2-3 recent decisions or lessons from the session. Query omega
309
+ for each one. Does the query return the correct memory in the top 3
310
+ results? If not, embeddings may be degraded or the memory text may
311
+ be too generic to differentiate.
237
312
 
238
313
  ## Output Format
239
314
 
@@ -129,6 +129,35 @@ the upstream guard hook because it runs as a separate process using
129
129
  the filesystem directly. This is by design — the installer is the
130
130
  authorized update path for manifest-tracked files.
131
131
 
132
+ ### 2.4. Memory Hook Migration (v0.9.x → v0.10+)
133
+
134
+ **This step runs when upgrading from v0.9.x or earlier** (detected by
135
+ the presence of `memory-session-start.sh` or `memory-post-compact.sh`
136
+ in `.claude/settings.json`).
137
+
138
+ Starting in v0.10, omega's native hooks handle memory capture/recall
139
+ directly (configured in global `~/.claude/settings.json`). The old
140
+ project-level CC memory hooks are now redundant and cause double
141
+ context injection if left in place.
142
+
143
+ **Check and clean:**
144
+ 1. Read `.claude/settings.json` — look for `memory-session-start.sh`
145
+ in `SessionStart` hooks and `memory-post-compact.sh` in `PostCompact`
146
+ 2. If found, remove those entries. Keep other hooks (git-guardrails,
147
+ cc-upstream-guard, telemetry) untouched.
148
+ 3. Verify omega native hooks are configured: run `omega hooks doctor`.
149
+ If not configured, the installer's omega-setup already ran
150
+ `omega hooks setup` — verify by checking `~/.claude/settings.json`
151
+ for `fast_hook.py` entries.
152
+ 4. The old shell scripts (`hooks/memory-session-start.sh`,
153
+ `hooks/memory-post-compact.sh`) can be deleted from the project's
154
+ `.claude/hooks/` directory — they're no longer called.
155
+
156
+ **Tell the user:** "Memory hooks have been upgraded to omega native.
157
+ You now get 3 additional capabilities: real-time decision capture,
158
+ assistant insight extraction, and relevant memory surfacing before
159
+ file edits."
160
+
132
161
  ### 2.5. Legacy Detection and Migration
133
162
 
134
163
  **This step runs ONLY when upgrading from v0.5.x or earlier** (detected
@@ -116,9 +116,44 @@ Read `phases/close-work.md` for how to match session work against open
116
116
  items and close them. This includes marking tasks as done, resolving
117
117
  feedback, and updating any tracking system.
118
118
 
119
- **Skip (absent/empty).** The debrief can still inventory and record
120
- lessons, but work items won't be closed they'll appear as open in
121
- the next orient, creating stale state.
119
+ **Default (absent/empty):** Match the session's work against open items
120
+ in pib-db and propose closing what was completed. If pib-db is not
121
+ initialized, skip gracefully.
122
+
123
+ 1. **Get session work:** `git log --oneline` for this session's commits
124
+ (since session start or last 2 hours)
125
+ 2. **Get open actions:**
126
+ ```bash
127
+ sqlite3 pib.db "SELECT fid, text, project_fid FROM actions WHERE completed = 0 AND deleted_at IS NULL ORDER BY flagged DESC, sort_order ASC"
128
+ ```
129
+ 3. **Match:** For each open action, check if the session's commits
130
+ address it (compare action text/notes against commit messages and
131
+ changed files)
132
+ 4. **Propose:** Present matched actions and ask the user to confirm
133
+ which to close
134
+ 5. **Close confirmed:**
135
+ ```bash
136
+ sqlite3 pib.db "UPDATE actions SET completed = 1, completed_at = date('now') WHERE fid = '<fid>'"
137
+ ```
138
+
139
+ **Project completion scan:** After closing actions, check for projects
140
+ where all actions are now done:
141
+
142
+ ```bash
143
+ sqlite3 pib.db "
144
+ SELECT p.fid, p.name,
145
+ (SELECT COUNT(*) FROM actions a WHERE a.project_fid = p.fid) as total,
146
+ (SELECT COUNT(*) FROM actions a WHERE a.project_fid = p.fid AND a.completed = 1) as done
147
+ FROM projects p
148
+ WHERE p.status = 'active'
149
+ AND p.deleted_at IS NULL
150
+ AND (SELECT COUNT(*) FROM actions a WHERE a.project_fid = p.fid) > 0
151
+ AND (SELECT COUNT(*) FROM actions a WHERE a.project_fid = p.fid AND a.completed = 0 AND a.deleted_at IS NULL) = 0
152
+ "
153
+ ```
154
+
155
+ For each result, propose completing the project (show name + action
156
+ count, confirm before closing).
122
157
 
123
158
  For each open item, determine:
124
159
  - **Clearly complete** — mark it done with a reference to what was built
@@ -377,7 +412,7 @@ Read `phases/report.md` for how to present the debrief summary.
377
412
  | Phase | Absent = | What it customizes |
378
413
  |-------|----------|-------------------|
379
414
  | `inventory.md` | Default: review git log + session | How to identify what was done |
380
- | `close-work.md` | Skip | How to close work items |
415
+ | `close-work.md` | Default: match pib-db actions against git log | How to close work items |
381
416
  | `auto-maintenance.md` | Skip | Recurring session-end tasks |
382
417
  | `update-state.md` | Default: check system-status.md | What state files to update |
383
418
  | `health-checks.md` | Skip | Session-end health checks |
@@ -61,6 +61,35 @@ Review the session and ask:
61
61
  - Anything already in CLAUDE.md files
62
62
  - Ephemeral task details only relevant to this session
63
63
 
64
+ ## After Storing — Link and Check
65
+
66
+ After storing each memory, omega auto-relates it to similar existing
67
+ memories. Surface this to the user:
68
+
69
+ ```bash
70
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
71
+ from omega import find_similar_memories
72
+ result = find_similar_memories('THE_NEW_MEMORY_ID')
73
+ print(result)
74
+ "
75
+ ```
76
+
77
+ If the new memory is similar to existing ones, mention it:
78
+ "This connects to your earlier memory about [topic]."
79
+
80
+ Also check for contradictions — if the new memory conflicts with an
81
+ existing one, ask the user which is correct:
82
+
83
+ ```bash
84
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
85
+ from omega import SQLiteStore
86
+ s = SQLiteStore()
87
+ edges = s.get_edges_by_type('contradicts')
88
+ for e in edges: print(f\"{e['source_id']} <-> {e['target_id']} ({e['weight']:.2f})\")
89
+ "
90
+ ```
91
+
64
92
  ## Report What Was Recorded
65
93
  Tell the user what memories were created or updated so they know what
66
- the system will remember next time. Include the count and types.
94
+ the system will remember next time. Include the count, types, and any
95
+ new connections discovered in the knowledge graph.
@@ -27,9 +27,11 @@ If not available, tell the user:
27
27
 
28
28
  ## Adapter Reference
29
29
 
30
- The adapter (`scripts/cabinet-memory-adapter.py`) is the single interface
31
- to omega. All commands read JSON from stdin, output JSON to stdout, and
32
- exit 0 even on failure. Always call it via the venv Python:
30
+ The adapter (`scripts/cabinet-memory-adapter.py`) provides project-scoped
31
+ queries and a stable JSON interface. Session-level capture and recall are
32
+ handled by omega's native hooks (configured globally). The adapter handles
33
+ skill-invoked operations. All commands read JSON from stdin, output JSON
34
+ to stdout, and exit 0 even on failure.
33
35
 
34
36
  ```bash
35
37
  echo '<json>' | ~/.claude-cabinet/omega-venv/bin/python3 scripts/cabinet-memory-adapter.py <command>
@@ -37,16 +39,13 @@ echo '<json>' | ~/.claude-cabinet/omega-venv/bin/python3 scripts/cabinet-memory-
37
39
 
38
40
  | Command | Input | Output |
39
41
  |---------|-------|--------|
40
- | `welcome` | `{}` or hook JSON | `{ok, context}` — relevant memories |
41
42
  | `store` | `{text, type, tags?, project?}` | `{ok, id}` — stored memory ID |
42
- | `query` | `{text, limit?, type?, project?, scope?}` | `{ok, results}` — semantic search |
43
+ | `query` | `{text, limit?, type?, project?, scope?}` | `{ok, results}` — semantic search with project scoping |
43
44
  | `delete` | `{id}` | `{ok, deleted}` — requires full node_id |
44
45
  | `list` | `{type?, project?, limit?}` | `{ok, memories, count}` — all memories with full IDs |
45
- | `capture` | hook JSON with `compact_summary` | `{ok, stored}` — auto-capture count |
46
- | `status` | `{}` | `{ok, ...health info}` |
47
46
 
48
- Memory types: `decision`, `lesson`, `preference`, `constraint`, `pattern`,
49
- `compaction`.
47
+ Memory types: `decision`, `lesson_learned`, `user_preference`, `constraint`,
48
+ `error_pattern`.
50
49
 
51
50
  ## Commands
52
51
 
@@ -83,6 +82,25 @@ Present results conversationally — highlight the most relevant matches,
83
82
  their types, and which project they came from when cross-project results
84
83
  appear.
85
84
 
85
+ **Graph enrichment:** For the top 1-2 results, check for related memories
86
+ via omega's graph traversal. This surfaces the knowledge network — not
87
+ just what matched, but what's connected to what matched:
88
+
89
+ ```bash
90
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
91
+ from omega import traverse
92
+ result = traverse('THE_MEMORY_ID', max_hops=2)
93
+ print(result)
94
+ "
95
+ ```
96
+
97
+ If traversal returns connected memories, present them as "Related:"
98
+ under the main result. Edge types tell the story:
99
+ - `related` — semantically similar
100
+ - `evolution` — this understanding has developed over time
101
+ - `contradicts` — conflicts with another memory (surface both sides)
102
+ - `temporal_cluster` — captured in the same session
103
+
86
104
  ### Remember — user wants to store something
87
105
 
88
106
  ```bash
@@ -91,13 +109,59 @@ echo '{"text": "what to remember", "type": "preference"}' | \
91
109
  ```
92
110
 
93
111
  Pick the type based on what the user said:
94
- - `decision` — they made a choice and want it recorded
95
- - `lesson` — they learned something
96
- - `preference` — they want something done a certain way
97
- - `constraint` — a limitation or prerequisite
98
- - `pattern` — a convention or recurring approach
112
+ - `decision` — they made a choice and want it recorded (permanent)
113
+ - `lesson` — they learned something (maps to `lesson_learned`, permanent)
114
+ - `preference` — they want something done a certain way (maps to `user_preference`, permanent)
115
+ - `constraint` — a limitation or prerequisite (permanent)
116
+ - `error` — a failure pattern to avoid (maps to `error_pattern`, permanent)
117
+
118
+ The adapter maps friendly names to omega's native types for correct TTL.
119
+
120
+ Confirm what was stored. After storing, check for similar existing memories
121
+ and link them if relevant:
122
+
123
+ ```bash
124
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
125
+ from omega import find_similar_memories
126
+ result = find_similar_memories('THE_NEW_MEMORY_ID')
127
+ print(result)
128
+ "
129
+ ```
130
+
131
+ If similar memories exist, tell the user: "This connects to N existing
132
+ memories about [topic]." Omega auto-relates on store, but surfacing it
133
+ builds user confidence that the knowledge graph is working.
134
+
135
+ ### Link — user wants to connect memories
136
+
137
+ If the user says "link these" or "these are related":
138
+
139
+ ```bash
140
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
141
+ from omega import SQLiteStore
142
+ s = SQLiteStore()
143
+ s.add_edge('MEM_ID_1', 'MEM_ID_2', edge_type='related', weight=1.0)
144
+ print('Linked')
145
+ "
146
+ ```
147
+
148
+ Edge types: `related`, `contradicts`, `supersedes`, `evolves`.
149
+
150
+ ### Contradictions — user asks what conflicts
151
+
152
+ ```bash
153
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
154
+ from omega import SQLiteStore
155
+ s = SQLiteStore()
156
+ edges = s.get_edges_by_type('contradicts')
157
+ for e in edges:
158
+ print(f\"{e['source_id']} <-> {e['target_id']} (confidence: {e['weight']:.2f})\")
159
+ if not edges: print('No contradictions found')
160
+ "
161
+ ```
99
162
 
100
- Confirm what was stored.
163
+ For each contradiction pair, query both memories to show the user what
164
+ conflicts. Ask which one is correct, then supersede the wrong one.
101
165
 
102
166
  ### Forget — user wants to remove something
103
167
 
@@ -171,7 +171,7 @@ Read `phases/work-tracking.md` for how to present work tracking options.
171
171
  tasks.md, GitHub Issues, custom phase files). Present two built-in
172
172
  options — SQLite database (pib-db) or markdown file (tasks.md) — plus
173
173
  bring-your-own for external systems. User picks one, the other, or
174
- neither. The choice is recorded in `.corrc.json` under `workTracking`
174
+ neither. The choice is recorded in `.ccrc.json` under `workTracking`
175
175
  and feeds into generate-briefing and generate-session-loop.
176
176
 
177
177
  ### 4. Options
@@ -49,7 +49,7 @@ early vs mature re-run:
49
49
  | CLAUDE.md | Root `CLAUDE.md` | Project instructions exist |
50
50
  | Rules files | `.claude/rules/*.md` | Scoped instructions exist |
51
51
  | Hook config | `.claude/settings.json` or `.claude/settings.local.json` | Enforcement hooks exist |
52
- | Omega memory | `~/.claude-cabinet/omega-venv/` and `scripts/cabinet-memory-adapter.py` | Semantic memory is active |
52
+ | Omega memory | `~/.claude-cabinet/omega-venv/` and `omega hooks doctor` OK | Semantic memory is active |
53
53
 
54
54
  **Early re-run:** Fewer than 5 of the above are populated.
55
55
  **Mature re-run:** 5 or more are populated.
@@ -89,16 +89,17 @@ sessions, and project-specific context.
89
89
  - `.claude/memory/patterns/` — enforcement patterns from prior sessions.
90
90
  Scan the directory, read each pattern file. These are project-level
91
91
  feedback that guides behavior (what to avoid, what to keep doing).
92
- - **Omega semantic memory** — if `~/.claude-cabinet/omega-venv/bin/python3`
93
- and `scripts/cabinet-memory-adapter.py` both exist, query omega for
94
- relevant context:
92
+ - **Omega semantic memory** — omega's native SessionStart hook
93
+ automatically surfaces recalled memories. During orient, query for
94
+ additional project-scoped context via the adapter:
95
95
  ```bash
96
96
  echo '{"text": "session context project status recent decisions", "limit": 10}' | \
97
97
  ~/.claude-cabinet/omega-venv/bin/python3 scripts/cabinet-memory-adapter.py query
98
98
  ```
99
99
  Surface any relevant memories (decisions, lessons, constraints) that
100
- inform the current session. If the venv is missing but `.ccrc.json`
101
- lists the memory module as installed, warn the user:
100
+ inform the current session. If omega is unavailable, run `omega hooks
101
+ doctor` to diagnose. If the venv is missing but `.ccrc.json` lists
102
+ the memory module as installed, warn the user:
102
103
  > ⚠ Memory module is installed but omega venv is missing.
103
104
  > Run `npx create-claude-cabinet` to restore it.
104
105
 
@@ -211,9 +212,11 @@ Read `phases/auto-maintenance.md` for recurring automated tasks that
211
212
  should run every session. These are operations that would decay if left
212
213
  to human memory — the anti-entropy principle in action.
213
214
 
214
- **Skip (absent/empty).** Projects add maintenance tasks as they discover
215
- operations that need regular execution but aren't worth remembering to
216
- invoke manually.
215
+ **Default (absent/empty):** If omega is active (`~/.claude-cabinet/omega-venv/bin/omega`
216
+ exists), run memory hygiene: `omega consolidate` every session (prune stale,
217
+ dedup), `omega compact` weekly (cluster similar memories), `omega backup`
218
+ weekly. Projects add additional maintenance tasks as they discover operations
219
+ that need regular execution.
217
220
 
218
221
  ### 6. Activate Cabinet Members (core)
219
222
 
@@ -259,7 +262,7 @@ stated a focus, ask.
259
262
  | `data-sync.md` | Skip | How to sync remote data |
260
263
  | `work-scan.md` | Default: pib-db scan + staleness detection | What work items to check |
261
264
  | `health-checks.md` | Skip | System health checks |
262
- | `auto-maintenance.md` | Skip | Recurring session-start tasks |
265
+ | `auto-maintenance.md` | Default: omega memory hygiene | Recurring session-start tasks |
263
266
  | `cabinet.md` | Skip | Which cabinet members to activate |
264
267
  | `briefing.md` | Default: simple summary | How to present orientation |
265
268
 
@@ -6,43 +6,87 @@ applied to session management.
6
6
 
7
7
  The distinction from health checks: health checks DETECT problems;
8
8
  auto-maintenance DOES work. A health check reports "data is stale."
9
+ An auto-maintenance task runs the sync to fix it.
9
10
 
10
11
  When this file is absent or empty, this step is skipped. (`skip: true`
11
12
  is equivalent to absent here.)
12
- An auto-maintenance task runs the sync to fix it.
13
13
 
14
- ## What to Include
14
+ ## Omega Memory Hygiene
15
15
 
16
- For each task, provide:
17
- - **What** the operation to perform
18
- - **Why every session** — what decays if this is skipped
19
- - **Command** — how to run it
20
- - **Auto-execute?** — yes (run silently) or surface (ask user first)
16
+ If omega is active (`~/.claude-cabinet/omega-venv/bin/omega` exists),
17
+ run these maintenance tasks every session:
21
18
 
22
- ## Example Maintenance Tasks
19
+ ### Consolidate (every session)
23
20
 
24
- Uncomment and adapt these for your project:
21
+ Prune zero-access memories older than 30 days and deduplicate. Silent,
22
+ non-destructive — only removes never-accessed entries and exact duplicates.
25
23
 
26
- <!--
27
- ### Process Pending Queue Items
28
24
  ```bash
29
- # Check for items queued by external systems
30
- curl -s https://your-api.example.com/api/queue/pending
25
+ ~/.claude-cabinet/omega-venv/bin/omega consolidate --prune-days 30 2>&1
31
26
  ```
32
- Items queued from a UI or external integration since last session.
33
- Auto-execute routine items; surface unusual ones for confirmation.
34
27
 
35
- ### Rotate Logs
28
+ Report only if something was actually pruned or merged (non-zero counts).
29
+
30
+ ### Compact (weekly)
31
+
32
+ Cluster and summarize similar memories by type. Only run if 7+ days
33
+ since last compact. Check by looking for the most recent `compaction`
34
+ type memory via the adapter:
35
+
36
+ ```bash
37
+ echo '{"type": "compaction", "limit": 1}' | \
38
+ ~/.claude-cabinet/omega-venv/bin/python3 scripts/cabinet-memory-adapter.py list
39
+ ```
40
+
41
+ If the most recent compaction memory is older than 7 days (or none exists):
42
+
36
43
  ```bash
37
- # Truncate logs that grow unbounded
38
- tail -1000 sync/app.log > sync/app.log.tmp && mv sync/app.log.tmp sync/app.log
44
+ ~/.claude-cabinet/omega-venv/bin/omega compact -t lesson_learned 2>&1
45
+ ~/.claude-cabinet/omega-venv/bin/omega compact -t decision 2>&1
46
+ ~/.claude-cabinet/omega-venv/bin/omega compact -t error_pattern 2>&1
39
47
  ```
40
- Prevents log files from consuming disk. Silent, no user interaction.
41
48
 
42
- ### Refresh Cached Computations
49
+ Report results only if clusters were found and compacted.
50
+
51
+ ### Discover Connections (weekly)
52
+
53
+ Scan for unlinked memories that should be related and create graph edges.
54
+ Auto-relate runs after each store but only checks the 3 nearest memories.
55
+ discover_connections does a broader sweep, turning isolated memories into
56
+ a connected knowledge graph. Runs alongside compact (same weekly cadence).
57
+
43
58
  ```bash
44
- ./scripts/rebuild-index.sh
59
+ ~/.claude-cabinet/omega-venv/bin/python3 -c "
60
+ from omega.bridge import discover_connections
61
+ result = discover_connections(lookback_hours=168) # 7 days
62
+ print(result if result else 'No new connections found')
63
+ "
45
64
  ```
46
- Regenerates derived data that may have drifted from source files.
47
- Run if source files changed since last session.
65
+
66
+ Report: "Discovered N new connections between memories" if non-zero.
67
+
68
+ ### Backup (weekly)
69
+
70
+ Back up the omega database. Runs alongside compact (same weekly cadence).
71
+ Omega keeps the last 5 backups automatically.
72
+
73
+ ```bash
74
+ ~/.claude-cabinet/omega-venv/bin/omega backup 2>&1
75
+ ```
76
+
77
+ <!--
78
+ ## Project-Specific Maintenance
79
+
80
+ Add your own recurring tasks below. For each task, provide:
81
+ - **What** — the operation to perform
82
+ - **Why every session** — what decays if this is skipped
83
+ - **Command** — how to run it
84
+ - **Auto-execute?** — yes (run silently) or surface (ask user first)
85
+
86
+ ### Example: Process Pending Queue Items
87
+ ```bash
88
+ curl -s https://your-api.example.com/api/queue/pending
89
+ ```
90
+ Items queued from a UI or external integration since last session.
91
+ Auto-execute routine items; surface unusual ones for confirmation.
48
92
  -->
@@ -41,18 +41,9 @@ your investor-reports project too."
41
41
 
42
42
  ### Omega Semantic Memory
43
43
 
44
- If `~/.claude-cabinet/omega-venv/bin/python3` and
45
- `scripts/cabinet-memory-adapter.py` both exist, surface relevant
46
- memories from omega at session start:
47
-
48
- ```bash
49
- echo '{}' | ~/.claude-cabinet/omega-venv/bin/python3 \
50
- scripts/cabinet-memory-adapter.py welcome
51
- ```
52
-
53
- The `welcome` command returns memories relevant to the current project.
54
- The SessionStart hook (`memory-session-start.sh`) also does this
55
- automatically, but during orient you can query for specific context:
44
+ Omega's native SessionStart hook (in `~/.claude/settings.json` global)
45
+ automatically surfaces recalled memories at session start. During orient,
46
+ you can query for additional specific context using the adapter:
56
47
 
57
48
  ```bash
58
49
  echo '{"text": "recent decisions and lessons", "limit": 5}' | \
@@ -60,9 +51,11 @@ echo '{"text": "recent decisions and lessons", "limit": 5}' | \
60
51
  scripts/cabinet-memory-adapter.py query
61
52
  ```
62
53
 
54
+ To verify omega is healthy, run `omega hooks doctor` or `omega status`.
55
+
63
56
  If omega is not available, check whether the memory module is installed
64
57
  (look for `"memory": true` in `.ccrc.json`). If it IS installed but the
65
- venv or adapter is missing, surface a warning:
58
+ venv is missing, surface a warning:
66
59
 
67
60
  > **⚠ Memory module is installed but omega is not available.**
68
61
  > The venv at `~/.claude-cabinet/omega-venv/` may be missing or broken.