continuous-improvement 1.0.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.
@@ -0,0 +1,433 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+
7
+ const rootDir = path.resolve(__dirname, '..');
8
+ const homeDir = os.homedir();
9
+ const cwd = process.cwd();
10
+
11
+ const args = process.argv.slice(2);
12
+ const command = args[0];
13
+ const flags = new Set(args.slice(1));
14
+ const dryRun = flags.has('--dry-run');
15
+ const useGlobal = flags.has('--global');
16
+
17
+ const TARGET_FLAGS = ['claude', 'codex', 'cursor', 'openclaw', 'chatgpt'];
18
+ const selectedTarget = TARGET_FLAGS.find((name) => flags.has(`--${name}`));
19
+
20
+ const CODING_AGENT_BLOCK = `## Operating Rules (continuous-improvement)
21
+
22
+ 1. RESEARCH before executing — check docs, rate limits, existing implementations
23
+ 2. PLAN before coding — write what you will build, what you won't, how to verify, and fallback
24
+ 3. ONE THING at a time — complete and verify each task before starting the next
25
+ 4. VERIFY before reporting — run it, check the output, confirm it matches expected
26
+ 5. REFLECT after sessions — log what worked, what failed, what to change
27
+ 6. ITERATE means one change at a time — fix before adding, verify before proceeding
28
+ 7. LEARN from every session — patterns become instincts, corrections weaken bad behaviors, nothing is permanent without reinforcement
29
+ `;
30
+
31
+ const CURSOR_BLOCK = `Follow continuous-improvement: Research → Plan → Execute (one thing) → Verify → Reflect → Iterate.
32
+ Never report "done" without verification.
33
+ Never add features before fixing bugs.
34
+ Never execute without checking docs first.
35
+ `;
36
+
37
+ const CHATGPT_BLOCK = `Follow the continuous-improvement loop for all tasks:
38
+ 1. Research first — what exists? what can break? what are the limits?
39
+ 2. Plan — what to build, what NOT to build, how to verify, fallback plan
40
+ 3. Execute one thing at a time — finish and verify before starting the next
41
+ 4. Verify before saying "done" — actually check the output
42
+ 5. Reflect — what worked, what failed, what to do differently
43
+ 6. Iterate — one change at a time, verify each before proceeding
44
+ `;
45
+
46
+ function usage(code = 0) {
47
+ console.log(`continuous-improvement\n\nUsage:\n continuous-improvement install [--claude|--codex|--cursor|--openclaw|--chatgpt] [--global] [--dry-run]\n continuous-improvement uninstall [--claude|--codex|--cursor|--openclaw]\n\nExamples:\n npx continuous-improvement install\n npx continuous-improvement install --claude\n npx continuous-improvement install --cursor\n npx continuous-improvement install --openclaw\n npx continuous-improvement install --chatgpt\n npx continuous-improvement install --claude --global\n npx continuous-improvement uninstall --codex\n`);
48
+ process.exit(code);
49
+ }
50
+
51
+ function exists(filePath) {
52
+ return fs.existsSync(filePath);
53
+ }
54
+
55
+ function ensureDir(dirPath) {
56
+ if (dryRun) return;
57
+ fs.mkdirSync(dirPath, { recursive: true });
58
+ }
59
+
60
+ function readUtf8(filePath) {
61
+ return fs.readFileSync(filePath, 'utf8');
62
+ }
63
+
64
+ function writeUtf8(filePath, content) {
65
+ if (dryRun) return;
66
+ ensureDir(path.dirname(filePath));
67
+ fs.writeFileSync(filePath, content, 'utf8');
68
+ }
69
+
70
+ function appendBlock(filePath, block) {
71
+ const trimmedBlock = block.trim();
72
+ const existing = exists(filePath) ? readUtf8(filePath) : '';
73
+
74
+ if (existing.includes(trimmedBlock)) {
75
+ return { changed: false, reason: 'already-installed' };
76
+ }
77
+
78
+ const next = existing.trim().length === 0
79
+ ? `${trimmedBlock}\n`
80
+ : `${existing.replace(/\s*$/, '')}\n\n${trimmedBlock}\n`;
81
+
82
+ writeUtf8(filePath, next);
83
+ return { changed: true };
84
+ }
85
+
86
+ function removeBlock(filePath, block) {
87
+ if (!exists(filePath)) {
88
+ return { changed: false, reason: 'not-found' };
89
+ }
90
+
91
+ const trimmedBlock = block.trim();
92
+ const existing = readUtf8(filePath);
93
+
94
+ if (!existing.includes(trimmedBlock)) {
95
+ return { changed: false, reason: 'not-installed' };
96
+ }
97
+
98
+ const next = existing
99
+ .replace(new RegExp(`\\n?\\n?${escapeRegExp(trimmedBlock)}\\n?`, 'm'), '\n')
100
+ .replace(/^\s+|\s+$/g, '');
101
+
102
+ writeUtf8(filePath, next ? `${next}\n` : '');
103
+ return { changed: true };
104
+ }
105
+
106
+ function escapeRegExp(value) {
107
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
108
+ }
109
+
110
+ function copySkill() {
111
+ const sourceDir = path.join(rootDir, 'skills', 'continuous-improvement');
112
+ const destDir = path.join(homeDir, '.openclaw', 'skills', 'continuous-improvement');
113
+ const sourceFile = path.join(sourceDir, 'SKILL.md');
114
+ const destFile = path.join(destDir, 'SKILL.md');
115
+ const content = readUtf8(sourceFile);
116
+
117
+ if (exists(destFile) && readUtf8(destFile) === content) {
118
+ return { target: 'openclaw', location: destFile, changed: false, reason: 'already-installed' };
119
+ }
120
+
121
+ writeUtf8(destFile, content);
122
+ return { target: 'openclaw', location: destFile, changed: true };
123
+ }
124
+
125
+ function setupMulahazah() {
126
+ const mulahazahDir = path.join(homeDir, '.claude', 'mulahazah');
127
+ const instinctsPersonalDir = path.join(mulahazahDir, 'instincts', 'personal');
128
+ const projectsDir = path.join(mulahazahDir, 'projects');
129
+
130
+ ensureDir(mulahazahDir);
131
+ ensureDir(instinctsPersonalDir);
132
+ ensureDir(projectsDir);
133
+
134
+ const configDest = path.join(mulahazahDir, 'config.json');
135
+ if (!exists(configDest)) {
136
+ const configSrc = path.join(rootDir, 'config.json');
137
+ if (exists(configSrc)) {
138
+ writeUtf8(configDest, readUtf8(configSrc));
139
+ }
140
+ }
141
+
142
+ const projectsRegistry = path.join(mulahazahDir, 'projects.json');
143
+ if (!exists(projectsRegistry)) {
144
+ writeUtf8(projectsRegistry, JSON.stringify({}, null, 2) + '\n');
145
+ }
146
+
147
+ return { location: mulahazahDir, changed: true };
148
+ }
149
+
150
+ function installHooks() {
151
+ const mulahazahDir = path.join(homeDir, '.claude', 'mulahazah');
152
+ const hookDest = path.join(mulahazahDir, 'observe.sh');
153
+ const hookSrc = path.join(rootDir, 'hooks', 'observe.sh');
154
+
155
+ ensureDir(mulahazahDir);
156
+
157
+ if (exists(hookSrc)) {
158
+ writeUtf8(hookDest, readUtf8(hookSrc));
159
+ if (!dryRun) {
160
+ fs.chmodSync(hookDest, 0o755);
161
+ }
162
+ }
163
+
164
+ const settingsPath = path.join(homeDir, '.claude', 'settings.json');
165
+ let settings = {};
166
+ if (exists(settingsPath)) {
167
+ try {
168
+ settings = JSON.parse(readUtf8(settingsPath));
169
+ } catch (_) {
170
+ settings = {};
171
+ }
172
+ }
173
+
174
+ const hookEntry = { matcher: '*', hooks: [{ type: 'command', command: hookDest }] };
175
+
176
+ let changed = false;
177
+
178
+ for (const hookType of ['PreToolUse', 'PostToolUse']) {
179
+ if (!settings.hooks) settings.hooks = {};
180
+ if (!settings.hooks[hookType]) settings.hooks[hookType] = [];
181
+
182
+ const alreadyInstalled = settings.hooks[hookType].some(
183
+ (entry) => entry.hooks && entry.hooks.some((h) => h.command === hookDest)
184
+ );
185
+
186
+ if (!alreadyInstalled) {
187
+ settings.hooks[hookType].push(hookEntry);
188
+ changed = true;
189
+ }
190
+ }
191
+
192
+ if (changed) {
193
+ writeUtf8(settingsPath, JSON.stringify(settings, null, 2) + '\n');
194
+ }
195
+
196
+ return { location: settingsPath, changed };
197
+ }
198
+
199
+ function copyObserverFiles() {
200
+ const agentsSrc = path.join(rootDir, 'agents');
201
+ const agentsDest = path.join(homeDir, '.claude', 'mulahazah', 'agents');
202
+
203
+ ensureDir(agentsDest);
204
+
205
+ const filesToCopy = ['observer.md', 'observer-loop.sh', 'start-observer.sh'];
206
+ let changed = false;
207
+
208
+ for (const fileName of filesToCopy) {
209
+ const srcFile = path.join(agentsSrc, fileName);
210
+ const destFile = path.join(agentsDest, fileName);
211
+
212
+ if (exists(srcFile)) {
213
+ const content = readUtf8(srcFile);
214
+ const existingContent = exists(destFile) ? readUtf8(destFile) : null;
215
+ if (existingContent !== content) {
216
+ writeUtf8(destFile, content);
217
+ if (!dryRun && fileName.endsWith('.sh')) {
218
+ fs.chmodSync(destFile, 0o755);
219
+ }
220
+ changed = true;
221
+ }
222
+ }
223
+ }
224
+
225
+ return { location: agentsDest, changed };
226
+ }
227
+
228
+ function uninstallHooks() {
229
+ const settingsPath = path.join(homeDir, '.claude', 'settings.json');
230
+ if (!exists(settingsPath)) return;
231
+
232
+ let settings;
233
+ try {
234
+ settings = JSON.parse(readUtf8(settingsPath));
235
+ } catch (_) {
236
+ return;
237
+ }
238
+
239
+ if (!settings.hooks) return;
240
+
241
+ const mulahazahDir = path.join(homeDir, '.claude', 'mulahazah');
242
+ const hookDest = path.join(mulahazahDir, 'observe.sh');
243
+
244
+ let changed = false;
245
+ for (const hookType of ['PreToolUse', 'PostToolUse']) {
246
+ if (!Array.isArray(settings.hooks[hookType])) continue;
247
+ const before = settings.hooks[hookType].length;
248
+ settings.hooks[hookType] = settings.hooks[hookType].filter(
249
+ (entry) => !(entry.hooks && entry.hooks.some((h) => h.command === hookDest))
250
+ );
251
+ if (settings.hooks[hookType].length === 0) {
252
+ delete settings.hooks[hookType];
253
+ }
254
+ if (settings.hooks[hookType] === undefined || settings.hooks[hookType].length !== before) {
255
+ changed = true;
256
+ }
257
+ }
258
+
259
+ if (Object.keys(settings.hooks).length === 0) {
260
+ delete settings.hooks;
261
+ }
262
+
263
+ if (changed) {
264
+ writeUtf8(settingsPath, JSON.stringify(settings, null, 2) + '\n');
265
+ }
266
+ }
267
+
268
+ function installClaude(globalInstall = useGlobal) {
269
+ const filePath = globalInstall
270
+ ? path.join(homeDir, '.claude', 'CLAUDE.md')
271
+ : path.join(cwd, 'CLAUDE.md');
272
+ const result = appendBlock(filePath, CODING_AGENT_BLOCK);
273
+ return { target: 'claude', location: filePath, ...result };
274
+ }
275
+
276
+ function installCodex() {
277
+ const filePath = path.join(cwd, 'AGENTS.md');
278
+ const result = appendBlock(filePath, CODING_AGENT_BLOCK);
279
+ return { target: 'codex', location: filePath, ...result };
280
+ }
281
+
282
+ function installCursor() {
283
+ const filePath = path.join(cwd, '.cursorrules');
284
+ const result = appendBlock(filePath, CURSOR_BLOCK);
285
+ return { target: 'cursor', location: filePath, ...result };
286
+ }
287
+
288
+ function installChatgpt() {
289
+ return { target: 'chatgpt', location: 'stdout', changed: true, printed: CHATGPT_BLOCK };
290
+ }
291
+
292
+ function uninstallClaude(globalInstall = useGlobal) {
293
+ const filePath = globalInstall
294
+ ? path.join(homeDir, '.claude', 'CLAUDE.md')
295
+ : path.join(cwd, 'CLAUDE.md');
296
+ const result = removeBlock(filePath, CODING_AGENT_BLOCK);
297
+ return { target: 'claude', location: filePath, ...result };
298
+ }
299
+
300
+ function uninstallCodex() {
301
+ const filePath = path.join(cwd, 'AGENTS.md');
302
+ const result = removeBlock(filePath, CODING_AGENT_BLOCK);
303
+ return { target: 'codex', location: filePath, ...result };
304
+ }
305
+
306
+ function uninstallCursor() {
307
+ const filePath = path.join(cwd, '.cursorrules');
308
+ const result = removeBlock(filePath, CURSOR_BLOCK);
309
+ return { target: 'cursor', location: filePath, ...result };
310
+ }
311
+
312
+ function uninstallOpenclaw() {
313
+ const destFile = path.join(homeDir, '.openclaw', 'skills', 'continuous-improvement', 'SKILL.md');
314
+ if (!exists(destFile)) {
315
+ return { target: 'openclaw', location: destFile, changed: false, reason: 'not-installed' };
316
+ }
317
+ if (!dryRun) {
318
+ fs.rmSync(path.dirname(destFile), { recursive: true, force: true });
319
+ }
320
+ return { target: 'openclaw', location: destFile, changed: true };
321
+ }
322
+
323
+ function detectTargets() {
324
+ const targets = [];
325
+ if (exists(path.join(cwd, 'CLAUDE.md'))) targets.push('claude');
326
+ if (exists(path.join(cwd, 'AGENTS.md'))) targets.push('codex');
327
+ if (exists(path.join(cwd, '.cursorrules'))) targets.push('cursor');
328
+ if (exists(path.join(homeDir, '.openclaw'))) targets.push('openclaw');
329
+ if (targets.length === 0) {
330
+ if (exists(path.join(homeDir, '.claude'))) targets.push('claude-global');
331
+ }
332
+ return targets;
333
+ }
334
+
335
+ function installTarget(target) {
336
+ switch (target) {
337
+ case 'claude': {
338
+ const claudeResult = installClaude(false);
339
+ const mulahazahResult = setupMulahazah();
340
+ const hooksResult = installHooks();
341
+ const observerResult = copyObserverFiles();
342
+ return { ...claudeResult, mulahazah: mulahazahResult, hooks: hooksResult, observer: observerResult };
343
+ }
344
+ case 'claude-global': {
345
+ const claudeResult = installClaude(true);
346
+ const mulahazahResult = setupMulahazah();
347
+ const hooksResult = installHooks();
348
+ const observerResult = copyObserverFiles();
349
+ return { ...claudeResult, mulahazah: mulahazahResult, hooks: hooksResult, observer: observerResult };
350
+ }
351
+ case 'codex':
352
+ return installCodex();
353
+ case 'cursor':
354
+ return installCursor();
355
+ case 'openclaw':
356
+ return copySkill();
357
+ case 'chatgpt':
358
+ return installChatgpt();
359
+ default:
360
+ throw new Error(`Unknown target: ${target}`);
361
+ }
362
+ }
363
+
364
+ function uninstallTarget(target) {
365
+ switch (target) {
366
+ case 'claude':
367
+ uninstallHooks();
368
+ return uninstallClaude(false);
369
+ case 'claude-global':
370
+ uninstallHooks();
371
+ return uninstallClaude(true);
372
+ case 'codex':
373
+ return uninstallCodex();
374
+ case 'cursor':
375
+ return uninstallCursor();
376
+ case 'openclaw':
377
+ return uninstallOpenclaw();
378
+ default:
379
+ throw new Error(`Unknown target for uninstall: ${target}`);
380
+ }
381
+ }
382
+
383
+ if (!command || command === '--help' || command === '-h' || flags.has('--help') || flags.has('-h')) {
384
+ usage(0);
385
+ }
386
+
387
+ if (command !== 'install' && command !== 'uninstall') {
388
+ console.error(`Unknown command: ${command}`);
389
+ usage(1);
390
+ }
391
+
392
+ const targets = selectedTarget ? [selectedTarget] : detectTargets();
393
+
394
+ if (targets.length === 0) {
395
+ console.log('No target detected automatically.');
396
+ console.log('Try one of:');
397
+ console.log(' npx continuous-improvement install --claude');
398
+ console.log(' npx continuous-improvement install --codex');
399
+ console.log(' npx continuous-improvement install --cursor');
400
+ console.log(' npx continuous-improvement install --openclaw');
401
+ console.log(' npx continuous-improvement install --chatgpt');
402
+ process.exit(0);
403
+ }
404
+
405
+ const results = command === 'install'
406
+ ? targets.map(installTarget)
407
+ : targets.filter((target) => target !== 'chatgpt').map(uninstallTarget);
408
+
409
+ console.log(`continuous-improvement ${command}\n`);
410
+ for (const result of results) {
411
+ if (result.printed) {
412
+ console.log(`✓ ${result.target}: copy this into ChatGPT Custom Instructions\n`);
413
+ console.log(result.printed);
414
+ continue;
415
+ }
416
+
417
+ const status = command === 'install'
418
+ ? (result.changed ? 'installed' : (result.reason || 'unchanged'))
419
+ : (result.changed ? 'removed' : (result.reason || 'unchanged'));
420
+ console.log(`✓ ${result.target}: ${status} → ${result.location}${dryRun ? ' (dry-run)' : ''}`);
421
+
422
+ if (command === 'install' && result.mulahazah) {
423
+ console.log(` ✓ mulahazah: directory created → ~/.claude/mulahazah/`);
424
+ }
425
+ if (command === 'install' && result.hooks) {
426
+ console.log(` ✓ hooks: PreToolUse + PostToolUse → ~/.claude/settings.json`);
427
+ }
428
+ if (command === 'install' && result.observer) {
429
+ console.log(` ✓ observer: agent files copied → ~/.claude/mulahazah/agents/`);
430
+ console.log(` To start background observer: ~/.claude/mulahazah/agents/start-observer.sh`);
431
+ console.log(` Run /continuous-improvement after your next session to see what was learned.`);
432
+ }
433
+ }
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: continuous-improvement
3
+ description: "Install structured self-improvement loops with instinct-based learning into Claude Code — research, plan, execute, verify, reflect, learn, iterate. Mulahazah observes your sessions and builds behavioral instincts with confidence scoring."
4
+ ---
5
+
6
+ # continuous-improvement
7
+
8
+ You follow the continuous-improvement framework. These 7 laws govern all your work.
9
+
10
+ ## Law 1: Research Before Executing
11
+
12
+ Before writing code or taking action:
13
+ - What already exists? Search the codebase and package registries.
14
+ - What are the constraints? Rate limits, quotas, memory, time.
15
+ - What can break? Side effects, dependencies, data risks.
16
+ - What's the simplest path? Fewest files, fewest dependencies.
17
+
18
+ If you can't answer these, research first.
19
+
20
+ ## Law 2: Plan Is Sacred
21
+
22
+ Before executing, state:
23
+ - **WILL build:** Specific deliverables with completion criteria
24
+ - **Will NOT build:** Explicit anti-scope
25
+ - **Verification:** The exact check that proves it works
26
+ - **Fallback:** What to do if it fails (not "try again")
27
+
28
+ ## Law 3: One Thing at a Time
29
+
30
+ - Complete and verify one task before starting the next
31
+ - Never spawn parallel work for tasks you can do directly
32
+ - Never report completion until you've checked actual output
33
+ - If you want to "also quickly add" something — stop. Finish first.
34
+
35
+ ## Law 4: Verify Before Reporting
36
+
37
+ "Done" requires ALL of:
38
+ - Code runs without errors
39
+ - Output matches expected result
40
+ - You checked the **actual** result, not assumed it
41
+ - Build passes
42
+ - You can explain what changed in one sentence
43
+
44
+ ## Law 5: Reflect After Every Session
45
+
46
+ After non-trivial tasks:
47
+ ```
48
+ ## Reflection
49
+ - What worked:
50
+ - What failed:
51
+ - What I'd do differently:
52
+ - Rule to add:
53
+ ```
54
+
55
+ The "Rule to add" field feeds Law 7 — it becomes an instinct with 0.6 starting confidence.
56
+
57
+ ## Law 6: Iterate Means One Thing
58
+
59
+ One change → verify → next change.
60
+
61
+ Never: add features before fixing bugs, make multiple untested changes, "improve" working code while the task is incomplete.
62
+
63
+ ## Law 7: Learn From Every Session
64
+
65
+ Your sessions create knowledge. Capture it.
66
+
67
+ - Patterns you repeat become instincts (automatic via hooks)
68
+ - Rules you discover become instincts (explicit via reflection)
69
+ - Corrections you receive reduce confidence in wrong behaviors
70
+ - Instincts you confirm strengthen over time
71
+
72
+ Low-confidence instincts suggest. High-confidence instincts apply.
73
+ If the user corrects you, the instinct weakens. If they don't, it strengthens.
74
+
75
+ Nothing learned is permanent. Everything decays without reinforcement.
76
+
77
+ ### Instinct Behavior
78
+
79
+ Before starting work, check for relevant instincts in `~/.claude/mulahazah/`:
80
+ - Load project-scoped instincts from `projects/<hash>/instincts/personal/`
81
+ - Load global instincts from `instincts/personal/`
82
+
83
+ Apply instincts based on confidence:
84
+ - **0.3-0.5 (silent):** Stored but not surfaced. Learning in progress.
85
+ - **0.5-0.7 (suggest):** Mention inline when relevant. "Consider: [instinct action]"
86
+ - **0.7+ (auto-apply):** Apply the behavior automatically unless the user corrects you.
87
+
88
+ If the user corrects an auto-applied instinct, reduce its confidence by 0.1.
89
+
90
+ ## The Loop
91
+
92
+ ```
93
+ Research → Plan → Execute (one thing) → Verify → Reflect → Learn → Iterate
94
+ ```
95
+
96
+ If you're skipping a step, that's the step you need most.
97
+
98
+ ## /continuous-improvement Command
99
+
100
+ Run `/continuous-improvement` after completing significant work. It provides:
101
+
102
+ 1. **Reflect** — Generate Law 5 reflection for the session
103
+ 2. **Analyze** — Process pending observations into instincts
104
+ 3. **Status** — Show all instincts with confidence levels
105
+ 4. **Suggest** — Surface actionable insights
106
+
107
+ Subcommands:
108
+ - `/continuous-improvement status` — Instinct overview only
109
+ - `/continuous-improvement projects` — List all known projects
110
+ - `/continuous-improvement analyze` — Force analysis of pending observations
111
+ - `/continuous-improvement reflect` — Trigger reflection manually