claude-prism 1.0.0 → 1.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.
- package/README.md +90 -36
- package/bin/cli.mjs +76 -5
- package/hooks/plan-enforcement.mjs +1 -1
- package/lib/installer.mjs +86 -4
- package/lib/messages.mjs +1 -1
- package/package.json +3 -2
- package/templates/commands/claude-prism/help.md +3 -2
- package/templates/commands/claude-prism/hud.md +65 -0
- package/templates/commands/claude-prism/plan.md +1 -1
- package/templates/commands/claude-prism/prism.md +52 -31
- package/templates/hud/omc-hud.mjs +197 -0
- package/templates/rules.md +64 -20
- package/templates/skills/prism/SKILL.md +26 -4
package/README.md
CHANGED
|
@@ -1,73 +1,79 @@
|
|
|
1
1
|
```
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
╱╲
|
|
3
|
+
━━━━━━━━━▶ ╱ ╲ ── E Essence
|
|
4
|
+
complex ╱ ╲ ── U Understand
|
|
5
|
+
problem ╱ PRISM╲── D Decompose
|
|
6
|
+
╱ ╲─ E Execute
|
|
7
|
+
╱__________╲─ C Checkpoint
|
|
7
8
|
```
|
|
8
9
|
|
|
9
10
|
[](https://www.npmjs.com/package/claude-prism)
|
|
10
11
|
[](https://github.com/lazysaturday91/claude-prism/blob/main/LICENSE)
|
|
11
12
|
[](https://nodejs.org)
|
|
13
|
+
[](https://github.com/lazysaturday91/claude-prism/actions/workflows/ci.yml)
|
|
12
14
|
|
|
13
|
-
> `ai-coding` · `methodology` · `
|
|
15
|
+
> `ai-coding` · `methodology` · `eudec` · `claude-code`
|
|
14
16
|
|
|
15
17
|
# claude-prism
|
|
16
18
|
|
|
17
|
-
**
|
|
19
|
+
**EUDEC methodology framework for AI coding agents.**
|
|
18
20
|
|
|
19
|
-
Installs the
|
|
21
|
+
Installs the EUDEC methodology — **Essence, Understand, Decompose, Execute, Checkpoint** — directly into your project's Claude Code environment. Includes a session transition protocol (Handoff) that bookends the core cycle. Three lightweight hooks enforce the methodology where it matters most.
|
|
20
22
|
|
|
21
23
|
## The Problem
|
|
22
24
|
|
|
23
25
|
AI coding agents fail in predictable ways:
|
|
24
26
|
|
|
25
|
-
| Failure Mode | What Happens |
|
|
27
|
+
| Failure Mode | What Happens | EUDEC Fix |
|
|
26
28
|
|---|---|---|
|
|
29
|
+
| Skip essence extraction | Solves the wrong problem entirely | ESSENCE phase |
|
|
27
30
|
| Skip understanding | Builds the wrong thing for 30 minutes | UNDERSTAND phase |
|
|
28
31
|
| No decomposition | One massive change that's hard to review | DECOMPOSE into verifiable batches |
|
|
29
|
-
| No verification | "should work" without evidence | Risk-based verification
|
|
30
|
-
| Scope creep | "While I'm here..." changes nobody asked for | Scope Guard
|
|
31
|
-
| Context loss | New session = start from scratch | HANDOFF
|
|
32
|
+
| No verification | "should work" without evidence | Risk-based verification + Fallback Ladder |
|
|
33
|
+
| Scope creep | "While I'm here..." changes nobody asked for | Scope Guard + Thrashing Detector |
|
|
34
|
+
| Context loss | New session = start from scratch | HANDOFF + Project Memory |
|
|
32
35
|
|
|
33
36
|
**The biggest failure mode of AI coding isn't bad code — it's building the wrong thing.**
|
|
34
37
|
|
|
35
38
|
## Core Philosophy
|
|
36
39
|
|
|
37
|
-
> Never implement what you haven't understood. Never
|
|
40
|
+
> Never implement what you haven't understood. Never understand what you haven't distilled to its essence.
|
|
38
41
|
|
|
39
42
|
## What Prism Provides
|
|
40
43
|
|
|
41
|
-
### 1.
|
|
44
|
+
### 1. EUDEC Methodology (the core product)
|
|
42
45
|
|
|
43
|
-
Injected into `CLAUDE.md`,
|
|
46
|
+
Injected into `CLAUDE.md`, EUDEC is a behavioral framework that corrects how AI agents approach tasks:
|
|
44
47
|
|
|
45
48
|
```
|
|
46
|
-
|
|
47
|
-
│
|
|
48
|
-
|
|
49
|
-
┌─────────────────── UDEC Core Cycle ───────────────────┐
|
|
49
|
+
┌─────────────────── EUDEC Core Cycle ──────────────────┐
|
|
50
|
+
│ ESSENCE ── Extract core problem → simplify → expand │
|
|
51
|
+
│ │ Task type derivation from essence │
|
|
50
52
|
│ UNDERSTAND ── Sufficiency assessment → ask → align │
|
|
51
|
-
│ │
|
|
52
|
-
│ DECOMPOSE ── Batches → plan file
|
|
53
|
-
│ │
|
|
53
|
+
│ │ Environment validation │
|
|
54
|
+
│ DECOMPOSE ── Batches → plan file → quality gate │
|
|
55
|
+
│ │ Codebase audit → cross-plan check │
|
|
54
56
|
│ EXECUTE ── Adaptive batches → risk-based verification │
|
|
55
|
-
│ │
|
|
56
|
-
│ CHECKPOINT ── Report with evidence →
|
|
57
|
+
│ │ Goal recitation → thrashing detection │
|
|
58
|
+
│ CHECKPOINT ── Report with evidence → plan-reality sync │
|
|
57
59
|
│ (loops back for next batch) │
|
|
58
60
|
└────────────────────────────────────────────────────────┘
|
|
59
61
|
│
|
|
60
62
|
▼
|
|
61
|
-
HANDOFF ── Session transition doc
|
|
63
|
+
HANDOFF ── Session transition doc + Project Memory
|
|
62
64
|
(exit protocol)
|
|
63
65
|
```
|
|
64
66
|
|
|
65
67
|
**Task-type aware**: Each task type (bugfix, feature, migration, refactor, investigation) follows a different optimal path. Migrations skip per-file decomposition. Bugfixes skip straight to locate-fix-verify. Investigations skip decomposition entirely.
|
|
66
68
|
|
|
67
|
-
**Risk-based verification
|
|
68
|
-
- **High risk** (business logic, auth, state machines): TDD required
|
|
69
|
+
**Risk-based verification** with Fallback Ladder:
|
|
70
|
+
- **High risk** (business logic, auth, state machines): TDD required + negative tests
|
|
69
71
|
- **Medium risk** (new components, API integration): Build + runtime check
|
|
70
72
|
- **Low risk** (imports, types, renaming): Build/lint passes
|
|
73
|
+
- **No test infra** (legacy PHP, WordPress): Grep-based static check + syntax validation
|
|
74
|
+
- Fallback: Automated Tests → Approval Testing → Build → Lint → Smoke Check → Manual Diff
|
|
75
|
+
|
|
76
|
+
**Quality gates** between phases prevent executing on broken baselines.
|
|
71
77
|
|
|
72
78
|
### 2. Three Focused Hooks
|
|
73
79
|
|
|
@@ -85,18 +91,56 @@ Hooks enforce the methodology at critical points. All three are deterministic (n
|
|
|
85
91
|
|
|
86
92
|
| Command | Purpose |
|
|
87
93
|
|---------|---------|
|
|
88
|
-
| `/claude-prism:prism` | Run full
|
|
89
|
-
| `/claude-prism:checkpoint` | Check batch progress |
|
|
94
|
+
| `/claude-prism:prism` | Run full EUDEC cycle |
|
|
95
|
+
| `/claude-prism:checkpoint` | Check batch progress with plan-reality sync |
|
|
90
96
|
| `/claude-prism:plan` | List/create/view plan files |
|
|
97
|
+
| `/claude-prism:analytics` | Show usage analytics (blocks, warns, tests) |
|
|
91
98
|
| `/claude-prism:doctor` | Diagnose installation health |
|
|
92
99
|
| `/claude-prism:stats` | Version, hooks, plan count |
|
|
93
100
|
| `/claude-prism:update` | Update to latest version |
|
|
101
|
+
| `/claude-prism:hud` | Manage the statusline HUD |
|
|
94
102
|
| `/claude-prism:help` | Command reference |
|
|
95
103
|
|
|
104
|
+
### 4. HUD Statusline
|
|
105
|
+
|
|
106
|
+
Prism includes an optional statusline HUD for Claude Code that shows live project context at the bottom of the terminal:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
⚡ my-project:main | Opus 4.6 | 🔋84% | 11:17
|
|
110
|
+
📋 auth-refactor 60%(6/10) | 💾 fix: token validation (2h)
|
|
111
|
+
📊 세션 45%(30m) │ 주간92%(목 19:00)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
| Line | Content |
|
|
115
|
+
|------|---------|
|
|
116
|
+
| 1 | Project:branch · model · context % · time |
|
|
117
|
+
| 2 | Active plan progress · last commit · test status |
|
|
118
|
+
| 3 | Session and weekly usage (when available) |
|
|
119
|
+
|
|
120
|
+
Enable during install (interactive prompt) or at any time:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
prism hud enable # Install script + update ~/.claude/settings.json
|
|
124
|
+
prism hud disable # Remove statusLine setting
|
|
125
|
+
prism hud # Show current status
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Or from within Claude Code: `/claude-prism:hud enable`
|
|
129
|
+
|
|
130
|
+
### 4. Analytics
|
|
131
|
+
|
|
132
|
+
Hook events (blocks, warnings) are automatically logged to session files. View aggregated statistics:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
prism analytics # Summary across all sessions
|
|
136
|
+
prism analytics --detail # Include per-session breakdown
|
|
137
|
+
```
|
|
138
|
+
|
|
96
139
|
## Installation
|
|
97
140
|
|
|
98
141
|
```bash
|
|
99
|
-
npx claude-prism init # Install with hooks
|
|
142
|
+
npx claude-prism init # Install with hooks (prompts for HUD)
|
|
143
|
+
npx claude-prism init --hud # Install + auto-enable HUD
|
|
100
144
|
npx claude-prism init --no-hooks # Methodology only, no hooks
|
|
101
145
|
npx claude-prism init --global # Global skill (all projects)
|
|
102
146
|
npx claude-prism init --dry-run # Preview what would be installed
|
|
@@ -106,15 +150,18 @@ npx claude-prism init --dry-run # Preview what would be installed
|
|
|
106
150
|
|
|
107
151
|
```
|
|
108
152
|
your-project/
|
|
109
|
-
├── CLAUDE.md #
|
|
153
|
+
├── CLAUDE.md # EUDEC methodology injected
|
|
110
154
|
├── .claude-prism.json # Hook configuration
|
|
111
155
|
├── .claude/
|
|
112
|
-
│ ├── commands/claude-prism/ #
|
|
156
|
+
│ ├── commands/claude-prism/ # 9 slash commands
|
|
113
157
|
│ ├── hooks/ # pre-tool.mjs, post-tool.mjs
|
|
114
158
|
│ ├── rules/ # commit-guard, test-tracker, plan-enforcement
|
|
115
159
|
│ ├── lib/ # Shared dependencies
|
|
116
160
|
│ └── settings.json # Hook registration
|
|
117
161
|
└── docs/plans/ # Plan files (created during work)
|
|
162
|
+
|
|
163
|
+
~/.claude/ # (HUD — global, opt-in)
|
|
164
|
+
└── hud/omc-hud.mjs # Statusline script
|
|
118
165
|
```
|
|
119
166
|
|
|
120
167
|
## Configuration
|
|
@@ -123,6 +170,7 @@ Edit `.claude-prism.json`:
|
|
|
123
170
|
|
|
124
171
|
```json
|
|
125
172
|
{
|
|
173
|
+
"version": 1,
|
|
126
174
|
"hooks": {
|
|
127
175
|
"commit-guard": { "enabled": true, "maxTestAge": 300 },
|
|
128
176
|
"test-tracker": { "enabled": true },
|
|
@@ -133,6 +181,7 @@ Edit `.claude-prism.json`:
|
|
|
133
181
|
|
|
134
182
|
| Setting | Default | Description |
|
|
135
183
|
|---------|---------|-------------|
|
|
184
|
+
| `version` | 1 | Config schema version (for future migrations) |
|
|
136
185
|
| `commit-guard.maxTestAge` | 300 | Seconds before test run is considered stale |
|
|
137
186
|
| `plan-enforcement.warnAt` | 6 | Unique source file count that triggers plan warning |
|
|
138
187
|
|
|
@@ -140,12 +189,17 @@ Edit `.claude-prism.json`:
|
|
|
140
189
|
|
|
141
190
|
```bash
|
|
142
191
|
prism init [--no-hooks] [--global] [--dry-run] # Install
|
|
192
|
+
prism init --hud # Install + auto-enable HUD
|
|
143
193
|
prism check [--ci] # Verify installation
|
|
144
194
|
prism doctor # Diagnose issues
|
|
145
195
|
prism stats # Installation summary
|
|
196
|
+
prism analytics [--detail] # Usage analytics
|
|
146
197
|
prism reset # Clear hook state
|
|
147
198
|
prism update [--global] # Update to latest
|
|
148
199
|
prism uninstall [--global] # Remove
|
|
200
|
+
prism hud # HUD status
|
|
201
|
+
prism hud enable # Activate HUD statusline
|
|
202
|
+
prism hud disable # Deactivate HUD statusline
|
|
149
203
|
```
|
|
150
204
|
|
|
151
205
|
## Before & After
|
|
@@ -155,9 +209,9 @@ prism uninstall [--global] # Remove
|
|
|
155
209
|
2. AI: 30 minutes autonomous execution, no questions asked
|
|
156
210
|
3. Result: Structure nobody wanted, untested, scope creep everywhere
|
|
157
211
|
|
|
158
|
-
**After** (with
|
|
212
|
+
**After** (with EUDEC):
|
|
159
213
|
1. User: "Refactor auth module"
|
|
160
|
-
2. AI classifies as **Refactor
|
|
214
|
+
2. AI extracts **essence**: "Separate concerns in auth module", classifies as **Refactor**, assesses information as **[Partial]**
|
|
161
215
|
3. Asks: "Keep existing API surface? Or allowed to change public interface?"
|
|
162
216
|
4. Decomposes into 3 batches with size tags, creates plan file
|
|
163
217
|
5. Executes batch 1 → checkpoints with evidence → continues on approval
|
|
@@ -169,9 +223,9 @@ Prism auto-detects [oh-my-claudecode](https://github.com/raidenppl/oh-my-claudec
|
|
|
169
223
|
|
|
170
224
|
## Design Philosophy
|
|
171
225
|
|
|
172
|
-
|
|
226
|
+
EUDEC is the product. Everything else serves it.
|
|
173
227
|
|
|
174
|
-
The methodology works because it targets the specific failure modes of AI agents — not human developers. Humans naturally ask questions and break things down. AI optimizes for speed and skips these steps.
|
|
228
|
+
The methodology works because it targets the specific failure modes of AI agents — not human developers. Humans naturally ask questions and break things down. AI optimizes for speed and skips these steps. EUDEC forces the discipline that makes AI-assisted coding reliable — starting from the essence of the problem.
|
|
175
229
|
|
|
176
230
|
The hooks exist to enforce the two most critical rules:
|
|
177
231
|
1. **Don't commit untested code** (commit-guard + test-tracker)
|
package/bin/cli.mjs
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* prism update
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { init, check, uninstall, update, doctor, stats, reset, initGlobal, uninstallGlobal } from '../lib/installer.mjs';
|
|
14
|
+
import { init, check, uninstall, update, doctor, stats, reset, initGlobal, uninstallGlobal, installHud, uninstallHud, hudStatus } from '../lib/installer.mjs';
|
|
15
15
|
|
|
16
16
|
const args = process.argv.slice(2);
|
|
17
17
|
const command = args[0];
|
|
@@ -60,13 +60,41 @@ switch (command) {
|
|
|
60
60
|
console.log('🌈 claude-prism init\n');
|
|
61
61
|
await init(cwd, { hooks });
|
|
62
62
|
|
|
63
|
-
console.log('✅
|
|
63
|
+
console.log('✅ EUDEC methodology → CLAUDE.md');
|
|
64
64
|
console.log('✅ Commands → /prism, /checkpoint, /plan');
|
|
65
65
|
if (hooks) {
|
|
66
66
|
console.log('✅ Commit guard → blocks commits with failing tests');
|
|
67
67
|
} else {
|
|
68
68
|
console.log('⏭️ Hooks skipped (--no-hooks)');
|
|
69
69
|
}
|
|
70
|
+
|
|
71
|
+
// HUD prompt — only ask interactively if not already installed and no flag given
|
|
72
|
+
if (!hasFlag('no-hud') && process.stdin.isTTY) {
|
|
73
|
+
const status = hudStatus();
|
|
74
|
+
if (!status.enabled) {
|
|
75
|
+
const { createInterface } = await import('readline');
|
|
76
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
77
|
+
const answer = await new Promise(resolve =>
|
|
78
|
+
rl.question('\n🖥️ Enable Prism HUD statusline? Shows project/branch/plan in Claude Code (y/N): ', a => {
|
|
79
|
+
rl.close();
|
|
80
|
+
resolve(a.trim().toLowerCase());
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
if (answer === 'y' || answer === 'yes') {
|
|
84
|
+
const { scriptPath } = installHud();
|
|
85
|
+
console.log(`✅ HUD enabled → ${scriptPath}`);
|
|
86
|
+
console.log(' Restart Claude Code to activate.');
|
|
87
|
+
} else {
|
|
88
|
+
console.log('⏭️ HUD skipped (run `prism hud enable` anytime)');
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
console.log('✅ HUD already enabled');
|
|
92
|
+
}
|
|
93
|
+
} else if (hasFlag('hud')) {
|
|
94
|
+
const { scriptPath } = installHud();
|
|
95
|
+
console.log(`✅ HUD enabled → ${scriptPath}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
70
98
|
console.log('\n🌈 Done. Use /prism before complex tasks.');
|
|
71
99
|
break;
|
|
72
100
|
}
|
|
@@ -132,6 +160,44 @@ switch (command) {
|
|
|
132
160
|
break;
|
|
133
161
|
}
|
|
134
162
|
|
|
163
|
+
case 'hud': {
|
|
164
|
+
const subcommand = args[1];
|
|
165
|
+
|
|
166
|
+
if (subcommand === 'enable') {
|
|
167
|
+
console.log('🌈 claude-prism hud enable\n');
|
|
168
|
+
const { scriptPath } = installHud();
|
|
169
|
+
console.log(` ✅ HUD script → ${scriptPath}`);
|
|
170
|
+
console.log(' ✅ statusLine → ~/.claude/settings.json');
|
|
171
|
+
console.log('\n Restart Claude Code to activate.');
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (subcommand === 'disable') {
|
|
176
|
+
console.log('🌈 claude-prism hud disable\n');
|
|
177
|
+
uninstallHud();
|
|
178
|
+
console.log(' ✅ statusLine removed from ~/.claude/settings.json');
|
|
179
|
+
console.log('\n Restart Claude Code to apply.');
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Default: show status
|
|
184
|
+
console.log('🌈 claude-prism hud\n');
|
|
185
|
+
const status = hudStatus();
|
|
186
|
+
console.log(` Status: ${status.enabled ? '✅ enabled' : '⏭️ disabled'}`);
|
|
187
|
+
if (status.scriptExists) {
|
|
188
|
+
console.log(` Script: ~/.claude/hud/omc-hud.mjs`);
|
|
189
|
+
} else {
|
|
190
|
+
console.log(' Script: ❌ not installed');
|
|
191
|
+
}
|
|
192
|
+
if (status.command) {
|
|
193
|
+
console.log(` Command: ${status.command}`);
|
|
194
|
+
}
|
|
195
|
+
if (!status.enabled) {
|
|
196
|
+
console.log('\n Run `prism hud enable` to activate.');
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
|
|
135
201
|
case 'uninstall': {
|
|
136
202
|
if (hasFlag('global')) {
|
|
137
203
|
console.log('🌈 claude-prism uninstall --global\n');
|
|
@@ -165,9 +231,9 @@ switch (command) {
|
|
|
165
231
|
console.log('🌈 claude-prism update\n');
|
|
166
232
|
const result = await update(cwd);
|
|
167
233
|
if (result?.sourceRepo) {
|
|
168
|
-
console.log('✅
|
|
234
|
+
console.log('✅ EUDEC methodology updated (from local templates)');
|
|
169
235
|
} else {
|
|
170
|
-
console.log('✅
|
|
236
|
+
console.log('✅ EUDEC methodology updated');
|
|
171
237
|
}
|
|
172
238
|
console.log('✅ Commands updated');
|
|
173
239
|
console.log('✅ Commit guard updated');
|
|
@@ -239,7 +305,7 @@ switch (command) {
|
|
|
239
305
|
}
|
|
240
306
|
|
|
241
307
|
default: {
|
|
242
|
-
console.log(`🌈 claude-prism —
|
|
308
|
+
console.log(`🌈 claude-prism — EUDEC methodology framework for AI coding agents
|
|
243
309
|
|
|
244
310
|
Usage:
|
|
245
311
|
prism init [--no-hooks] Install prism in current project
|
|
@@ -253,9 +319,14 @@ Usage:
|
|
|
253
319
|
prism update --global Update global commands + OMC skill
|
|
254
320
|
prism uninstall Remove prism from current project
|
|
255
321
|
prism uninstall --global Remove global commands + OMC skill
|
|
322
|
+
prism hud Show HUD statusline status
|
|
323
|
+
prism hud enable Install and activate the HUD
|
|
324
|
+
prism hud disable Deactivate the HUD
|
|
256
325
|
|
|
257
326
|
Options:
|
|
258
327
|
--no-hooks Skip commit guard hook
|
|
328
|
+
--hud Auto-enable HUD during init (no prompt)
|
|
329
|
+
--no-hud Skip HUD prompt during init
|
|
259
330
|
--dry-run Show what init would do without making changes
|
|
260
331
|
--global Install/uninstall globally (all projects)
|
|
261
332
|
--ci Output JSON for CI integration
|
package/lib/installer.mjs
CHANGED
|
@@ -28,7 +28,7 @@ export async function init(projectDir, options = {}) {
|
|
|
28
28
|
const nsCommandsDir = join(claudeDir, 'commands', 'claude-prism');
|
|
29
29
|
mkdirSync(nsCommandsDir, { recursive: true });
|
|
30
30
|
|
|
31
|
-
const commandFiles = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md', 'update.md', 'analytics.md'];
|
|
31
|
+
const commandFiles = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md', 'update.md', 'analytics.md', 'hud.md'];
|
|
32
32
|
for (const cmd of commandFiles) {
|
|
33
33
|
copyFileSync(
|
|
34
34
|
join(TEMPLATES_DIR, 'commands', 'claude-prism', cmd),
|
|
@@ -302,7 +302,7 @@ export function doctor(projectDir, options = {}) {
|
|
|
302
302
|
|
|
303
303
|
// Check namespaced commands
|
|
304
304
|
const nsCommandsDir = join(claudeDir, 'commands', 'claude-prism');
|
|
305
|
-
const expectedCommands = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md', 'update.md', 'analytics.md'];
|
|
305
|
+
const expectedCommands = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md', 'update.md', 'analytics.md', 'hud.md'];
|
|
306
306
|
for (const cmd of expectedCommands) {
|
|
307
307
|
if (!existsSync(join(nsCommandsDir, cmd))) {
|
|
308
308
|
issues.push(`Missing command: claude-prism/${cmd}`);
|
|
@@ -449,7 +449,7 @@ export function initGlobal(options = {}) {
|
|
|
449
449
|
const commandsDir = join(claudeDir, 'commands', 'claude-prism');
|
|
450
450
|
mkdirSync(commandsDir, { recursive: true });
|
|
451
451
|
|
|
452
|
-
const commandFiles = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md', 'update.md', 'analytics.md'];
|
|
452
|
+
const commandFiles = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md', 'update.md', 'analytics.md', 'hud.md'];
|
|
453
453
|
for (const cmd of commandFiles) {
|
|
454
454
|
copyFileSync(
|
|
455
455
|
join(TEMPLATES_DIR, 'commands', 'claude-prism', cmd),
|
|
@@ -494,7 +494,7 @@ export function dryRun(projectDir, options = {}) {
|
|
|
494
494
|
|
|
495
495
|
// Commands
|
|
496
496
|
const nsCommandsDir = join(claudeDir, 'commands', 'claude-prism');
|
|
497
|
-
const commandFiles = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md', 'update.md', 'analytics.md'];
|
|
497
|
+
const commandFiles = ['prism.md', 'checkpoint.md', 'plan.md', 'doctor.md', 'stats.md', 'help.md', 'update.md', 'analytics.md', 'hud.md'];
|
|
498
498
|
for (const cmd of commandFiles) {
|
|
499
499
|
const target = join(nsCommandsDir, cmd);
|
|
500
500
|
actions.push({
|
|
@@ -551,6 +551,88 @@ export function dryRun(projectDir, options = {}) {
|
|
|
551
551
|
return { actions };
|
|
552
552
|
}
|
|
553
553
|
|
|
554
|
+
// ─── HUD management ───
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Install the Prism HUD statusline
|
|
558
|
+
* @param {Object} [options]
|
|
559
|
+
* @param {string} [options.homeDir] - Override home dir (for testing)
|
|
560
|
+
*/
|
|
561
|
+
export function installHud(options = {}) {
|
|
562
|
+
const home = options.homeDir || homedir();
|
|
563
|
+
const claudeDir = join(home, '.claude');
|
|
564
|
+
const hudDir = join(claudeDir, 'hud');
|
|
565
|
+
|
|
566
|
+
// 1. Copy HUD script
|
|
567
|
+
mkdirSync(hudDir, { recursive: true });
|
|
568
|
+
const scriptDest = join(hudDir, 'omc-hud.mjs');
|
|
569
|
+
const scriptSrc = join(TEMPLATES_DIR, 'hud', 'omc-hud.mjs');
|
|
570
|
+
|
|
571
|
+
// Backup existing custom HUD if present and different from generic wrapper
|
|
572
|
+
if (existsSync(scriptDest)) {
|
|
573
|
+
const existing = readFileSync(scriptDest, 'utf8');
|
|
574
|
+
// If existing file is larger than our template it's likely a custom HUD — keep a backup
|
|
575
|
+
const template = readFileSync(scriptSrc, 'utf8');
|
|
576
|
+
if (existing.length > template.length + 100) {
|
|
577
|
+
writeFileSync(join(hudDir, 'omc-hud.mjs.prism-backup'), existing);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
copyFileSync(scriptSrc, scriptDest);
|
|
582
|
+
|
|
583
|
+
// 2. Update ~/.claude/settings.json
|
|
584
|
+
const settingsPath = join(claudeDir, 'settings.json');
|
|
585
|
+
let settings = {};
|
|
586
|
+
if (existsSync(settingsPath)) {
|
|
587
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
588
|
+
}
|
|
589
|
+
settings.statusLine = {
|
|
590
|
+
type: 'command',
|
|
591
|
+
command: `node ${scriptDest}`
|
|
592
|
+
};
|
|
593
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
594
|
+
|
|
595
|
+
return { scriptPath: scriptDest };
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Disable the Prism HUD statusline (removes statusLine from settings)
|
|
600
|
+
* @param {Object} [options]
|
|
601
|
+
* @param {string} [options.homeDir] - Override home dir (for testing)
|
|
602
|
+
*/
|
|
603
|
+
export function uninstallHud(options = {}) {
|
|
604
|
+
const home = options.homeDir || homedir();
|
|
605
|
+
const settingsPath = join(home, '.claude', 'settings.json');
|
|
606
|
+
|
|
607
|
+
if (!existsSync(settingsPath)) return;
|
|
608
|
+
|
|
609
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
610
|
+
delete settings.statusLine;
|
|
611
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Get current HUD status
|
|
616
|
+
* @param {Object} [options]
|
|
617
|
+
* @param {string} [options.homeDir] - Override home dir (for testing)
|
|
618
|
+
* @returns {{ enabled: boolean, scriptExists: boolean, command: string|undefined }}
|
|
619
|
+
*/
|
|
620
|
+
export function hudStatus(options = {}) {
|
|
621
|
+
const home = options.homeDir || homedir();
|
|
622
|
+
const settingsPath = join(home, '.claude', 'settings.json');
|
|
623
|
+
const scriptPath = join(home, '.claude', 'hud', 'omc-hud.mjs');
|
|
624
|
+
|
|
625
|
+
if (!existsSync(settingsPath)) {
|
|
626
|
+
return { enabled: false, scriptExists: existsSync(scriptPath), command: undefined };
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
630
|
+
const cmd = settings.statusLine?.command;
|
|
631
|
+
const enabled = settings.statusLine?.type === 'command' && !!cmd?.includes('omc-hud.mjs');
|
|
632
|
+
|
|
633
|
+
return { enabled, scriptExists: existsSync(scriptPath), command: cmd };
|
|
634
|
+
}
|
|
635
|
+
|
|
554
636
|
// ─── internal helpers ───
|
|
555
637
|
|
|
556
638
|
function injectRules(projectDir, overrideRulesPath) {
|
package/lib/messages.mjs
CHANGED
|
@@ -7,7 +7,7 @@ const MESSAGES = {
|
|
|
7
7
|
'commit-guard.warn.no-test': '🌈 Prism > No test run detected this session. Run tests before committing.',
|
|
8
8
|
'commit-guard.warn.stale': '🌈 Prism > Last test run was {minutes}min ago. Run tests before committing.',
|
|
9
9
|
'test-tracker.warn.failed': '🌈 Prism 📊 Tests FAILED. Fix before committing.',
|
|
10
|
-
'plan-enforcement.warn.no-plan': '🌈 Prism > Editing {count} unique source files without a plan. Create a plan at docs/plans/ per
|
|
10
|
+
'plan-enforcement.warn.no-plan': '🌈 Prism > Editing {count} unique source files without a plan. Create a plan at docs/plans/ per EUDEC DECOMPOSE protocol.',
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export function getMessage(_lang, key, params = {}) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-prism",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "EUDEC methodology framework for AI coding agents — Essence, Understand, Decompose, Execute, Checkpoint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"prism": "./bin/cli.mjs"
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"problem-decomposition",
|
|
21
21
|
"claude-code-hooks",
|
|
22
22
|
"udec",
|
|
23
|
+
"eudec",
|
|
23
24
|
"ai-agent"
|
|
24
25
|
],
|
|
25
26
|
"engines": {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
| Command | Description |
|
|
6
6
|
|---------|-------------|
|
|
7
|
-
| `/claude-prism:prism` | Start full
|
|
7
|
+
| `/claude-prism:prism` | Start full EUDEC workflow (Essence → Understand → Decompose → Execute → Checkpoint). Also handles analysis-only requests — stops after U phase when no code change is needed. |
|
|
8
8
|
| `/claude-prism:checkpoint` | Check current batch progress, show next batch preview |
|
|
9
9
|
| `/claude-prism:plan` | List, create, or view plan files in `docs/plans/` |
|
|
10
10
|
| `/claude-prism:doctor` | Diagnose installation health and suggest fixes |
|
|
@@ -31,9 +31,10 @@ prism update # Re-install / migrate
|
|
|
31
31
|
prism uninstall # Remove prism
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## EUDEC Framework
|
|
35
35
|
|
|
36
36
|
```
|
|
37
|
+
E — Essence: Extract core problem, simplify to minimal case, define expansion path
|
|
37
38
|
U — Understand: Assess sufficiency, ask questions, confirm alignment
|
|
38
39
|
(analysis-only requests stop here with findings report)
|
|
39
40
|
D — Decompose: Break into 2-5 min units, create plan file
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# /claude-prism:hud — HUD Management
|
|
2
|
+
|
|
3
|
+
When this command is invoked, manage the Prism statusline HUD.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
- No argument → show current HUD status
|
|
8
|
+
- `enable` → install and activate the HUD
|
|
9
|
+
- `disable` → deactivate the HUD
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
### No argument — Show status
|
|
14
|
+
|
|
15
|
+
Run:
|
|
16
|
+
```bash
|
|
17
|
+
npx claude-prism@latest hud status
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Report format:
|
|
21
|
+
```
|
|
22
|
+
🌈 claude-prism hud
|
|
23
|
+
|
|
24
|
+
Status: ✅ enabled
|
|
25
|
+
Script: ~/.claude/hud/omc-hud.mjs
|
|
26
|
+
Command: node /Users/<you>/.claude/hud/omc-hud.mjs
|
|
27
|
+
|
|
28
|
+
Lines:
|
|
29
|
+
1 ⚡ project:branch | Model | 🔋ctx% | HH:MM
|
|
30
|
+
2 📋 plan name XX%(done/total) | 💾 commit msg (elapsed)
|
|
31
|
+
3 📊 세션 XX%(Xm) │ 주간XX%(요일 HH:MM)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### enable
|
|
35
|
+
|
|
36
|
+
1. Run:
|
|
37
|
+
```bash
|
|
38
|
+
npx claude-prism@latest hud enable
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
2. Report:
|
|
42
|
+
```
|
|
43
|
+
🌈 claude-prism hud enabled
|
|
44
|
+
|
|
45
|
+
✅ HUD script → ~/.claude/hud/omc-hud.mjs
|
|
46
|
+
✅ statusLine → ~/.claude/settings.json
|
|
47
|
+
|
|
48
|
+
Restart Claude Code to see the HUD.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### disable
|
|
52
|
+
|
|
53
|
+
1. Run:
|
|
54
|
+
```bash
|
|
55
|
+
npx claude-prism@latest hud disable
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
2. Report:
|
|
59
|
+
```
|
|
60
|
+
🌈 claude-prism hud disabled
|
|
61
|
+
|
|
62
|
+
✅ statusLine removed from ~/.claude/settings.json
|
|
63
|
+
|
|
64
|
+
Restart Claude Code to apply.
|
|
65
|
+
```
|
|
@@ -1,15 +1,36 @@
|
|
|
1
1
|
# /claude-prism:prism — Problem Decomposition
|
|
2
2
|
|
|
3
|
-
When this command is invoked, follow the
|
|
3
|
+
When this command is invoked, follow the EUDEC framework strictly:
|
|
4
|
+
|
|
5
|
+
## E — ESSENCE
|
|
6
|
+
|
|
7
|
+
0. **Extract the essence**: Before exploring code, ask: "What is the core problem here — in one sentence, without naming specific tools?"
|
|
8
|
+
- Output: `본질: [one sentence]`
|
|
9
|
+
- Output: `최소 케이스: [simplest working version]`
|
|
10
|
+
- Output: `확장 경로: minimal → [step1] → [step2] → [complete]`
|
|
11
|
+
1. **Verify essence quality**:
|
|
12
|
+
- Does the essence sentence avoid specific technology names? If not → still at solution level, go higher
|
|
13
|
+
- Is the minimal case truly minimal? Can it be reduced further?
|
|
14
|
+
- Symptom vs cause: "Is this the cause, or a consequence?"
|
|
15
|
+
- Solution vs essence: "Caching" is a solution. "Eliminating redundant computation" is the essence.
|
|
16
|
+
2. **Derive task type** from the essence:
|
|
17
|
+
|
|
18
|
+
| Essence Character | Type | Path |
|
|
19
|
+
|-------------------|------|------|
|
|
20
|
+
| "X is broken" | Bugfix | UNDERSTAND → locate → fix → verify |
|
|
21
|
+
| "X should be possible" | Feature | UNDERSTAND → DECOMPOSE → EXECUTE → CHECKPOINT |
|
|
22
|
+
| "All X must become Y" | Migration | UNDERSTAND → pattern → batch apply → verify |
|
|
23
|
+
| "X's structure must change" | Refactor | UNDERSTAND → DECOMPOSE → EXECUTE → CHECKPOINT |
|
|
24
|
+
| "Why does X happen?" | Investigation | explore → analyze → report |
|
|
4
25
|
|
|
5
26
|
## U — UNDERSTAND
|
|
6
27
|
|
|
7
|
-
|
|
8
|
-
|
|
28
|
+
3. **Explore first**: Read package.json, project structure, related files before asking anything
|
|
29
|
+
4. **Assess information sufficiency**:
|
|
9
30
|
- [Sufficient] Specific file, function, symptom mentioned → skip to DECOMPOSE
|
|
10
31
|
- [Partial] Direction clear but details missing → explore then ask 1-2 questions
|
|
11
32
|
- [Insufficient] Abstract, vague, multiple interpretations → must ask questions first
|
|
12
|
-
|
|
33
|
+
5. **Check for hidden assumptions** (Red Flag Detection):
|
|
13
34
|
|
|
14
35
|
| Red Flag | Question to Ask Yourself |
|
|
15
36
|
|----------|-------------------------|
|
|
@@ -21,63 +42,63 @@ When this command is invoked, follow the UDEC framework strictly:
|
|
|
21
42
|
| No file/function names | [Insufficient]. Must ask. |
|
|
22
43
|
| "just", "simply" | Complexity being underestimated |
|
|
23
44
|
|
|
24
|
-
|
|
45
|
+
6. **Question rules** (if questions needed):
|
|
25
46
|
- One question at a time
|
|
26
47
|
- Multiple choice with 2-3 options + recommendation
|
|
27
48
|
- Include reasoning based on code exploration
|
|
28
49
|
- Maximum 3 rounds of questions
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
7. **Confirm alignment**: Summarize goal in one sentence, get user approval
|
|
51
|
+
8. **Analysis-only requests**: If no code change is needed (architecture review, cause analysis, investigation), report findings and ask: "Further action needed?" Do NOT proceed to D/E/C unless the user requests implementation.
|
|
31
52
|
|
|
32
53
|
## D — DECOMPOSE
|
|
33
54
|
|
|
34
|
-
|
|
55
|
+
9. **Assess complexity** (consider BOTH file count AND logic complexity):
|
|
35
56
|
- [Simple] 1-2 files, minor changes (<50 LOC) → execute directly, no decomposition needed
|
|
36
57
|
- [Medium] 3-5 files, OR 1-2 files with significant logic changes (50-150 LOC) → 2-3 batches
|
|
37
58
|
- [Complex] 6+ files, OR substantial architectural changes → 5+ batches, must create plan file
|
|
38
59
|
- [Complex system] Unclear scope → reduce scope first, then decompose
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
60
|
+
10. **Create batches** following the 5 principles:
|
|
61
|
+
- Unit size: 2-5 minutes each (test/implement/verify as separate steps)
|
|
62
|
+
- Test first: test before implementation in each unit
|
|
63
|
+
- Independent verification: each unit has a pass criterion
|
|
64
|
+
- Files specified: list files to create/modify per unit
|
|
65
|
+
- Dependencies noted: mark if unit depends on a previous one
|
|
66
|
+
11. **Assign size tags** to every task: [S] <30 LOC, [M] 30-100 LOC, [L] >100 LOC
|
|
67
|
+
- Batch composition: S+S+M = 1 batch, L = 1 batch alone
|
|
68
|
+
12. **Assign verification strategy** per task: `| Verify: TDD` or `| Verify: Build` or `| Verify: Visual`
|
|
69
|
+
13. **Pre-decomposition checklist**:
|
|
49
70
|
- Required types/interfaces have the necessary fields?
|
|
50
71
|
- External package APIs behave as expected?
|
|
51
72
|
- Cross-package dependencies identified and noted as prerequisites?
|
|
52
|
-
|
|
53
|
-
|
|
73
|
+
14. **Save plan** to `docs/plans/YYYY-MM-DD-<topic>.md`
|
|
74
|
+
15. **Get approval**: "Proceed with this plan?"
|
|
54
75
|
|
|
55
76
|
## E — EXECUTE
|
|
56
77
|
|
|
57
|
-
|
|
78
|
+
16. Execute in adaptive batches:
|
|
58
79
|
- Simple changes (imports, types, config): 5-8 per batch
|
|
59
80
|
- Standard changes (feature add/modify): 3-4 per batch
|
|
60
81
|
- Complex changes (new module, architecture): 1-2 per batch
|
|
61
|
-
|
|
82
|
+
17. Apply context-aware verification:
|
|
62
83
|
- `lib/`, `utils/`, `store/`, `hooks/`, `services/` → TDD (failing test → implement → verify)
|
|
63
84
|
- `components/`, `pages/`, `views/` → Build verification (escalate to TDD if complex logic)
|
|
64
85
|
- `config/`, `styles/`, `types/` → Build/lint only
|
|
65
|
-
|
|
66
|
-
|
|
86
|
+
18. **Scope Guard**: Before each change, ask: "Was this requested?" If no → don't do it
|
|
87
|
+
19. **Self-correction triggers**:
|
|
67
88
|
- Same file edited 3+ times **on the same region/logic** → stop, investigate root cause (progressive edits across different regions — imports, logic, JSX — are normal)
|
|
68
89
|
- File not in plan → pause, ask about scope change
|
|
69
90
|
- 3 consecutive test failures → stop, reconsider approach
|
|
70
91
|
- New package needed → ask user first
|
|
71
92
|
- Adding workarounds on workarounds → design problem, step back
|
|
72
|
-
|
|
73
|
-
|
|
93
|
+
20. **Verification scoping**: When running build checks (tsc, lint, etc.), filter output to only changed files. Pre-existing errors in other files are not your concern. Example: `tsc --noEmit 2>&1 | grep -i "<changed-file>"`
|
|
94
|
+
21. **Agent failure recovery**: If a delegated agent partially fails or produces incomplete results:
|
|
74
95
|
1. Verify actual file state (read the file, not just the agent's report)
|
|
75
96
|
2. If partially correct → complete the remaining work directly
|
|
76
97
|
3. If fully wrong → retry with clearer instructions or execute directly
|
|
77
98
|
|
|
78
99
|
## C — CHECKPOINT
|
|
79
100
|
|
|
80
|
-
|
|
101
|
+
22. After each batch, report using this format:
|
|
81
102
|
|
|
82
103
|
| Item | Before | After |
|
|
83
104
|
|------|--------|-------|
|
|
@@ -88,10 +109,10 @@ When this command is invoked, follow the UDEC framework strictly:
|
|
|
88
109
|
[████████░░] 80% — Next: [next batch name]
|
|
89
110
|
```
|
|
90
111
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
112
|
+
23. Include: verification results, files modified, tests status
|
|
113
|
+
24. **Checkpoint policy**: after 3 consecutive approvals, increase batch size to 5-8 for the rest of the phase
|
|
114
|
+
25. Ask: "Continue to next batch?"
|
|
115
|
+
26. User can redirect, adjust scope, or stop at any checkpoint
|
|
95
116
|
|
|
96
117
|
## OMC Integration
|
|
97
118
|
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { readFileSync, existsSync, readdirSync, statSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { homedir, tmpdir } from 'os';
|
|
6
|
+
|
|
7
|
+
function shortenModelName(name) {
|
|
8
|
+
return name
|
|
9
|
+
.replace('Claude 3.5 Sonnet', 'Sonnet 3.5')
|
|
10
|
+
.replace('Claude 3 Opus', 'Opus 3')
|
|
11
|
+
.replace('Claude 3 Haiku', 'Haiku 3')
|
|
12
|
+
.replace('Claude ', '');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getCurrentTime() {
|
|
16
|
+
const now = new Date();
|
|
17
|
+
return `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function hasGitChanges(cwd) {
|
|
21
|
+
try {
|
|
22
|
+
const status = execSync('git -c core.fileMode=false status --porcelain 2>/dev/null', {
|
|
23
|
+
encoding: 'utf-8', cwd, stdio: ['ignore', 'pipe', 'ignore']
|
|
24
|
+
}).trim();
|
|
25
|
+
return status.length > 0;
|
|
26
|
+
} catch { return false; }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getPlanUsage() {
|
|
30
|
+
try {
|
|
31
|
+
const cachePath = join(homedir(), '.claude', 'plugins', 'oh-my-claudecode', '.usage-cache.json');
|
|
32
|
+
if (!existsSync(cachePath)) return null;
|
|
33
|
+
const cache = JSON.parse(readFileSync(cachePath, 'utf-8'));
|
|
34
|
+
if (cache.error || !cache.data) return null;
|
|
35
|
+
const now = new Date();
|
|
36
|
+
const { fiveHourPercent, weeklyPercent, fiveHourResetsAt, weeklyResetsAt } = cache.data;
|
|
37
|
+
const minutesUntilReset = Math.max(0, Math.round((new Date(fiveHourResetsAt) - now) / 60000));
|
|
38
|
+
const weeklyReset = new Date(weeklyResetsAt);
|
|
39
|
+
const dayNames = ['일', '월', '화', '수', '목', '금', '토'];
|
|
40
|
+
return {
|
|
41
|
+
session: fiveHourPercent,
|
|
42
|
+
weekly: weeklyPercent,
|
|
43
|
+
sessionResetMin: minutesUntilReset,
|
|
44
|
+
weeklyResetLabel: `${dayNames[weeklyReset.getDay()]} ${String(weeklyReset.getHours()).padStart(2, '0')}:${String(weeklyReset.getMinutes()).padStart(2, '0')}`
|
|
45
|
+
};
|
|
46
|
+
} catch { return null; }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getGitRoot(cwd) {
|
|
50
|
+
try {
|
|
51
|
+
return execSync('git rev-parse --show-toplevel 2>/dev/null', {
|
|
52
|
+
encoding: 'utf-8', cwd, stdio: ['ignore', 'pipe', 'ignore']
|
|
53
|
+
}).trim();
|
|
54
|
+
} catch { return null; }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getActivePlan(cwd) {
|
|
58
|
+
try {
|
|
59
|
+
const gitRoot = getGitRoot(cwd);
|
|
60
|
+
if (!gitRoot) return null;
|
|
61
|
+
const plansDir = join(gitRoot, 'docs', 'plans');
|
|
62
|
+
if (!existsSync(plansDir)) return null;
|
|
63
|
+
const files = readdirSync(plansDir).filter(f => f.endsWith('.md')).sort().reverse();
|
|
64
|
+
if (files.length === 0) return null;
|
|
65
|
+
const latestFile = files[0];
|
|
66
|
+
const content = readFileSync(join(plansDir, latestFile), 'utf-8');
|
|
67
|
+
const doneCount = (content.match(/- \[x\]/gi) || []).length;
|
|
68
|
+
const todoCount = (content.match(/- \[ \]/g) || []).length;
|
|
69
|
+
const total = doneCount + todoCount;
|
|
70
|
+
const planName = latestFile.replace(/^\d{4}-\d{2}-\d{2}-/, '').replace(/\.md$/, '');
|
|
71
|
+
return { name: planName, done: doneCount, total, percent: total > 0 ? Math.round((doneCount / total) * 100) : 0 };
|
|
72
|
+
} catch { return null; }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function relativeTime(unixTimestamp) {
|
|
76
|
+
const diff = Math.floor(Date.now() / 1000) - unixTimestamp;
|
|
77
|
+
if (diff < 60) return `${diff}s`;
|
|
78
|
+
if (diff < 3600) return `${Math.floor(diff / 60)}m`;
|
|
79
|
+
if (diff < 86400) return `${Math.floor(diff / 3600)}h`;
|
|
80
|
+
if (diff < 604800) return `${Math.floor(diff / 86400)}d`;
|
|
81
|
+
return `${Math.floor(diff / 604800)}w`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getRecentCommit(cwd) {
|
|
85
|
+
try {
|
|
86
|
+
const raw = execSync('git log -1 --format="%s|%ct" 2>/dev/null', {
|
|
87
|
+
encoding: 'utf-8', cwd, stdio: ['ignore', 'pipe', 'ignore']
|
|
88
|
+
}).trim();
|
|
89
|
+
if (!raw) return null;
|
|
90
|
+
const sepIdx = raw.lastIndexOf('|');
|
|
91
|
+
if (sepIdx === -1) return null;
|
|
92
|
+
const message = raw.substring(0, sepIdx);
|
|
93
|
+
const timestamp = parseInt(raw.substring(sepIdx + 1), 10);
|
|
94
|
+
const maxLen = 25;
|
|
95
|
+
const truncated = message.length > maxLen ? message.substring(0, maxLen - 1) + '\u2026' : message;
|
|
96
|
+
return { message: truncated, elapsed: relativeTime(timestamp) };
|
|
97
|
+
} catch { return null; }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getTestStatus() {
|
|
101
|
+
try {
|
|
102
|
+
const prismRoot = join(tmpdir(), '.prism');
|
|
103
|
+
if (!existsSync(prismRoot)) return null;
|
|
104
|
+
let latestRun = 0;
|
|
105
|
+
let latestDir = null;
|
|
106
|
+
for (const dir of readdirSync(prismRoot)) {
|
|
107
|
+
const dirPath = join(prismRoot, dir);
|
|
108
|
+
try { if (!statSync(dirPath).isDirectory()) continue; } catch { continue; }
|
|
109
|
+
const runFile = join(dirPath, 'last-test-run');
|
|
110
|
+
if (!existsSync(runFile)) continue;
|
|
111
|
+
const runTs = parseInt(readFileSync(runFile, 'utf-8').trim(), 10);
|
|
112
|
+
if (runTs > latestRun) { latestRun = runTs; latestDir = dirPath; }
|
|
113
|
+
}
|
|
114
|
+
if (!latestDir) return null;
|
|
115
|
+
const resultFile = join(latestDir, 'last-test-result');
|
|
116
|
+
const result = existsSync(resultFile) ? readFileSync(resultFile, 'utf-8').trim() : null;
|
|
117
|
+
return { passed: result === 'pass', elapsed: relativeTime(latestRun) };
|
|
118
|
+
} catch { return null; }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ═══════════════════════════════════════════════════════════════
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const fs = await import('fs');
|
|
125
|
+
const input = fs.readFileSync(0, 'utf-8');
|
|
126
|
+
const context = JSON.parse(input);
|
|
127
|
+
|
|
128
|
+
const cwd = context.workspace?.current_dir || process.cwd();
|
|
129
|
+
const dirName = cwd.split('/').pop();
|
|
130
|
+
const modelName = shortenModelName(context.model?.display_name || 'Claude');
|
|
131
|
+
const remaining = context.context_window?.remaining_percentage;
|
|
132
|
+
const planUsage = getPlanUsage();
|
|
133
|
+
|
|
134
|
+
let gitBranch = '';
|
|
135
|
+
let gitDirty = false;
|
|
136
|
+
try {
|
|
137
|
+
gitBranch = execSync(
|
|
138
|
+
'git -c core.fileMode=false -c core.checkStat=minimal symbolic-ref --short HEAD 2>/dev/null || git -c core.fileMode=false -c core.checkStat=minimal rev-parse --short HEAD 2>/dev/null',
|
|
139
|
+
{ encoding: 'utf-8', cwd, stdio: ['ignore', 'pipe', 'ignore'] }
|
|
140
|
+
).trim();
|
|
141
|
+
if (gitBranch) gitDirty = hasGitChanges(cwd);
|
|
142
|
+
} catch {}
|
|
143
|
+
|
|
144
|
+
const activePlan = getActivePlan(cwd);
|
|
145
|
+
const recentCommit = getRecentCommit(cwd);
|
|
146
|
+
const testStatus = getTestStatus();
|
|
147
|
+
|
|
148
|
+
const S = ' | ';
|
|
149
|
+
|
|
150
|
+
// ── Line 1: Project:Branch | Model | Ctx% | Time ──
|
|
151
|
+
const line1 = [];
|
|
152
|
+
if (gitBranch) {
|
|
153
|
+
const dirty = gitDirty ? '*' : '';
|
|
154
|
+
line1.push(`\u26A1 ${dirName}:${gitBranch}${dirty}`);
|
|
155
|
+
} else {
|
|
156
|
+
line1.push(`\u26A1 ${dirName}`);
|
|
157
|
+
}
|
|
158
|
+
line1.push(modelName);
|
|
159
|
+
if (remaining !== null && remaining !== undefined) {
|
|
160
|
+
const pct = Math.round(remaining);
|
|
161
|
+
const icon = pct < 20 ? '\uD83D\uDD34' : pct < 50 ? '\u26A0\uFE0F' : '\uD83D\uDD0B';
|
|
162
|
+
line1.push(`${icon}${pct}%`);
|
|
163
|
+
}
|
|
164
|
+
line1.push(getCurrentTime());
|
|
165
|
+
|
|
166
|
+
// ── Line 2: Plan + Commit + Test ──
|
|
167
|
+
const line2 = [];
|
|
168
|
+
if (activePlan) {
|
|
169
|
+
const short = activePlan.name.length > 12 ? activePlan.name.substring(0, 11) + '\u2026' : activePlan.name;
|
|
170
|
+
line2.push(`\uD83D\uDCCB ${short} ${activePlan.percent}%(${activePlan.done}/${activePlan.total})`);
|
|
171
|
+
}
|
|
172
|
+
if (recentCommit) {
|
|
173
|
+
line2.push(`\uD83D\uDCBE ${recentCommit.message}(${recentCommit.elapsed})`);
|
|
174
|
+
}
|
|
175
|
+
if (testStatus) {
|
|
176
|
+
line2.push(`${testStatus.passed ? '\u2705' : '\u274C'}${testStatus.elapsed}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ── Line 3: Usage ──
|
|
180
|
+
const line3 = [];
|
|
181
|
+
if (planUsage) {
|
|
182
|
+
const warn = (planUsage.session > 95 || planUsage.weekly > 95) ? '\uD83D\uDD34' : (planUsage.session > 80 || planUsage.weekly > 80) ? '\u26A0\uFE0F' : '';
|
|
183
|
+
line3.push(`\uD83D\uDCCA ${planUsage.session}%(${planUsage.sessionResetMin}m) \u2502 \uC8FC\uAC04${planUsage.weekly}%(${planUsage.weeklyResetLabel})${warn}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ── Compose ──
|
|
187
|
+
const lines = [line1.join(S)];
|
|
188
|
+
if (line2.length > 0) lines.push(line2.join(S));
|
|
189
|
+
if (line3.length > 0) lines.push(line3.join(S));
|
|
190
|
+
|
|
191
|
+
console.log(lines.join('\n'));
|
|
192
|
+
|
|
193
|
+
} catch (e) {
|
|
194
|
+
const powerEmojis = ['\u26A1', '\uD83D\uDD25', '\uD83D\uDE80', '\u2728'];
|
|
195
|
+
const randomEmoji = powerEmojis[Math.floor(Math.random() * powerEmojis.length)];
|
|
196
|
+
console.log(`${randomEmoji} LazySaturday \u276F \uD83E\uDDE0 Claude \u276F \uD83D\uDD50 ${getCurrentTime()}`);
|
|
197
|
+
}
|
package/templates/rules.md
CHANGED
|
@@ -1,33 +1,74 @@
|
|
|
1
1
|
|
|
2
2
|
<!-- PRISM:START -->
|
|
3
|
-
# Prism —
|
|
3
|
+
# Prism — EUDEC Methodology Framework
|
|
4
4
|
|
|
5
|
-
**
|
|
6
|
-
Bookended by
|
|
5
|
+
**EUDEC = Essence, Understand, Decompose, Execute, Checkpoint** — the core cycle.
|
|
6
|
+
Bookended by HANDOFF (exit protocol).
|
|
7
7
|
|
|
8
8
|
## Core Principle
|
|
9
9
|
|
|
10
|
-
**Never implement what you haven't understood. Never
|
|
10
|
+
**Never implement what you haven't understood. Never understand what you haven't distilled to its essence.**
|
|
11
|
+
|
|
12
|
+
The approach: **Essence → Simplify → Expand**. Strip down to the core of the problem, reduce to its simplest form, then build up from the smallest working unit.
|
|
11
13
|
|
|
12
14
|
---
|
|
13
15
|
|
|
14
|
-
##
|
|
16
|
+
## EUDEC 1. ESSENCE — Essence Extraction Protocol
|
|
17
|
+
|
|
18
|
+
Starting point for all work. Strip down to the core of the problem before implementation.
|
|
19
|
+
|
|
20
|
+
### 1-1. Essence Extraction (3 Steps)
|
|
21
|
+
|
|
22
|
+
| Step | Question | Output |
|
|
23
|
+
|------|----------|--------|
|
|
24
|
+
| **Extract** | "What do they actually want?" | Essence statement (1 sentence) |
|
|
25
|
+
| **Simplify** | "What's the smallest working version?" | Minimal case |
|
|
26
|
+
| **Expansion path** | "How do we grow from here?" | Expansion steps (2-4 steps) |
|
|
27
|
+
|
|
28
|
+
**Output format:**
|
|
29
|
+
```
|
|
30
|
+
## ESSENCE
|
|
31
|
+
- Essence: [one sentence — no technology/tool names]
|
|
32
|
+
- Minimal case: [simplest working form]
|
|
33
|
+
- Expansion path: minimal → [step1] → [step2] → [complete]
|
|
34
|
+
```
|
|
15
35
|
|
|
16
|
-
|
|
36
|
+
### 1-2. Task Type Derivation
|
|
17
37
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
|
21
|
-
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
38
|
+
The task type naturally emerges from the essence:
|
|
39
|
+
|
|
40
|
+
| Essence Character | Type | Path |
|
|
41
|
+
|-------------------|------|------|
|
|
42
|
+
| "X is broken" | Bugfix | UNDERSTAND → locate → fix → verify |
|
|
43
|
+
| "X should be possible" | Feature | UNDERSTAND → DECOMPOSE → EXECUTE → CHECKPOINT |
|
|
44
|
+
| "All X must become Y" | Migration | UNDERSTAND → pattern → batch apply → verify |
|
|
45
|
+
| "X's structure must change" | Refactor | UNDERSTAND → DECOMPOSE → EXECUTE → CHECKPOINT |
|
|
46
|
+
| "Why does X happen?" | Investigation | explore → analyze → report |
|
|
25
47
|
|
|
26
48
|
**Migration shortcut**: When applying the same transformation to 10+ files, don't decompose into individual file tasks. Define the pattern once, apply in batches of 5-10, verify after each batch. Scope guard thresholds are raised automatically when a plan file exists.
|
|
27
49
|
|
|
50
|
+
### 1-3. Essence Validation (Error Prevention)
|
|
51
|
+
|
|
52
|
+
| Trap | Response |
|
|
53
|
+
|------|----------|
|
|
54
|
+
| Mistaking symptom for essence | "Is this the cause, or a consequence?" |
|
|
55
|
+
| Mistaking solution for essence | "Add caching" is not the essence. "Eliminate redundant computation" is. |
|
|
56
|
+
| Too abstract | "Can I write even one line of code from this?" |
|
|
57
|
+
| Too specific | "What's the real problem one level up?" |
|
|
58
|
+
|
|
59
|
+
**Core test**: If the essence statement contains specific technology/tool names → it's still at solution level, not essence. Go one level higher.
|
|
60
|
+
|
|
61
|
+
### 1-4. Quality Gate: ESSENCE → UNDERSTAND
|
|
62
|
+
|
|
63
|
+
Before moving to UNDERSTAND, verify:
|
|
64
|
+
- [ ] Essence statement is technology-neutral (holds without naming specific tools/libraries)
|
|
65
|
+
- [ ] Minimal case is truly "minimal" (can it be reduced further?)
|
|
66
|
+
- [ ] Each step in the expansion path works independently
|
|
67
|
+
- [ ] Task type has been clearly derived
|
|
68
|
+
|
|
28
69
|
---
|
|
29
70
|
|
|
30
|
-
##
|
|
71
|
+
## EUDEC 2. UNDERSTAND — Understanding Protocol
|
|
31
72
|
|
|
32
73
|
### 2-1. Information Sufficiency Assessment (MANDATORY)
|
|
33
74
|
|
|
@@ -82,7 +123,7 @@ Before moving to DECOMPOSE:
|
|
|
82
123
|
|
|
83
124
|
---
|
|
84
125
|
|
|
85
|
-
##
|
|
126
|
+
## EUDEC 3. DECOMPOSE — Planning Protocol
|
|
86
127
|
|
|
87
128
|
### 3-1. Decomposition Trigger
|
|
88
129
|
|
|
@@ -170,7 +211,7 @@ If any gate fails → resolve before executing. Do not start implementation on a
|
|
|
170
211
|
|
|
171
212
|
---
|
|
172
213
|
|
|
173
|
-
##
|
|
214
|
+
## EUDEC 4. EXECUTE — Execution Protocol
|
|
174
215
|
|
|
175
216
|
### 4-1. Batch Execution
|
|
176
217
|
|
|
@@ -236,7 +277,7 @@ Choose verification proportional to the **risk of the change**, not the file pat
|
|
|
236
277
|
|
|
237
278
|
- Same file edited 3+ times → "Possible thrashing. Investigate root cause."
|
|
238
279
|
- Editing file not in plan → "Scope change needed?"
|
|
239
|
-
- 3 consecutive test failures → "Approach problem. Back to
|
|
280
|
+
- 3 consecutive test failures → "Approach problem. Back to ESSENCE — did we get the essence wrong?"
|
|
240
281
|
- New package needed → "Confirm with user"
|
|
241
282
|
- 5 turns autonomous → "Report progress before continuing"
|
|
242
283
|
- Adding workarounds to fix workarounds → "Design problem. Step back."
|
|
@@ -250,7 +291,7 @@ Choose verification proportional to the **risk of the change**, not the file pat
|
|
|
250
291
|
**Thrashing Detector** (beyond simple edit counting):
|
|
251
292
|
- Successive edits reverting previous changes (oscillation) → "Reverting own work. Wrong approach."
|
|
252
293
|
- Scope of changes expanding beyond plan → "Scope creep. Return to DECOMPOSE."
|
|
253
|
-
- Error messages changing type across fixes → "Chasing symptoms, not root cause. Back to
|
|
294
|
+
- Error messages changing type across fixes → "Chasing symptoms, not root cause. Back to ESSENCE."
|
|
254
295
|
|
|
255
296
|
### 4-5. Scope Guard
|
|
256
297
|
|
|
@@ -286,7 +327,7 @@ When delegating work to sub-agents:
|
|
|
286
327
|
|
|
287
328
|
---
|
|
288
329
|
|
|
289
|
-
##
|
|
330
|
+
## EUDEC 5. CHECKPOINT — Confirmation Protocol
|
|
290
331
|
|
|
291
332
|
### Quality Gate: EXECUTE → CHECKPOINT
|
|
292
333
|
|
|
@@ -328,7 +369,7 @@ Plan freshness: verified [date] | Remaining targets: [N] confirmed in code
|
|
|
328
369
|
|
|
329
370
|
### 5-2. Direction Change
|
|
330
371
|
|
|
331
|
-
User says "change direction" → return to
|
|
372
|
+
User says "change direction" → return to ESSENCE (re-examine from the core)
|
|
332
373
|
User says "stop here" → clean exit
|
|
333
374
|
|
|
334
375
|
---
|
|
@@ -415,6 +456,9 @@ If any of these excuses come to mind, **that's a warning signal**. Stop and retu
|
|
|
415
456
|
| "Other plans won't conflict" | Check `docs/plans/` for overlapping files |
|
|
416
457
|
| "Tests pass, so it must be correct" | Passing tests only prove what you tested. Check edge cases and negative cases |
|
|
417
458
|
| "3 files is too few to decompose" | Depends on coupling. 2 files in a tightly-coupled legacy system may need decomposition |
|
|
459
|
+
| "I already grasped the essence" | If the essence statement contains technology names, it's still at solution level |
|
|
460
|
+
| "No need to simplify, just implement" | Starting without a minimal case drowns you in complexity |
|
|
461
|
+
| "Expansion path can wait" | Without expansion direction, the minimal case becomes a dead end |
|
|
418
462
|
|
|
419
463
|
## 8. Completion Declaration Rules
|
|
420
464
|
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: prism
|
|
3
|
-
description: AI coding problem decomposition tool —
|
|
3
|
+
description: AI coding problem decomposition tool — EUDEC methodology
|
|
4
4
|
triggers:
|
|
5
5
|
- "prism"
|
|
6
6
|
- "decompose"
|
|
7
7
|
- "udec"
|
|
8
|
+
- "eudec"
|
|
8
9
|
argument-hint: "[task description]"
|
|
9
10
|
---
|
|
10
11
|
|
|
11
12
|
<Purpose>
|
|
12
|
-
Prism applies the
|
|
13
|
+
Prism applies the EUDEC methodology (Essence, Understand, Decompose, Execute, Checkpoint) to any coding task. It prevents the biggest AI coding failure mode: building the wrong thing by skipping essence extraction and understanding.
|
|
13
14
|
</Purpose>
|
|
14
15
|
|
|
15
16
|
<Use_When>
|
|
16
|
-
- User says "prism", "decompose", or "
|
|
17
|
+
- User says "prism", "decompose", "udec", or "eudec"
|
|
17
18
|
- Complex task requiring structured approach (3+ files, unclear scope)
|
|
18
19
|
- Vague request that needs clarification before implementation
|
|
19
20
|
- User wants disciplined, checkpoint-based execution
|
|
@@ -31,9 +32,30 @@ AI agents optimize for speed, not correctness. Without structure, they skip unde
|
|
|
31
32
|
|
|
32
33
|
<Steps>
|
|
33
34
|
|
|
35
|
+
## E — ESSENCE
|
|
36
|
+
|
|
37
|
+
0. **Extract the essence**: Before exploring code, ask: "What is the core problem here — in one sentence, without naming specific tools?"
|
|
38
|
+
- Output: `본질: [one sentence — no technology/tool names]`
|
|
39
|
+
- Output: `최소 케이스: [simplest working version]`
|
|
40
|
+
- Output: `확장 경로: minimal → [step1] → [step2] → [complete]`
|
|
41
|
+
1. **Verify essence quality**:
|
|
42
|
+
- Does the essence sentence avoid specific technology names? If not → still at solution level, go higher
|
|
43
|
+
- Is the minimal case truly minimal? Can it be reduced further?
|
|
44
|
+
- Symptom vs cause: "Is this the cause, or a consequence?"
|
|
45
|
+
- Solution vs essence: "Caching" is a solution. "Eliminating redundant computation" is the essence.
|
|
46
|
+
2. **Derive task type** from the essence:
|
|
47
|
+
|
|
48
|
+
| Essence Character | Type | Path |
|
|
49
|
+
|-------------------|------|------|
|
|
50
|
+
| "X is broken" | Bugfix | UNDERSTAND → locate → fix → verify |
|
|
51
|
+
| "X should be possible" | Feature | UNDERSTAND → DECOMPOSE → EXECUTE → CHECKPOINT |
|
|
52
|
+
| "All X must become Y" | Migration | UNDERSTAND → pattern → batch apply → verify |
|
|
53
|
+
| "X's structure must change" | Refactor | UNDERSTAND → DECOMPOSE → EXECUTE → CHECKPOINT |
|
|
54
|
+
| "Why does X happen?" | Investigation | explore → analyze → report |
|
|
55
|
+
|
|
34
56
|
## U — UNDERSTAND
|
|
35
57
|
|
|
36
|
-
|
|
58
|
+
3. **Explore first**: Read package.json, project structure, related files before asking anything
|
|
37
59
|
2. **Assess information sufficiency**:
|
|
38
60
|
- [Sufficient] Specific file, function, symptom mentioned → skip to DECOMPOSE
|
|
39
61
|
- [Partial] Direction clear but details missing → explore then ask 1-2 questions
|