claude-prism 0.1.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,439 @@
1
+ /**
2
+ * claude-prism — Installer
3
+ * Handles init, check, update, uninstall
4
+ */
5
+
6
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, rmSync, readdirSync, renameSync } from 'fs';
7
+ import { join, dirname } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ import { tmpdir } from 'os';
10
+ import { detectOmc } from './omc.mjs';
11
+
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+ const TEMPLATES_DIR = join(__dirname, '..', 'templates');
14
+
15
+ /**
16
+ * Initialize prism in a project
17
+ * @param {string} projectDir - Project root
18
+ * @param {Object} options
19
+ * @param {string} options.language - 'en' | 'ko'
20
+ * @param {boolean} options.hooks - Install enforcement hooks
21
+ */
22
+ export async function init(projectDir, options = {}) {
23
+ const { language = 'en', hooks = true } = options;
24
+
25
+ // 1. Create directories
26
+ const claudeDir = join(projectDir, '.claude');
27
+ const hooksDir = join(claudeDir, 'hooks');
28
+
29
+ // 2. Copy namespaced slash commands
30
+ const nsCommandsDir = join(claudeDir, 'commands', 'claude-prism');
31
+ mkdirSync(nsCommandsDir, { recursive: true });
32
+
33
+ const commandFiles = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md'];
34
+ for (const cmd of commandFiles) {
35
+ copyFileSync(
36
+ join(TEMPLATES_DIR, 'commands', 'claude-prism', cmd),
37
+ join(nsCommandsDir, cmd)
38
+ );
39
+ }
40
+
41
+ // 3. Copy hooks (optional)
42
+ if (hooks) {
43
+ mkdirSync(hooksDir, { recursive: true });
44
+
45
+ // Copy runner scripts (executable wrappers Claude Code calls)
46
+ const runnersDir = join(TEMPLATES_DIR, 'runners');
47
+ copyFileSync(join(runnersDir, 'commit-guard.mjs'), join(hooksDir, 'commit-guard.mjs'));
48
+ copyFileSync(join(runnersDir, 'debug-loop.mjs'), join(hooksDir, 'debug-loop.mjs'));
49
+ copyFileSync(join(runnersDir, 'test-tracker.mjs'), join(hooksDir, 'test-tracker.mjs'));
50
+ copyFileSync(join(runnersDir, 'scope-guard.mjs'), join(hooksDir, 'scope-guard.mjs'));
51
+
52
+ // Copy rule logic files
53
+ const rulesDestDir = join(claudeDir, 'rules');
54
+ mkdirSync(rulesDestDir, { recursive: true });
55
+ const hooksSourceDir = join(__dirname, '..', 'hooks');
56
+ copyFileSync(join(hooksSourceDir, 'commit-guard.mjs'), join(rulesDestDir, 'commit-guard.mjs'));
57
+ copyFileSync(join(hooksSourceDir, 'debug-loop.mjs'), join(rulesDestDir, 'debug-loop.mjs'));
58
+ copyFileSync(join(hooksSourceDir, 'test-tracker.mjs'), join(rulesDestDir, 'test-tracker.mjs'));
59
+ copyFileSync(join(hooksSourceDir, 'scope-guard.mjs'), join(rulesDestDir, 'scope-guard.mjs'));
60
+
61
+ // Copy lib dependencies (adapter + state + config + utils)
62
+ const libDestDir = join(claudeDir, 'lib');
63
+ mkdirSync(libDestDir, { recursive: true });
64
+ const libSourceDir = join(__dirname);
65
+ for (const file of ['adapter.mjs', 'state.mjs', 'config.mjs', 'utils.mjs']) {
66
+ copyFileSync(join(libSourceDir, file), join(libDestDir, file));
67
+ }
68
+
69
+ // Merge settings.json
70
+ mergeSettings(claudeDir);
71
+ }
72
+
73
+ // 4. Inject rules into CLAUDE.md
74
+ injectRules(projectDir, language);
75
+
76
+ // 5. Create .claude-prism.json config
77
+ const configPath = join(projectDir, '.claude-prism.json');
78
+ if (!existsSync(configPath)) {
79
+ writeFileSync(configPath, JSON.stringify({
80
+ language,
81
+ hooks: {
82
+ 'commit-guard': { enabled: true, maxTestAge: 300 },
83
+ 'debug-loop': { enabled: true, warnAt: 3, blockAt: 5 },
84
+ 'test-tracker': { enabled: true },
85
+ 'scope-guard': { enabled: true, warnAt: 4, blockAt: 7, agentWarnAt: 8, agentBlockAt: 12 }
86
+ }
87
+ }, null, 2) + '\n');
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Check installation status
93
+ * @param {string} projectDir
94
+ * @returns {{ commands: boolean, rules: boolean, hooks: boolean, config: boolean, ok: boolean }}
95
+ */
96
+ export function check(projectDir) {
97
+ const claudeDir = join(projectDir, '.claude');
98
+
99
+ const nsCommandsDir = join(claudeDir, 'commands', 'claude-prism');
100
+ const commands = existsSync(join(nsCommandsDir, 'prism.md'))
101
+ && existsSync(join(nsCommandsDir, 'checkpoint.md'))
102
+ && existsSync(join(nsCommandsDir, 'plan.md'))
103
+ && existsSync(join(nsCommandsDir, 'help.md'));
104
+
105
+ const claudeMdPath = join(projectDir, 'CLAUDE.md');
106
+ const rules = existsSync(claudeMdPath)
107
+ && readFileSync(claudeMdPath, 'utf8').includes('<!-- PRISM:START -->');
108
+
109
+ const hooks = existsSync(join(claudeDir, 'hooks', 'commit-guard.mjs'))
110
+ && existsSync(join(claudeDir, 'hooks', 'debug-loop.mjs'))
111
+ && existsSync(join(claudeDir, 'hooks', 'test-tracker.mjs'))
112
+ && existsSync(join(claudeDir, 'hooks', 'scope-guard.mjs'));
113
+
114
+ const config = existsSync(join(projectDir, '.claude-prism.json'));
115
+
116
+ return {
117
+ commands,
118
+ rules,
119
+ hooks,
120
+ config,
121
+ ok: commands && rules && config
122
+ };
123
+ }
124
+
125
+ /**
126
+ * Uninstall prism from a project
127
+ * @param {string} projectDir
128
+ */
129
+ export function uninstall(projectDir) {
130
+ const claudeDir = join(projectDir, '.claude');
131
+
132
+ // 1. Remove PRISM block from CLAUDE.md
133
+ const claudeMdPath = join(projectDir, 'CLAUDE.md');
134
+ if (existsSync(claudeMdPath)) {
135
+ const content = readFileSync(claudeMdPath, 'utf8');
136
+ const startMarker = '<!-- PRISM:START -->';
137
+ const endMarker = '<!-- PRISM:END -->';
138
+ if (content.includes(startMarker) && content.includes(endMarker)) {
139
+ const before = content.slice(0, content.indexOf(startMarker));
140
+ const after = content.slice(content.indexOf(endMarker) + endMarker.length);
141
+ writeFileSync(claudeMdPath, (before + after).replace(/\n{3,}/g, '\n\n').trim() + '\n');
142
+ }
143
+ }
144
+
145
+ // 2. Remove namespaced commands directory
146
+ const nsCommandsDir = join(claudeDir, 'commands', 'claude-prism');
147
+ if (existsSync(nsCommandsDir)) rmSync(nsCommandsDir, { recursive: true });
148
+
149
+ // 2b. Remove legacy flat commands (migration cleanup)
150
+ for (const cmd of ['prism.md', 'checkpoint.md']) {
151
+ const p = join(claudeDir, 'commands', cmd);
152
+ if (existsSync(p)) rmSync(p);
153
+ }
154
+
155
+ // 3. Remove prism hooks
156
+ for (const hook of ['commit-guard.mjs', 'debug-loop.mjs', 'test-tracker.mjs', 'scope-guard.mjs']) {
157
+ const p = join(claudeDir, 'hooks', hook);
158
+ if (existsSync(p)) rmSync(p);
159
+ }
160
+
161
+ // 4. Remove rules/ and lib/ directories
162
+ const rulesDir = join(claudeDir, 'rules');
163
+ if (existsSync(rulesDir)) rmSync(rulesDir, { recursive: true });
164
+ const libDir = join(claudeDir, 'lib');
165
+ if (existsSync(libDir)) rmSync(libDir, { recursive: true });
166
+
167
+ // 5. Clean prism hooks from settings.json
168
+ const settingsPath = join(claudeDir, 'settings.json');
169
+ if (existsSync(settingsPath)) {
170
+ const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
171
+ if (settings.hooks) {
172
+ for (const [event, hookList] of Object.entries(settings.hooks)) {
173
+ settings.hooks[event] = hookList.filter(
174
+ h => !h.hooks?.some(hh => hh.command?.includes('commit-guard') || hh.command?.includes('debug-loop') || hh.command?.includes('test-tracker') || hh.command?.includes('scope-guard'))
175
+ );
176
+ if (settings.hooks[event].length === 0) delete settings.hooks[event];
177
+ }
178
+ }
179
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
180
+ }
181
+
182
+ // 6. Remove .claude-prism.json and legacy .prism.json
183
+ const configPath = join(projectDir, '.claude-prism.json');
184
+ if (existsSync(configPath)) rmSync(configPath);
185
+ const legacyConfigPath = join(projectDir, '.prism.json');
186
+ if (existsSync(legacyConfigPath)) rmSync(legacyConfigPath);
187
+ }
188
+
189
+ /**
190
+ * Update prism — re-install using existing config
191
+ * @param {string} projectDir
192
+ */
193
+ export async function update(projectDir) {
194
+ // Migration: rename .prism.json to .claude-prism.json
195
+ const oldConfigPath = join(projectDir, '.prism.json');
196
+ const newConfigPath = join(projectDir, '.claude-prism.json');
197
+ if (existsSync(oldConfigPath) && !existsSync(newConfigPath)) {
198
+ renameSync(oldConfigPath, newConfigPath);
199
+ }
200
+
201
+ const configPath = newConfigPath;
202
+ let language = 'en';
203
+ let hooks = true;
204
+
205
+ if (existsSync(configPath)) {
206
+ const config = JSON.parse(readFileSync(configPath, 'utf8'));
207
+ language = config.language || 'en';
208
+ hooks = config.hooks?.['commit-guard']?.enabled !== false;
209
+ }
210
+
211
+ // Migration: remove legacy flat commands before re-init
212
+ const claudeDir = join(projectDir, '.claude');
213
+ for (const cmd of ['prism.md', 'checkpoint.md']) {
214
+ const p = join(claudeDir, 'commands', cmd);
215
+ if (existsSync(p)) rmSync(p);
216
+ }
217
+
218
+ // Migration: remove deprecated namespaced commands
219
+ for (const cmd of ['understand.md']) {
220
+ const p = join(claudeDir, 'commands', 'claude-prism', cmd);
221
+ if (existsSync(p)) rmSync(p);
222
+ }
223
+
224
+ // Remove old config so init creates a fresh one
225
+ if (existsSync(configPath)) rmSync(configPath);
226
+
227
+ await init(projectDir, { language, hooks });
228
+ }
229
+
230
+ /**
231
+ * Diagnose installation issues with actionable fix suggestions
232
+ * @param {string} projectDir
233
+ * @param {Object} [options]
234
+ * @param {string} [options.homeDir] - Override home dir (for testing)
235
+ * @returns {{ healthy: boolean, issues: string[], fixes: string[], omc: Object }}
236
+ */
237
+ export function doctor(projectDir, options = {}) {
238
+ const claudeDir = join(projectDir, '.claude');
239
+ const issues = [];
240
+ const fixes = [];
241
+
242
+ // Check namespaced commands
243
+ const nsCommandsDir = join(claudeDir, 'commands', 'claude-prism');
244
+ const expectedCommands = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md'];
245
+ for (const cmd of expectedCommands) {
246
+ if (!existsSync(join(nsCommandsDir, cmd))) {
247
+ issues.push(`Missing command: claude-prism/${cmd}`);
248
+ fixes.push('Run `prism update` to restore missing files');
249
+ }
250
+ }
251
+
252
+ // Check for legacy flat commands (need migration)
253
+ for (const cmd of ['prism.md', 'checkpoint.md']) {
254
+ if (existsSync(join(claudeDir, 'commands', cmd))) {
255
+ issues.push(`Legacy command found: ${cmd} (needs migration to namespace)`);
256
+ fixes.push('Run `prism update` to migrate to namespaced commands');
257
+ }
258
+ }
259
+
260
+ // Check hooks
261
+ for (const hook of ['commit-guard.mjs', 'debug-loop.mjs', 'test-tracker.mjs', 'scope-guard.mjs']) {
262
+ if (!existsSync(join(claudeDir, 'hooks', hook))) {
263
+ issues.push(`Missing hook: ${hook}`);
264
+ fixes.push('Run `prism update` to restore missing files');
265
+ }
266
+ }
267
+
268
+ // Check CLAUDE.md
269
+ const claudeMdPath = join(projectDir, 'CLAUDE.md');
270
+ if (!existsSync(claudeMdPath)) {
271
+ issues.push('CLAUDE.md not found');
272
+ fixes.push('Run `prism update` to regenerate CLAUDE.md rules');
273
+ } else {
274
+ const content = readFileSync(claudeMdPath, 'utf8');
275
+ if (!content.includes('<!-- PRISM:START -->')) {
276
+ issues.push('CLAUDE.md missing PRISM rules block');
277
+ fixes.push('Run `prism update` to re-inject rules');
278
+ }
279
+ }
280
+
281
+ // Check config
282
+ if (!existsSync(join(projectDir, '.claude-prism.json'))) {
283
+ issues.push('Missing .claude-prism.json config');
284
+ fixes.push('Run `prism init` to create config');
285
+ }
286
+
287
+ // Check for legacy .prism.json
288
+ if (existsSync(join(projectDir, '.prism.json'))) {
289
+ issues.push('Legacy .prism.json found (needs migration to .claude-prism.json)');
290
+ fixes.push('Run `prism update` to migrate');
291
+ }
292
+
293
+ // Check rules/ and lib/
294
+ if (!existsSync(join(claudeDir, 'rules'))) {
295
+ issues.push('Missing .claude/rules/ directory');
296
+ fixes.push('Run `prism update` to restore');
297
+ }
298
+ if (!existsSync(join(claudeDir, 'lib'))) {
299
+ issues.push('Missing .claude/lib/ directory');
300
+ fixes.push('Run `prism update` to restore');
301
+ }
302
+
303
+ // Deduplicate fixes
304
+ const uniqueFixes = [...new Set(fixes)];
305
+
306
+ // Detect OMC
307
+ const omc = detectOmc(options.homeDir);
308
+
309
+ return {
310
+ healthy: issues.length === 0,
311
+ issues,
312
+ fixes: uniqueFixes,
313
+ omc
314
+ };
315
+ }
316
+
317
+ /**
318
+ * Show installation statistics
319
+ * @param {string} projectDir
320
+ * @param {Object} [options]
321
+ * @param {string} [options.homeDir] - Override home dir (for testing)
322
+ * @returns {{ version: string, language: string, hooks: Object, planFiles: number, omc: Object }}
323
+ */
324
+ export function stats(projectDir, options = {}) {
325
+ // Read version from package.json
326
+ const pkgPath = join(__dirname, '..', 'package.json');
327
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
328
+
329
+ // Read config
330
+ const configPath = join(projectDir, '.claude-prism.json');
331
+ let language = 'en';
332
+ let hookConfig = {};
333
+
334
+ if (existsSync(configPath)) {
335
+ const config = JSON.parse(readFileSync(configPath, 'utf8'));
336
+ language = config.language || 'en';
337
+ if (config.hooks) {
338
+ for (const [name, cfg] of Object.entries(config.hooks)) {
339
+ hookConfig[name] = cfg.enabled !== false;
340
+ }
341
+ }
342
+ }
343
+
344
+ // Count plan files
345
+ let planFiles = 0;
346
+ const plansDir = join(projectDir, 'docs', 'plans');
347
+ if (existsSync(plansDir)) {
348
+ planFiles = readdirSync(plansDir).filter(f => f.endsWith('.md')).length;
349
+ }
350
+
351
+ // Detect OMC
352
+ const omc = detectOmc(options.homeDir);
353
+
354
+ return {
355
+ version: pkg.version,
356
+ language,
357
+ hooks: hookConfig,
358
+ planFiles,
359
+ omc
360
+ };
361
+ }
362
+
363
+ /**
364
+ * Reset hook state (clear edit counters, test timestamps)
365
+ * @returns {boolean}
366
+ */
367
+ export function reset() {
368
+ const stateRoot = join(tmpdir(), '.prism');
369
+ if (existsSync(stateRoot)) {
370
+ rmSync(stateRoot, { recursive: true });
371
+ }
372
+ return true;
373
+ }
374
+
375
+ // ─── internal helpers ───
376
+
377
+ function injectRules(projectDir, language) {
378
+ const claudeMdPath = join(projectDir, 'CLAUDE.md');
379
+ const rulesFile = `rules.${language}.md`;
380
+ const rulesPath = join(TEMPLATES_DIR, rulesFile);
381
+
382
+ if (!existsSync(rulesPath)) {
383
+ // Fallback to English
384
+ const fallback = join(TEMPLATES_DIR, 'rules.en.md');
385
+ if (!existsSync(fallback)) return;
386
+ }
387
+
388
+ const rules = readFileSync(existsSync(rulesPath) ? rulesPath : join(TEMPLATES_DIR, 'rules.en.md'), 'utf8');
389
+
390
+ let existing = '';
391
+ if (existsSync(claudeMdPath)) {
392
+ existing = readFileSync(claudeMdPath, 'utf8');
393
+ }
394
+
395
+ // Replace existing PRISM block or append
396
+ const startMarker = '<!-- PRISM:START -->';
397
+ const endMarker = '<!-- PRISM:END -->';
398
+
399
+ if (existing.includes(startMarker) && existing.includes(endMarker)) {
400
+ const before = existing.slice(0, existing.indexOf(startMarker));
401
+ const after = existing.slice(existing.indexOf(endMarker) + endMarker.length);
402
+ writeFileSync(claudeMdPath, before + rules + after);
403
+ } else {
404
+ writeFileSync(claudeMdPath, existing + '\n' + rules);
405
+ }
406
+ }
407
+
408
+ function mergeSettings(claudeDir) {
409
+ const settingsPath = join(claudeDir, 'settings.json');
410
+ const templatePath = join(TEMPLATES_DIR, 'settings.json');
411
+
412
+ const template = JSON.parse(readFileSync(templatePath, 'utf8'));
413
+
414
+ if (existsSync(settingsPath)) {
415
+ const existing = JSON.parse(readFileSync(settingsPath, 'utf8'));
416
+
417
+ // Merge hooks arrays by event type
418
+ if (!existing.hooks) existing.hooks = {};
419
+ for (const [event, hookList] of Object.entries(template.hooks)) {
420
+ if (!existing.hooks[event]) {
421
+ existing.hooks[event] = hookList;
422
+ } else {
423
+ // Add prism hooks that don't already exist
424
+ for (const hook of hookList) {
425
+ const alreadyExists = existing.hooks[event].some(
426
+ h => h.hooks?.[0]?.command === hook.hooks?.[0]?.command
427
+ );
428
+ if (!alreadyExists) {
429
+ existing.hooks[event].push(hook);
430
+ }
431
+ }
432
+ }
433
+ }
434
+
435
+ writeFileSync(settingsPath, JSON.stringify(existing, null, 2) + '\n');
436
+ } else {
437
+ writeFileSync(settingsPath, JSON.stringify(template, null, 2) + '\n');
438
+ }
439
+ }
package/lib/omc.mjs ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * claude-prism — OMC (oh-my-claudecode) Detection
3
+ * Detects OMC installation and extracts version info
4
+ */
5
+
6
+ import { existsSync, readFileSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+
10
+ /**
11
+ * Detect oh-my-claudecode installation
12
+ * @param {string} [homeDir] - Override home directory (for testing)
13
+ * @returns {{ detected: boolean, version: string|null }}
14
+ */
15
+ export function detectOmc(homeDir) {
16
+ const home = homeDir || homedir();
17
+ const claudeMdPath = join(home, '.claude', 'CLAUDE.md');
18
+
19
+ if (!existsSync(claudeMdPath)) {
20
+ return { detected: false, version: null };
21
+ }
22
+
23
+ try {
24
+ const content = readFileSync(claudeMdPath, 'utf8');
25
+
26
+ if (!content.includes('<!-- OMC:START -->')) {
27
+ return { detected: false, version: null };
28
+ }
29
+
30
+ // Extract version from "Unified Agents (vX.Y.Z)" pattern
31
+ const versionMatch = content.match(/\(v(\d+\.\d+\.\d+)\)/);
32
+ const version = versionMatch ? versionMatch[1] : null;
33
+
34
+ return { detected: true, version };
35
+ } catch {
36
+ return { detected: false, version: null };
37
+ }
38
+ }
package/lib/state.mjs ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * claude-prism — State Management
3
+ * File-based state storage for hook evaluation
4
+ */
5
+
6
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { tmpdir } from 'os';
9
+
10
+ const STATE_ROOT = join(tmpdir(), '.prism');
11
+
12
+ export function getStateDir(sessionId, agentId) {
13
+ const key = agentId && agentId !== 'default' ? `${sessionId}-${agentId}` : sessionId;
14
+ const dir = join(STATE_ROOT, key);
15
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
16
+ return dir;
17
+ }
18
+
19
+ export function readState(stateDir, key) {
20
+ const file = join(stateDir, key);
21
+ if (!existsSync(file)) return null;
22
+ try {
23
+ return readFileSync(file, 'utf8');
24
+ } catch {
25
+ return null;
26
+ }
27
+ }
28
+
29
+ export function writeState(stateDir, key, value) {
30
+ writeFileSync(join(stateDir, key), value, { mode: 0o600 });
31
+ }
32
+
33
+ export function readJsonState(stateDir, key) {
34
+ const raw = readState(stateDir, key);
35
+ if (raw === null) return null;
36
+ try {
37
+ return JSON.parse(raw);
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+
43
+ export function writeJsonState(stateDir, key, value) {
44
+ writeState(stateDir, key, JSON.stringify(value));
45
+ }
46
+
47
+ export function incrementCounter(stateDir, key) {
48
+ const current = parseInt(readState(stateDir, key) || '0', 10) || 0;
49
+ const next = current + 1;
50
+ writeState(stateDir, key, String(next));
51
+ return next;
52
+ }
package/lib/utils.mjs ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * claude-prism — Shared Utilities
3
+ */
4
+
5
+ export function sanitizeId(id) {
6
+ if (!id || typeof id !== 'string') return 'default';
7
+ return id.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 128) || 'default';
8
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "claude-prism",
3
+ "version": "0.1.0",
4
+ "description": "AI coding problem decomposition tool — Understand, Decompose, Execute, Checkpoint.",
5
+ "type": "module",
6
+ "bin": {
7
+ "prism": "./bin/cli.mjs"
8
+ },
9
+ "scripts": {
10
+ "test": "node --test tests/*.test.mjs"
11
+ },
12
+ "keywords": [
13
+ "ai",
14
+ "claude",
15
+ "claude-code",
16
+ "tdd",
17
+ "decomposition",
18
+ "methodology"
19
+ ],
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "files": [
24
+ "bin/",
25
+ "lib/",
26
+ "hooks/",
27
+ "templates/",
28
+ "README.md",
29
+ "README.ko.md"
30
+ ],
31
+ "author": "lazysaturday91",
32
+ "license": "MIT"
33
+ }
@@ -0,0 +1,34 @@
1
+ # /claude-prism:checkpoint — Progress Check
2
+
3
+ When this command is invoked:
4
+
5
+ 1. **Read the plan file** from `docs/plans/` (most recent matching file)
6
+ 2. **Check completed tasks** (marked with [x] in the plan)
7
+ 3. **Report current status** using this standard format:
8
+
9
+ ### Changes
10
+
11
+ | Item | Before | After |
12
+ |------|--------|-------|
13
+ | [what changed] | [old behavior/state] | [new behavior/state] |
14
+
15
+ ### Verification
16
+
17
+ | Check | Result |
18
+ |-------|--------|
19
+ | TypeScript | ✅/❌ [details] |
20
+ | Tests | ✅/❌ [pass count] |
21
+ | Lint | ✅/❌ or N/A |
22
+
23
+ ### Progress
24
+
25
+ - Batches complete: N/M
26
+ - Current batch: [name] — [X/Y tasks done]
27
+ - Remaining: [batch names]
28
+ - Blockers: [any issues encountered]
29
+
30
+ 4. **Show summary**:
31
+ - Files created/modified so far
32
+ - Tests added and their status
33
+ - Commits made
34
+ 5. **Ask**: "Continue with the current plan, adjust, or stop?"
@@ -0,0 +1,42 @@
1
+ # /claude-prism:doctor — Installation Diagnostics
2
+
3
+ When this command is invoked, check all components of the prism installation:
4
+
5
+ ## Checks
6
+
7
+ 1. **CLAUDE.md**: Does it contain `<!-- PRISM:START -->` marker?
8
+ 2. **Config**: Does `.claude-prism.json` exist? Is it valid JSON?
9
+ 3. **Commands**: Do these files exist in `.claude/commands/claude-prism/`?
10
+ - prism.md, checkpoint.md, plan.md, doctor.md, stats.md, help.md
11
+ 4. **Hooks**: Do these files exist in `.claude/hooks/`?
12
+ - commit-guard.mjs, debug-loop.mjs, test-tracker.mjs, scope-guard.mjs
13
+ 5. **Rules**: Do these files exist in `.claude/rules/`?
14
+ - commit-guard.mjs, debug-loop.mjs, test-tracker.mjs, scope-guard.mjs
15
+ 6. **Lib**: Do these files exist in `.claude/lib/`?
16
+ - adapter.mjs, state.mjs, config.mjs, utils.mjs
17
+ 7. **Settings**: Does `.claude/settings.json` contain prism hook registrations?
18
+ 8. **Legacy**: Are there old flat commands (`/prism`, `/checkpoint`) that need migration?
19
+
20
+ ## Report Format
21
+
22
+ ```
23
+ 🌈 claude-prism doctor
24
+
25
+ CLAUDE.md: ✅ PRISM rules present
26
+ Config: ✅ .claude-prism.json valid
27
+ Commands: ✅ 7/7 installed
28
+ Hooks: ✅ 4/4 installed
29
+ Rules: ✅ 4/4 installed
30
+ Lib: ✅ 4/4 installed
31
+ Settings: ✅ Hooks registered
32
+ Legacy: ✅ No old commands found
33
+
34
+ Status: ✅ Healthy
35
+ ```
36
+
37
+ ## Fix Suggestions
38
+
39
+ For each issue found, suggest the fix:
40
+ - Missing files → "Run `prism update` to restore"
41
+ - Legacy commands → "Run `prism update` to migrate to namespaced commands"
42
+ - Missing PRISM block → "Run `prism update` to re-inject rules"
@@ -0,0 +1,42 @@
1
+ # /claude-prism:help — Command Reference
2
+
3
+ ## Available Commands
4
+
5
+ | Command | Description |
6
+ |---------|-------------|
7
+ | `/claude-prism:prism` | Start full UDEC workflow (Understand → Decompose → Execute → Checkpoint). Also handles analysis-only requests — stops after U phase when no code change is needed. |
8
+ | `/claude-prism:checkpoint` | Check current batch progress, show next batch preview |
9
+ | `/claude-prism:plan` | List, create, or view plan files in `docs/plans/` |
10
+ | `/claude-prism:doctor` | Diagnose installation health and suggest fixes |
11
+ | `/claude-prism:stats` | Show project statistics, hook status, and plan progress |
12
+ | `/claude-prism:help` | This reference |
13
+
14
+ ## Quick Start
15
+
16
+ 1. Before any task (code or analysis): `/claude-prism:prism`
17
+ 2. Mid-project progress check: `/claude-prism:checkpoint`
18
+ 3. Create a new plan: `/claude-prism:plan`
19
+
20
+ ## CLI Commands
21
+
22
+ These are also available from the terminal:
23
+
24
+ ```bash
25
+ prism init [--lang=XX] [--no-hooks] # Install prism
26
+ prism check [--ci] # Verify installation
27
+ prism doctor # Diagnose issues
28
+ prism stats # Show summary
29
+ prism reset # Clear hook state
30
+ prism update # Re-install / migrate
31
+ prism uninstall # Remove prism
32
+ ```
33
+
34
+ ## UDEC Framework
35
+
36
+ ```
37
+ U — Understand: Assess sufficiency, ask questions, confirm alignment
38
+ (analysis-only requests stop here with findings report)
39
+ D — Decompose: Break into 2-5 min units, create plan file
40
+ E — Execute: Batch (3-4 tasks), TDD each unit, scope guard
41
+ C — Checkpoint: Report with before/after table, get confirmation
42
+ ```