create-claude-cabinet 0.23.1 → 0.25.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.
Files changed (41) hide show
  1. package/README.md +5 -5
  2. package/lib/cli.js +64 -2
  3. package/lib/verify-setup.js +140 -0
  4. package/package.json +1 -1
  5. package/templates/skills/debrief/SKILL.md +19 -22
  6. package/templates/skills/debrief/phases/record-lessons.md +152 -73
  7. package/templates/skills/debrief/phases/verify-coverage.md +101 -0
  8. package/templates/skills/execute/phases/verify-emit.md +104 -0
  9. package/templates/skills/orient/SKILL.md +30 -22
  10. package/templates/skills/plan/phases/verify-plan.md +97 -0
  11. package/templates/skills/verify/SKILL.md +228 -0
  12. package/templates/skills/verify/install.sh +342 -0
  13. package/templates/skills/verify/phases/calibrate.md +115 -0
  14. package/templates/skills/verify/phases/discover.md +114 -0
  15. package/templates/skills/verify/phases/draft.md +92 -0
  16. package/templates/skills/verify/phases/generate.md +71 -0
  17. package/templates/skills/verify/phases/scenario-template.md +119 -0
  18. package/templates/skills/verify/phases/update.md +81 -0
  19. package/templates/verify-runtime/CONVENTIONS.md +331 -0
  20. package/templates/verify-runtime/README.md +59 -0
  21. package/templates/verify-runtime/package-lock.json +2008 -0
  22. package/templates/verify-runtime/package.json +34 -0
  23. package/templates/verify-runtime/src/auto-check.ts +56 -0
  24. package/templates/verify-runtime/src/cli/preflight.ts +14 -0
  25. package/templates/verify-runtime/src/cli/report-last.ts +191 -0
  26. package/templates/verify-runtime/src/cli/report-status.ts +365 -0
  27. package/templates/verify-runtime/src/fixture-loader.ts +87 -0
  28. package/templates/verify-runtime/src/fresh-pass-cache.ts +193 -0
  29. package/templates/verify-runtime/src/human-verdict.ts +194 -0
  30. package/templates/verify-runtime/src/index.ts +66 -0
  31. package/templates/verify-runtime/src/manual-runner.ts +257 -0
  32. package/templates/verify-runtime/src/output.ts +177 -0
  33. package/templates/verify-runtime/src/path-hash.ts +241 -0
  34. package/templates/verify-runtime/src/preflight.ts +120 -0
  35. package/templates/verify-runtime/src/verdict-recorder.ts +318 -0
  36. package/templates/verify-runtime/src/world.ts +188 -0
  37. package/templates/verify-runtime/test/fixtures/sample.feature +17 -0
  38. package/templates/verify-runtime/test/fresh-pass-cache.test.ts +289 -0
  39. package/templates/verify-runtime/test/path-hash.test.ts +264 -0
  40. package/templates/verify-runtime/test/verdict-recorder.test.ts +58 -0
  41. package/templates/verify-runtime/tsconfig.json +16 -0
package/README.md CHANGED
@@ -5,7 +5,7 @@ gives Claude a memory, 31 domain experts, a planning process, and the
5
5
  habit of starting sessions informed and ending them properly.
6
6
 
7
7
  Built by a guy who'd rather talk to Claude than write code. Most of it
8
- was built by Claude. I just complained until it worked.
8
+ was built by Claude. I just complained until it (mostly) worked.
9
9
 
10
10
  ## The Idea
11
11
 
@@ -63,8 +63,8 @@ automatically.
63
63
 
64
64
  - **`/orient`** — open every session with this. Claude reads project
65
65
  state, checks health, surfaces what needs attention, and briefs you
66
- so you never start blind. Think of it as the morning briefing before
67
- the cabinet gets to work.
66
+ so you never start blind. Think of it as the briefing before the
67
+ cabinet gets to work.
68
68
  - **`/debrief`** — close every session with this. Claude marks work
69
69
  done, records lessons, updates state, and prepares the briefing for
70
70
  next time. Without debrief, the next orient starts with stale
@@ -134,7 +134,7 @@ hooks — things that keep going wrong become things that can't go wrong.
134
134
 
135
135
  ## Your Workflow
136
136
 
137
- The day-to-day rhythm:
137
+ The rhythm of each session:
138
138
 
139
139
  1. **Start a session** → `/orient` (get briefed)
140
140
  2. **Do your work** → talk to Claude, use `/plan` for anything non-trivial
@@ -227,7 +227,7 @@ other.
227
227
  ## Philosophy
228
228
 
229
229
  This started as the process layer of [Flow](https://github.com/orenmagid/flow),
230
- a cognitive workspace built on Claude Code over months of daily use. The
230
+ a cognitive workspace built on Claude Code over months of intensive use. The
231
231
  patterns that emerged — the session loop, cabinet-style audits, feedback
232
232
  enforcement — turned out to be transferable to any project.
233
233
 
package/lib/cli.js CHANGED
@@ -8,6 +8,7 @@ const { mergeSettings } = require('./settings-merge');
8
8
  const { create: createMetadata, read: readMetadata } = require('./metadata');
9
9
  const { setupDb } = require('./db-setup');
10
10
  const { setupOmega } = require('./omega-setup');
11
+ const { setupVerifyRuntime } = require('./verify-setup');
11
12
  const { reset } = require('./reset');
12
13
 
13
14
  const VERSION = require('../package.json').version;
@@ -356,6 +357,7 @@ const MODULES = {
356
357
  // Instruction phases — always ship, overriding the default skip-phases rule in copy.js
357
358
  'skills/debrief/phases/audit-pattern-capture.md',
358
359
  'skills/debrief/phases/methodology-capture.md',
360
+ 'skills/debrief/phases/record-lessons.md',
359
361
  'skills/debrief/phases/upstream-feedback.md',
360
362
  'skills/menu',
361
363
  ],
@@ -450,6 +452,20 @@ const MODULES = {
450
452
  needsOmega: true,
451
453
  templates: ['skills/memory', 'scripts/cabinet-memory-adapter.py', 'scripts/migrate-memory-to-omega.py', 'rules/memory-capture.md', 'hooks/omega-memory-guard.sh'],
452
454
  },
455
+ 'verify': {
456
+ name: 'Verification Harness (Cucumber + Playwright)',
457
+ description: 'Walkthrough verification with human-in-the-loop verdict pauses. Replaces flat AC lists with re-runnable user-journey scenarios. Includes /verify skeleton skill + cabinet-verify npm runtime + opt-in integration phases for /plan, /execute, /debrief.',
458
+ mandatory: false,
459
+ default: false,
460
+ lean: false,
461
+ templates: [
462
+ 'skills/verify',
463
+ 'skills/plan/phases/verify-plan.md',
464
+ 'skills/execute/phases/verify-emit.md',
465
+ 'skills/debrief/phases/verify-coverage.md',
466
+ ],
467
+ postInstall: 'verify-setup',
468
+ },
453
469
  };
454
470
 
455
471
  /** Recursively collect all relative file paths under a directory. */
@@ -503,7 +519,8 @@ function parseArgs(argv) {
503
519
  targetDir: '.',
504
520
  };
505
521
 
506
- for (const arg of args) {
522
+ for (let i = 0; i < args.length; i++) {
523
+ const arg = args[i];
507
524
  if (arg === '--yes' || arg === '-y') flags.yes = true;
508
525
  else if (arg === '--lean') flags.lean = true;
509
526
  else if (arg === '--no-db') flags.noDb = true;
@@ -511,6 +528,9 @@ function parseArgs(argv) {
511
528
  else if (arg === '--help' || arg === '-h') flags.help = true;
512
529
  else if (arg === '--reset') flags.reset = true;
513
530
  else if (arg === '--force') flags.force = true;
531
+ else if (arg === '--modules' && i + 1 < args.length) {
532
+ flags.modules = args[++i].split(',').map(s => s.trim()).filter(Boolean);
533
+ }
514
534
  else if (!arg.startsWith('-')) flags.targetDir = arg;
515
535
  }
516
536
 
@@ -525,6 +545,8 @@ function printHelp() {
525
545
  --yes, -y Accept all defaults, no prompts
526
546
  --lean Install core modules only (no work-tracking, compliance, validate)
527
547
  --no-db Skip work tracking database setup
548
+ --modules <keys> Comma-separated module keys to install (e.g., 'verify,memory').
549
+ Mandatory modules are always included.
528
550
  --dry-run Show what would be copied without writing
529
551
  --reset Remove Claude Cabinet files (uses manifest for safety)
530
552
  --force With --reset: remove even customized files
@@ -664,7 +686,27 @@ async function run() {
664
686
  let skippedModules = {};
665
687
  let includeDb = !flags.noDb;
666
688
 
667
- if (flags.lean) {
689
+ if (flags.modules) {
690
+ // Explicit module selection via --modules <key1,key2,...>. Mandatory
691
+ // modules are always included regardless of the flag value, so the
692
+ // installer always has session-loop etc. available.
693
+ const mandatoryKeys = Object.entries(MODULES)
694
+ .filter(([, mod]) => mod.mandatory)
695
+ .map(([key]) => key);
696
+ const requested = flags.modules.filter(k => MODULES[k]);
697
+ const unknown = flags.modules.filter(k => !MODULES[k]);
698
+ if (unknown.length > 0) {
699
+ console.log(` ⚠ Unknown modules ignored: ${unknown.join(', ')}`);
700
+ console.log(` Known modules: ${Object.keys(MODULES).join(', ')}`);
701
+ }
702
+ selectedModules = [...new Set([...mandatoryKeys, ...requested])];
703
+ const skippedKeys = Object.keys(MODULES).filter(k => !selectedModules.includes(k));
704
+ for (const k of skippedKeys) {
705
+ skippedModules[k] = `Skipped by --modules flag`;
706
+ }
707
+ if (!selectedModules.includes('work-tracking')) includeDb = false;
708
+ console.log(` Installing modules: ${selectedModules.join(', ')}\n`);
709
+ } else if (flags.lean) {
668
710
  selectedModules = Object.entries(MODULES)
669
711
  .filter(([, mod]) => mod.mandatory || mod.lean)
670
712
  .map(([key]) => key);
@@ -954,6 +996,26 @@ async function run() {
954
996
  }
955
997
  }
956
998
 
999
+ // --- Run module postInstall hooks ---
1000
+ // Modules with a `postInstall` field dispatch to a matching setup
1001
+ // function after templates are copied. Currently only 'verify-setup'
1002
+ // (the cabinet-verify tarball builder) is wired.
1003
+ for (const moduleKey of selectedModules) {
1004
+ const mod = MODULES[moduleKey];
1005
+ if (!mod.postInstall) continue;
1006
+ if (mod.postInstall === 'verify-setup') {
1007
+ try {
1008
+ console.log('');
1009
+ const verifyResult = setupVerifyRuntime({ dryRun: !!flags.dryRun });
1010
+ for (const r of verifyResult.results || []) console.log(` 📋 ${r}`);
1011
+ } catch (err) {
1012
+ console.log(` ⚠ cabinet-verify runtime setup failed: ${err.message}`);
1013
+ console.log(' /verify install.sh will fail until the runtime is installed.');
1014
+ console.log(' Re-run the installer to retry.');
1015
+ }
1016
+ }
1017
+ }
1018
+
957
1019
  // --- Manifest key migration (act:d1f16bee) ---
958
1020
  // When CC renames directories (e.g., perspectives/ → cabinet-*/), old manifest
959
1021
  // keys no longer match new template paths. Migrate keys BEFORE cleanup so the
@@ -0,0 +1,140 @@
1
+ /**
2
+ * verify-setup.js — install the cabinet-verify runtime tarball at
3
+ * ~/.claude-cabinet/verify/<version>/dist/.
4
+ *
5
+ * Mirrors the omega-setup.js pattern: dispatched from cli.js's install
6
+ * pipeline when the `verify` module is selected. Idempotent: skips if
7
+ * the matching-version tarball is already present.
8
+ *
9
+ * See templates/verify-runtime/CONVENTIONS.md §Install Dir and
10
+ * §Tarball Install Pattern for the frozen contract this implements.
11
+ */
12
+
13
+ const { execSync } = require('child_process');
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+ const os = require('os');
17
+
18
+ const CC_HOME = path.join(os.homedir(), '.claude-cabinet');
19
+ const VERIFY_BASE = path.join(CC_HOME, 'verify');
20
+
21
+ /**
22
+ * Set up the cabinet-verify runtime.
23
+ *
24
+ * Steps:
25
+ * 1. Read the version from templates/verify-runtime/package.json
26
+ * 2. Compute installDir = ~/.claude-cabinet/verify/<version>/dist/
27
+ * 3. If a tarball already exists at that path with the same version,
28
+ * log "already installed" and skip
29
+ * 4. Otherwise: mkdir -p installDir; npm pack inside templates/verify-runtime/;
30
+ * move the .tgz to installDir
31
+ * 5. Write ~/.claude-cabinet/verify/current/VERSION (single-line pointer
32
+ * used by /verify install.sh per CONVENTIONS.md Version Resolution)
33
+ *
34
+ * @param {Object} opts
35
+ * @param {boolean} [opts.dryRun] — print planned actions, don't execute
36
+ * @param {string} [opts.runtimeSourceDir] — override the templates/verify-runtime/
37
+ * location. Defaults to <repo>/templates/verify-runtime/ resolved from __dirname.
38
+ * @returns {Object} { installPath, version, status: 'installed'|'skipped'|'dry-run' }
39
+ */
40
+ function setupVerifyRuntime(opts = {}) {
41
+ const dryRun = !!opts.dryRun;
42
+ const runtimeSourceDir =
43
+ opts.runtimeSourceDir || path.resolve(__dirname, '..', 'templates', 'verify-runtime');
44
+
45
+ // 1. Read version
46
+ const packageJsonPath = path.join(runtimeSourceDir, 'package.json');
47
+ if (!fs.existsSync(packageJsonPath)) {
48
+ throw new Error(
49
+ `verify-setup: ${packageJsonPath} not found. Cannot resolve cabinet-verify version.`,
50
+ );
51
+ }
52
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
53
+ const version = pkg.version;
54
+ if (typeof version !== 'string' || version.length === 0) {
55
+ throw new Error(`verify-setup: ${packageJsonPath} has no version field`);
56
+ }
57
+
58
+ // 2. Compute installDir
59
+ const installDir = path.join(VERIFY_BASE, version, 'dist');
60
+ const tarballName = `cabinet-verify-${version}.tgz`;
61
+ const tarballPath = path.join(installDir, tarballName);
62
+ const versionPointer = path.join(VERIFY_BASE, 'current', 'VERSION');
63
+
64
+ const results = [];
65
+
66
+ if (dryRun) {
67
+ results.push(`Would install cabinet-verify@${version}`);
68
+ results.push(` source: ${runtimeSourceDir}`);
69
+ results.push(` target: ${tarballPath}`);
70
+ results.push(` pointer: ${versionPointer}`);
71
+ return { installPath: installDir, version, status: 'dry-run', results };
72
+ }
73
+
74
+ // 3. Idempotency check. Existence alone is not enough — an earlier
75
+ // stub-touch (e.g., a test fixture) can leave a 0-byte file at the
76
+ // tarball path. npm install on the consumer side then fails with
77
+ // ENODATA / TAR_BAD_ARCHIVE. Validate the file has non-trivial size
78
+ // before treating it as installed.
79
+ if (fs.existsSync(tarballPath) && fs.statSync(tarballPath).size > 1024) {
80
+ results.push(`cabinet-verify@${version} already installed (${tarballPath})`);
81
+ // Even on skip, ensure the VERSION pointer is up-to-date so a later
82
+ // version downgrade doesn't leave a stale pointer behind.
83
+ writeVersionPointer(versionPointer, version);
84
+ results.push(`Updated VERSION pointer: ${versionPointer}`);
85
+ return { installPath: installDir, version, status: 'skipped', results };
86
+ }
87
+
88
+ // Remove a 0-byte stub before re-packing so the move below doesn't
89
+ // hit a "file exists" surprise.
90
+ if (fs.existsSync(tarballPath)) {
91
+ fs.unlinkSync(tarballPath);
92
+ }
93
+
94
+ // 4. mkdir + npm pack + move
95
+ fs.mkdirSync(installDir, { recursive: true });
96
+ // Run npm pack in the runtime source dir. --pack-destination writes
97
+ // the tarball directly to installDir without an intermediate cwd move.
98
+ const packStdout = execSync(`npm pack --silent --pack-destination "${installDir}"`, {
99
+ cwd: runtimeSourceDir,
100
+ encoding: 'utf8',
101
+ }).trim();
102
+
103
+ // npm pack prints the tarball filename to stdout on the last non-empty line.
104
+ // Normalise to the expected name so consuming projects can rely on the
105
+ // CONVENTIONS.md-documented path.
106
+ const lastLine = packStdout.split('\n').filter(Boolean).pop() || '';
107
+ const producedName = path.basename(lastLine);
108
+ if (producedName && producedName !== tarballName) {
109
+ // npm pack may produce a name like 'cabinet-verify-0.1.0.tgz' that already
110
+ // matches; if it doesn't (e.g., npm prefixes with @scope/), rename to match.
111
+ const producedPath = path.join(installDir, producedName);
112
+ if (fs.existsSync(producedPath)) {
113
+ fs.renameSync(producedPath, tarballPath);
114
+ }
115
+ }
116
+
117
+ if (!fs.existsSync(tarballPath)) {
118
+ throw new Error(
119
+ `verify-setup: npm pack completed but ${tarballPath} not found. ` +
120
+ `stdout was: ${packStdout.slice(0, 500)}`,
121
+ );
122
+ }
123
+
124
+ results.push(`Installed cabinet-verify@${version} to ${tarballPath}`);
125
+
126
+ // 5. Write VERSION pointer
127
+ writeVersionPointer(versionPointer, version);
128
+ results.push(`Wrote VERSION pointer: ${versionPointer}`);
129
+
130
+ return { installPath: installDir, version, status: 'installed', results };
131
+ }
132
+
133
+ function writeVersionPointer(pointerPath, version) {
134
+ fs.mkdirSync(path.dirname(pointerPath), { recursive: true });
135
+ // No trailing newline — CONVENTIONS.md frozen contract requires the
136
+ // file to equal the version string exactly under `cat`.
137
+ fs.writeFileSync(pointerPath, version, 'utf8');
138
+ }
139
+
140
+ module.exports = { setupVerifyRuntime };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-cabinet",
3
- "version": "0.23.1",
3
+ "version": "0.25.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"
@@ -306,27 +306,24 @@ Don't silently bundle unrelated changes.
306
306
 
307
307
  ### 9. Record Lessons (core)
308
308
 
309
- Read `phases/record-lessons.md` for how to capture what was learned.
310
- This is the second irreducible purpose of debrief — the first is
311
- closing work, this is ensuring the next session is smarter than this
312
- one.
313
-
314
- **Default (absent/empty):** At minimum ask: did this session reveal
315
- anything that future sessions need to know? A new pattern, a gotcha,
316
- a process gap, a user preference? Lessons are perishable — capture
317
- them now while context is fresh.
318
-
319
- **Omega-only:** If `~/.claude-cabinet/omega-venv/bin/python3` and
320
- `scripts/cabinet-memory-adapter.py` both exist, write lessons to omega
321
- never to flat markdown. A guard hook enforces this. Use the adapter:
322
-
323
- ```bash
324
- echo '{"text": "the lesson", "type": "lesson"}' | \
325
- ~/.claude-cabinet/omega-venv/bin/python3 scripts/cabinet-memory-adapter.py store
326
- ```
327
-
328
- Types: `decision`, `lesson`, `preference`, `constraint`, `pattern`.
329
- Flat markdown memory is the fallback only when omega is unavailable.
309
+ Read `phases/record-lessons.md` for how to route session outputs to
310
+ their real homes. This is the second irreducible purpose of debrief —
311
+ the first is closing work, this is ensuring the next session is smarter
312
+ than this one.
313
+
314
+ **The phase file teaches a routing discipline:** every output has
315
+ exactly one home with a forcing function omega `decision`/`lesson`/
316
+ `constraint`/`preference` memory, inline in CLAUDE.md or a briefing
317
+ (for load-bearing project facts), a pib-db deferred action (for
318
+ conditional revisits), or the upstream-feedback phase (for CC-applicable
319
+ friction). Loose `.md` files written next to the code they describe
320
+ are explicitly an **anti-pattern** they rot silently when the code
321
+ changes. Hybrid observations (part project, part CC) must be split.
322
+
323
+ **Default (absent/empty):** Follow the routing tree in the phase file.
324
+ Ask the user only when routing is genuinely ambiguous — not as a
325
+ catch-all "what did we learn?" prompt, which tends to produce vague
326
+ lessons that don't get recorded anywhere useful.
330
327
 
331
328
  **Omega broken:** If the memory module is installed (check `.ccrc.json`
332
329
  for `"memory": true`) but the venv or adapter is missing, surface this
@@ -485,7 +482,7 @@ Read `phases/report.md` for how to present the debrief summary.
485
482
  | `auto-maintenance.md` | Skip | Recurring session-end tasks |
486
483
  | `update-state.md` | Default: check system-status.md | What state files to update |
487
484
  | `health-checks.md` | Skip | Session-end health checks |
488
- | `record-lessons.md` | Default: ask what was learned | How to capture learnings |
485
+ | `record-lessons.md` | Default: route outputs per the decision tree | How to route session outputs to omega / CLAUDE.md / pib-db triggers / upstream |
489
486
  | `audit-pattern-capture.md` | **Instruction: always runs** | Detect recurring audit findings, write to patterns-project.md |
490
487
  | `methodology-capture.md` | **Instruction: always runs** | Detect methodology-level work; capture reasoning chain + narrative to `.claude/methodology/` |
491
488
  | `upstream-feedback.md` | **Instruction: always runs** | Surface CC friction to source repo |
@@ -1,94 +1,173 @@
1
- # Record Lessons — Capture What Was Learned
1
+ # Record Lessons — Route Session Outputs to Their Real Homes
2
2
 
3
- Define how to capture lessons from the session so future sessions are
4
- smarter. This is the second irreducible purpose of debrief without it,
5
- the system does work but doesn't learn from it.
3
+ This is debrief's second irreducible purpose: make sure the next session
4
+ is smarter than this one. Without it, the system does work but doesn't
5
+ learn from it.
6
6
 
7
- When this file is absent or empty, the default behavior is: ask whether
8
- the session revealed anything future sessions need to know. To explicitly
9
- skip lesson recording, write only `skip: true`.
7
+ Lessons are perishable. A lesson captured while context is fresh is
8
+ worth ten captured from memory next week.
10
9
 
11
- Lessons are perishable. A lesson captured while context is fresh is worth
12
- ten captured from memory next week. This is why recording happens during
13
- debrief, not "sometime later."
10
+ ## The Routing Principle
14
11
 
15
- ## Where to Record Omega Primary
12
+ Every session output has **exactly one primary home**. The home must
13
+ have a forcing function — something that keeps the content accurate
14
+ when the code it describes changes. Loose `.md` files next to code
15
+ are the wrong home: they rot silently because nothing invalidates
16
+ them when the system evolves.
16
17
 
17
- Check whether omega memory is available:
18
- - `~/.claude-cabinet/omega-venv/bin/python3` exists AND
19
- - `scripts/cabinet-memory-adapter.py` exists
18
+ **Each output has one home. Don't double-store.** A decision stored
19
+ in omega doesn't also need a `.md` file. A constraint documented in
20
+ CLAUDE.md doesn't also need an omega entry "for backup." Duplication
21
+ just creates two things to keep in sync.
20
22
 
21
- **When omega is available — use it. No exceptions.** Write lessons to
22
- omega via the adapter. Never write to flat markdown memory files when
23
- omega is available a guard hook will block the attempt.
23
+ ## Routing Decision Tree
24
+
25
+ For each thing you'd want future sessions to know, pick the single
26
+ best home:
27
+
28
+ ### Decisions — "we chose X over Y because Z"
29
+
30
+ Architectural choices, tradeoff resolutions, accepted gaps, rejected
31
+ alternatives.
32
+
33
+ **Primary home:** omega `decision` memory. Omega has contradiction
34
+ detection — when a later decision supersedes this one, the old entry
35
+ can be marked `status=superseded` instead of silently rotting.
24
36
 
25
37
  ```bash
26
- echo '{"text": "the lesson", "type": "lesson", "tags": ["tag1"]}' | \
38
+ echo '{"text": "the decision + why", "type": "decision"}' | \
27
39
  ~/.claude-cabinet/omega-venv/bin/python3 scripts/cabinet-memory-adapter.py store
28
40
  ```
29
41
 
30
- Memory types to use:
31
- - `decision` architectural choices, tradeoff resolutions
32
- - `lesson` gotchas, discoveries, things that surprised
33
- - `preference` user corrections, style choices, workflow preferences
34
- - `constraint`limitations discovered, prerequisites found
35
- - `pattern` — conventions established, recurring solutions
36
-
37
- **When omega is NOT available:** Only then use flat markdown memory
38
- (auto-memory in `~/.claude/projects/` memory directory). Check omega
39
- availability first — don't assume it's unavailable without checking.
40
-
41
- ## What to Look For
42
-
43
- Review the session and ask:
44
- - Did we learn something future sessions need to know?
45
- - A new pattern established
46
- - A gotcha discovered
47
- - A process gap identified
48
- - A user preference revealed
49
- - Is this the second or third time something came up? If the same kind
50
- of problem keeps recurring, the lesson is "create a prevention mechanism"
51
- not just "remember this."
52
- - Did the session's work contradict any existing recorded knowledge?
53
- If so, update or remove the stale record (in omega: use `query` to
54
- find it, then note the contradiction in the new memory).
55
-
56
- ## What NOT to Record
57
- - Code patterns derivable by reading current files
58
- - Git history (use git log)
59
- - Debugging solutions (the fix is in the code)
60
- - Anything already in CLAUDE.md files
61
- - Ephemeral task details only relevant to this session
42
+ **Also add to CLAUDE.md** only if the decision is load-bearing enough
43
+ that *every* session needs to know it at startup (not just sessions
44
+ that touch the relevant code). Examples: "auth is per-user via FastAPI
45
+ Users (no shared passwords)" is load-bearing. "We rejected a specific
46
+ library option after evaluation" is not omega is enough.
62
47
 
63
- ## After Storing Link and Check
48
+ ### Project constraints / conventions / gotchas
64
49
 
65
- After storing each memory, omega auto-relates it to similar existing
66
- memories. Surface this to the user:
50
+ Environmental quirks, dev-workflow requirements, "this project has a
51
+ weird setup" facts.
67
52
 
68
- ```bash
69
- ~/.claude-cabinet/omega-venv/bin/python3 -c "
70
- from omega import find_similar_memories
71
- result = find_similar_memories('THE_NEW_MEMORY_ID')
72
- print(result)
73
- "
53
+ **Primary home:** inline in `CLAUDE.md` or the project briefing. These
54
+ files get edited when the code changes — the forcing function is that
55
+ they're load-bearing for every session, so staleness surfaces fast.
56
+
57
+ Use omega `constraint` type only for cross-project patterns (e.g.,
58
+ "in any project with nested package.json..."). Project-specific
59
+ constraints belong inline.
60
+
61
+ ### Conditional revisits — "do X later when Y happens"
62
+
63
+ "If we ever get multiple concurrent users, add a token blocklist."
64
+ "When curl becomes annoying, build a /settings UI."
65
+
66
+ **Primary home:** pib-db deferred action with `trigger_condition`.
67
+
68
+ ```
69
+ pib_create_action text="..." status="deferred" trigger_condition="..."
74
70
  ```
75
71
 
76
- If the new memory is similar to existing ones, mention it:
77
- "This connects to your earlier memory about [topic]."
72
+ Orient's deferred-check phase re-evaluates these every session. If the
73
+ condition has fired, the user gets asked; if it's obsolete, it gets
74
+ marked so. No silent rot.
75
+
76
+ ### CC upstream friction embedded in a project observation
77
+
78
+ Sometimes a project-scoped observation contains a CC-applicable piece:
79
+ "in this project auth tests are hard, AND cabinet-qa should flag this
80
+ pattern in any auth work." That's two things, not one.
81
+
82
+ **Split it.** Route the project piece to its home (omega / CLAUDE.md /
83
+ trigger). Route the CC piece to the upstream-feedback phase (step 11)
84
+ where it will be drafted and delivered. Don't bury the upstream piece
85
+ inside a project decision doc — it will never find its way home.
86
+
87
+ ### Lessons, gotchas, discoveries (not decisions, not constraints)
88
+
89
+ "We learned that X behaves differently from docs." "This pattern
90
+ works." "The CI was green but prod failed because…"
91
+
92
+ **Primary home:** omega `lesson` memory. Same forcing function as
93
+ decisions — superseded lessons can be marked and surfaced.
94
+
95
+ ### User preferences
96
+
97
+ Style choices, workflow preferences, corrections the user made.
98
+
99
+ **Primary home:** omega `preference` memory.
78
100
 
79
- Also check for contradictions if the new memory conflicts with an
80
- existing one, ask the user which is correct:
101
+ ## The Anti-Pattern: Loose Project-Scoped .md Files
102
+
103
+ **Do not write `feedback-project-*.md`, `decision-*.md`, or similar
104
+ loose .md files as the primary record of a session output.** This
105
+ pattern has been observed to rot — in one audited case, 4 of 5 such
106
+ files went stale within 7 days because the underlying code changed
107
+ and the files had no forcing function to catch it.
108
+
109
+ If you are tempted to write a loose .md file:
110
+ - Is it a decision? → omega `decision`
111
+ - Is it a constraint everyone needs? → CLAUDE.md / briefing
112
+ - Is it a conditional revisit? → pib-db deferred trigger
113
+ - Is it CC upstream friction? → upstream-feedback phase
114
+ - None of the above? → it probably doesn't need recording at all
115
+
116
+ ## Before Writing — Contradiction Check
117
+
118
+ For each memory you're about to write, query omega for existing
119
+ entries on the same topic:
120
+
121
+ ```bash
122
+ ~/.claude-cabinet/omega-venv/bin/omega query "topic keywords" --limit 5
123
+ ```
124
+
125
+ If an existing entry contradicts or is superseded by the new one,
126
+ mark the old one:
81
127
 
82
128
  ```bash
83
- ~/.claude-cabinet/omega-venv/bin/python3 -c "
84
- from omega import SQLiteStore
85
- s = SQLiteStore()
86
- edges = s.get_edges_by_type('contradicts')
87
- for e in edges: print(f\"{e['source_id']} <-> {e['target_id']} ({e['weight']:.2f})\")
88
- "
129
+ ~/.claude-cabinet/omega-venv/bin/omega update <old-id> --status superseded
130
+ ```
131
+
132
+ This is the forcing function that turns omega into a living record
133
+ instead of another pile of rotting notes.
134
+
135
+ ## When Omega Is Not Available
136
+
137
+ If `~/.claude-cabinet/omega-venv/bin/python3` is missing AND the
138
+ memory module is not installed (check `.ccrc.json`), fall back to
139
+ flat markdown memory in `~/.claude/projects/...`. But recognize
140
+ this fallback has the same rot problem — prefer CLAUDE.md for
141
+ anything load-bearing and pib-db triggers for anything conditional.
142
+
143
+ If the memory module IS installed but omega is broken, surface this
144
+ in the debrief report:
145
+
146
+ > **⚠ Memory module is installed but omega is not working.**
147
+ > Decisions/lessons from this session were saved to flat markdown
148
+ > instead. Run `npx create-claude-cabinet` to rebuild the omega venv.
149
+
150
+ ## What NOT to Record — Anywhere
151
+
152
+ - Code patterns derivable by reading current files
153
+ - Git history (use `git log`)
154
+ - Debugging solutions (the fix is already in the code; the commit
155
+ message has the context)
156
+ - Anything already in CLAUDE.md files
157
+ - Ephemeral task details only relevant to this session
158
+ - "We made progress on X" session summaries — that's what git is for
159
+
160
+ ## Report What Was Routed
161
+
162
+ Tell the user what went where so they can audit the routing:
163
+
164
+ ```
165
+ Routed this session:
166
+ - 1 decision → omega mem-xxxxx (JWT revocation tradeoff)
167
+ - 1 constraint → article-rewriter/CLAUDE.md (tsc must run from frontend)
168
+ - 1 deferred trigger → pib-db act:xxxxxxxx (add blocklist if multi-user)
169
+ - 1 upstream piece → CC feedback outbox (cabinet-qa testability)
89
170
  ```
90
171
 
91
- ## Report What Was Recorded
92
- Tell the user what memories were created or updated so they know what
93
- the system will remember next time. Include the count, types, and any
94
- new connections discovered in the knowledge graph.
172
+ This is also how you catch routing errors: if everything ended up in
173
+ omega, the routing discipline didn't actually run.