5-phase-workflow 1.8.5 → 1.8.7
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 +17 -0
- package/bin/install.js +6 -7
- package/docs/workflow-guide.md +1 -1
- package/package.json +1 -1
- package/src/commands/5/address-review-findings.md +2 -2
- package/src/commands/5/configure.md +22 -24
- package/src/commands/5/eject.md +91 -0
- package/src/commands/5/plan-feature.md +24 -22
- package/src/commands/5/reconfigure.md +11 -9
- package/src/hooks/plan-guard.js +41 -2
- package/src/hooks/statusline.js +80 -41
- package/src/skills/configure-project/SKILL.md +34 -85
- package/src/skills/generate-readme/SKILL.md +1 -2
- package/src/templates/ARCHITECTURE.md +16 -47
- package/src/templates/CONCERNS.md +12 -54
- package/src/templates/TESTING.md +12 -95
- package/src/skills/build-project/SKILL.md +0 -151
- package/src/skills/run-tests/SKILL.md +0 -162
- package/src/templates/CONVENTIONS.md +0 -75
- package/src/templates/INTEGRATIONS.md +0 -65
- package/src/templates/STACK.md +0 -60
- package/src/templates/STRUCTURE.md +0 -60
package/README.md
CHANGED
|
@@ -130,6 +130,7 @@ All commands are available under the `/5:` namespace:
|
|
|
130
130
|
| `/5:review-code` | 5 | AI-powered code review (Claude or CodeRabbit) |
|
|
131
131
|
| `/5:address-review-findings` | 5 | Apply annotated findings and address PR comments |
|
|
132
132
|
| `/5:quick-implement` | Fast | Streamlined workflow for small tasks |
|
|
133
|
+
| `/5:eject` | Utility | Permanently remove update infrastructure |
|
|
133
134
|
| `/5:unlock` | Utility | Remove planning guard lock |
|
|
134
135
|
|
|
135
136
|
## Configuration
|
|
@@ -264,6 +265,7 @@ After installation, your `.claude/` directory will contain:
|
|
|
264
265
|
│ ├── discuss-feature.md
|
|
265
266
|
│ ├── quick-implement.md
|
|
266
267
|
│ ├── configure.md
|
|
268
|
+
│ ├── eject.md
|
|
267
269
|
│ └── unlock.md
|
|
268
270
|
├── skills/ # Atomic operations
|
|
269
271
|
│ ├── build-project/
|
|
@@ -364,6 +366,21 @@ npx 5-phase-workflow
|
|
|
364
366
|
- User-created commands, agents, skills, hooks, and templates are preserved
|
|
365
367
|
- Only workflow-managed files are updated
|
|
366
368
|
|
|
369
|
+
### Ejecting
|
|
370
|
+
|
|
371
|
+
If you want to permanently opt out of the update system (e.g., to customize workflow files without future updates overwriting them), run:
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
/5:eject
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
This permanently removes the update infrastructure:
|
|
378
|
+
- Deletes `check-updates.js` hook, `update.md` and `eject.md` commands
|
|
379
|
+
- Deletes `.5/version.json` and `.5/.update-cache.json`
|
|
380
|
+
- Removes the update check hook entry from `.claude/settings.json`
|
|
381
|
+
|
|
382
|
+
All other workflow files remain untouched. **This is irreversible.** To restore update functionality, reinstall with `npx 5-phase-workflow`.
|
|
383
|
+
|
|
367
384
|
## Development
|
|
368
385
|
|
|
369
386
|
### Running Tests
|
package/bin/install.js
CHANGED
|
@@ -258,7 +258,11 @@ const LEGACY_REMOVED_FILES = [
|
|
|
258
258
|
'agents/integration-agent.md',
|
|
259
259
|
'agents/step-fixer.md',
|
|
260
260
|
'agents/step-verifier.md',
|
|
261
|
-
'agents/verification-agent.md'
|
|
261
|
+
'agents/verification-agent.md',
|
|
262
|
+
'templates/STACK.md',
|
|
263
|
+
'templates/STRUCTURE.md',
|
|
264
|
+
'templates/CONVENTIONS.md',
|
|
265
|
+
'templates/INTEGRATIONS.md'
|
|
262
266
|
];
|
|
263
267
|
|
|
264
268
|
// Get list of workflow-owned files/directories (not user-created)
|
|
@@ -274,8 +278,6 @@ function getWorkflowManagedFiles() {
|
|
|
274
278
|
|
|
275
279
|
// Skills: specific skill directories
|
|
276
280
|
skills: [
|
|
277
|
-
'build-project',
|
|
278
|
-
'run-tests',
|
|
279
281
|
'configure-project',
|
|
280
282
|
'generate-readme'
|
|
281
283
|
],
|
|
@@ -299,10 +301,6 @@ function getWorkflowManagedFiles() {
|
|
|
299
301
|
// Project documentation templates
|
|
300
302
|
'ARCHITECTURE.md',
|
|
301
303
|
'CONCERNS.md',
|
|
302
|
-
'CONVENTIONS.md',
|
|
303
|
-
'INTEGRATIONS.md',
|
|
304
|
-
'STACK.md',
|
|
305
|
-
'STRUCTURE.md',
|
|
306
304
|
'TESTING.md',
|
|
307
305
|
// Workflow output templates
|
|
308
306
|
'workflow/FEATURE-SPEC.md',
|
|
@@ -626,6 +624,7 @@ function showCommandsHelp(isGlobal) {
|
|
|
626
624
|
log.info(' /5:address-review-findings - Apply review findings & PR comments');
|
|
627
625
|
log.info(' /5:configure - Interactive project setup');
|
|
628
626
|
log.info(' /5:reconfigure - Refresh docs/skills (no Q&A)');
|
|
627
|
+
log.info(' /5:eject - Eject from update mechanism');
|
|
629
628
|
log.info(' /5:unlock - Remove planning guard lock');
|
|
630
629
|
log.info('');
|
|
631
630
|
log.info(`Config file: ${path.join(getDataPath(isGlobal), 'config.json')}`);
|
package/docs/workflow-guide.md
CHANGED
|
@@ -74,7 +74,7 @@ The installer copies workflow files to `.claude/` directory. **It does NOT creat
|
|
|
74
74
|
After completing these steps, you have:
|
|
75
75
|
- `.5/config.json` with your project settings
|
|
76
76
|
- `CLAUDE.md` with comprehensive project documentation
|
|
77
|
-
- `.5/
|
|
77
|
+
- `.5/ARCHITECTURE.md`, `.5/TESTING.md`, `.5/CONCERNS.md` with focused documentation
|
|
78
78
|
- Project-specific skills in `.claude/skills/`
|
|
79
79
|
|
|
80
80
|
**Without configuration, workflow commands will fail.**
|
package/package.json
CHANGED
|
@@ -296,8 +296,8 @@ If `gh api` is unavailable or fails, log the failure and continue. Do NOT abort
|
|
|
296
296
|
|
|
297
297
|
After all fixes are applied:
|
|
298
298
|
|
|
299
|
-
1. **Build:** Use the
|
|
300
|
-
2. **Test:** Use the
|
|
299
|
+
1. **Build:** Use the project's build skill (e.g., `run-build`) generated during configure
|
|
300
|
+
2. **Test:** Use the project's test skill (e.g., `run-tests`) generated during configure
|
|
301
301
|
3. **Lint:** Check for any lint warnings and errors
|
|
302
302
|
|
|
303
303
|
If build fails:
|
|
@@ -312,21 +312,23 @@ Generates CLAUDE.md with codebase analysis and creates project-specific skills.
|
|
|
312
312
|
## Requirements
|
|
313
313
|
|
|
314
314
|
### Requirement 1: Generate Documentation Files
|
|
315
|
-
Analyze the codebase and generate
|
|
316
|
-
|
|
317
|
-
**Create
|
|
318
|
-
- `.5/ARCHITECTURE.md` -
|
|
319
|
-
- `.5/
|
|
320
|
-
- `.5/
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
- `.5/INTEGRATIONS.md` - External services and APIs
|
|
324
|
-
- `.5/CONCERNS.md` - Tech debt, bugs, and risks
|
|
325
|
-
|
|
326
|
-
**Create CLAUDE.md as navigation hub:**
|
|
327
|
-
- Quick reference section with links to all `.5/*.md` files
|
|
315
|
+
Analyze the codebase and generate focused documentation capturing only non-derivable knowledge (skip version numbers, dependency lists, directory layouts, linter configs — Claude Code can look these up directly):
|
|
316
|
+
|
|
317
|
+
**Create documentation files in `.5/` folder:**
|
|
318
|
+
- `.5/ARCHITECTURE.md` - Architecture pattern, layers & data flow, key abstractions, non-obvious conventions, where to add new code
|
|
319
|
+
- `.5/TESTING.md` - Test organization, patterns, mocking approach, gotchas
|
|
320
|
+
- `.5/CONCERNS.md` - Tech debt, known issues, security/integration/performance notes (**only if concerns found — skip file entirely if nothing detected**)
|
|
321
|
+
|
|
322
|
+
**Create CLAUDE.md:**
|
|
328
323
|
- Project overview and build commands
|
|
329
|
-
-
|
|
324
|
+
- Links to whichever `.5/` documentation files were created
|
|
325
|
+
- Workflow rules section (verbatim):
|
|
326
|
+
```
|
|
327
|
+
## Workflow Rules
|
|
328
|
+
When running `/5:` workflow commands, follow the command instructions exactly as written.
|
|
329
|
+
Do not skip steps, combine phases, or proceed to actions not specified in the current command.
|
|
330
|
+
Each phase produces a specific artifact — do not create artifacts belonging to other phases.
|
|
331
|
+
```
|
|
330
332
|
- Mandatory coding guidelines:
|
|
331
333
|
1. Types should be clear and types should be available when possible
|
|
332
334
|
2. Use doc (jsdoc, javadoc, pydoc, etc) concisely. No doc is better than meaningless doc
|
|
@@ -363,17 +365,13 @@ Only generate rules for patterns that were actually detected:
|
|
|
363
365
|
|
|
364
366
|
## Acceptance Criteria
|
|
365
367
|
- [ ] `.5/` directory created
|
|
366
|
-
- [ ]
|
|
367
|
-
- [ ] `.5/ARCHITECTURE.md`
|
|
368
|
-
- [ ] `.5/
|
|
369
|
-
- [ ] `.5/
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
- [ ] `.5/INTEGRATIONS.md`
|
|
373
|
-
- [ ] `.5/CONCERNS.md`
|
|
374
|
-
- [ ] `CLAUDE.md` exists with references to `.5/` files
|
|
368
|
+
- [ ] Documentation files exist and contain only non-derivable knowledge:
|
|
369
|
+
- [ ] `.5/ARCHITECTURE.md` — architecture, conventions, where to add code
|
|
370
|
+
- [ ] `.5/TESTING.md` — test patterns and gotchas
|
|
371
|
+
- [ ] `.5/CONCERNS.md` — only if concerns were found (omit if empty)
|
|
372
|
+
- [ ] Empty sections omitted (no "Not detected" / "None found" placeholders)
|
|
373
|
+
- [ ] `CLAUDE.md` exists with references to created `.5/` files
|
|
375
374
|
- [ ] CLAUDE.md contains 6 coding guidelines
|
|
376
|
-
- [ ] No placeholder text like `{YYYY-MM-DD}` remains unfilled
|
|
377
375
|
- [ ] All specified project-specific skills are generated in `.claude/skills/`
|
|
378
376
|
- [ ] Generated skills reference actual project conventions
|
|
379
377
|
- [ ] If CLAUDE.md existed before, user-written sections are preserved
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 5:eject
|
|
3
|
+
description: Eject from the update mechanism — permanently removes update infrastructure
|
|
4
|
+
allowed-tools: Bash, Read, Edit, AskUserQuestion
|
|
5
|
+
user-invocable: true
|
|
6
|
+
model: haiku
|
|
7
|
+
context: fork
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<role>
|
|
11
|
+
You are a Workflow Ejector. You permanently remove the update infrastructure from this installation.
|
|
12
|
+
After ejecting, you are DONE.
|
|
13
|
+
</role>
|
|
14
|
+
|
|
15
|
+
# Eject from Update Mechanism
|
|
16
|
+
|
|
17
|
+
Ejecting permanently removes the update system from this installation. After ejecting:
|
|
18
|
+
- The update check hook (`check-updates.js`) is deleted
|
|
19
|
+
- The update command (`/5:update`) is deleted
|
|
20
|
+
- The eject command (`/5:eject`) is deleted
|
|
21
|
+
- Version tracking (`.5/version.json`) is deleted
|
|
22
|
+
- The update cache (`.5/.update-cache.json`) is deleted
|
|
23
|
+
- The `check-updates.js` hook entry is removed from `.claude/settings.json`
|
|
24
|
+
|
|
25
|
+
All other workflow files (commands, skills, hooks, templates) remain untouched.
|
|
26
|
+
|
|
27
|
+
**This is irreversible.** To restore update functionality, reinstall with `npx 5-phase-workflow`.
|
|
28
|
+
|
|
29
|
+
## Step 1: Check Current State
|
|
30
|
+
|
|
31
|
+
Read `.5/version.json`. If it doesn't exist, tell the user: "No 5-Phase Workflow installation found (or already ejected)." and stop.
|
|
32
|
+
|
|
33
|
+
Note the `packageVersion` for the confirmation message.
|
|
34
|
+
|
|
35
|
+
## Step 2: Confirm with User
|
|
36
|
+
|
|
37
|
+
Tell the user what ejecting means:
|
|
38
|
+
|
|
39
|
+
> **Eject from 5-Phase Workflow updates?**
|
|
40
|
+
>
|
|
41
|
+
> This will permanently delete:
|
|
42
|
+
> - `.claude/hooks/check-updates.js` (update check hook)
|
|
43
|
+
> - `.claude/commands/5/update.md` (update command)
|
|
44
|
+
> - `.claude/commands/5/eject.md` (this command)
|
|
45
|
+
> - `.5/version.json` (version tracking)
|
|
46
|
+
> - `.5/.update-cache.json` (update cache)
|
|
47
|
+
>
|
|
48
|
+
> The `check-updates.js` hook entry will also be removed from `.claude/settings.json`.
|
|
49
|
+
>
|
|
50
|
+
> All other workflow files remain untouched. To restore updates later, reinstall with `npx 5-phase-workflow`.
|
|
51
|
+
|
|
52
|
+
Ask: "Proceed with eject?"
|
|
53
|
+
|
|
54
|
+
If the user declines, stop here.
|
|
55
|
+
|
|
56
|
+
## Step 3: Delete Update Files
|
|
57
|
+
|
|
58
|
+
Run this command to delete the update-related files:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
rm -f .claude/hooks/check-updates.js .claude/commands/5/update.md .claude/commands/5/eject.md .5/version.json .5/.update-cache.json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Step 4: Clean Up settings.json
|
|
65
|
+
|
|
66
|
+
Read `.claude/settings.json`. Remove the hook entry from the `hooks.SessionStart` array where the command is `node .claude/hooks/check-updates.js`.
|
|
67
|
+
|
|
68
|
+
Specifically, find and remove the object in the `SessionStart` array that looks like:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"matcher": "startup",
|
|
73
|
+
"hooks": [
|
|
74
|
+
{
|
|
75
|
+
"type": "command",
|
|
76
|
+
"command": "node .claude/hooks/check-updates.js",
|
|
77
|
+
"timeout": 10
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If the `SessionStart` array becomes empty after removal, remove the `SessionStart` key entirely. Write the updated settings back.
|
|
84
|
+
|
|
85
|
+
## Step 5: Confirm
|
|
86
|
+
|
|
87
|
+
Tell the user:
|
|
88
|
+
|
|
89
|
+
> Ejected successfully. Update infrastructure has been removed from this installation (was v{packageVersion}).
|
|
90
|
+
>
|
|
91
|
+
> To restore update functionality, reinstall with: `npx 5-phase-workflow`
|
|
@@ -8,24 +8,27 @@ context: fork
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
<role>
|
|
11
|
-
You are a Feature Planner. Your
|
|
12
|
-
You do NOT implement code. You
|
|
13
|
-
You write ONLY to .5/.planning-active and .5/features/{name}/feature.md.
|
|
14
|
-
After creating the spec, you are
|
|
11
|
+
You are a Feature Planner. Your ONLY deliverable is a feature specification file (feature.md).
|
|
12
|
+
You do NOT implement code. You do NOT create implementation plans. You spawn ONLY Explore agents (subagent_type=Explore).
|
|
13
|
+
You write ONLY to .5/.planning-active, .5/features/{name}/codebase-scan.md, and .5/features/{name}/feature.md.
|
|
14
|
+
After creating the spec, you are FINISHED. You do not continue. You do not offer to continue.
|
|
15
15
|
</role>
|
|
16
16
|
|
|
17
17
|
<constraints>
|
|
18
18
|
HARD CONSTRAINTS — violations waste tokens and get blocked by plan-guard:
|
|
19
19
|
- NEVER write code, pseudo-code, or implementation snippets in any output
|
|
20
20
|
- NEVER describe HOW something will be implemented (file contents, signatures, class structures)
|
|
21
|
+
- NEVER create an implementation plan, file list, component breakdown, or step-by-step build guide — that is Phase 2's job
|
|
22
|
+
- NEVER suggest "shall I continue with implementation planning?" or "let me create the plan" — you are DONE after feature.md
|
|
23
|
+
- NEVER offer to proceed to the next phase — the user will invoke `/5:plan-implementation` themselves
|
|
21
24
|
- NEVER spawn Task agents with subagent_type other than Explore
|
|
22
|
-
- NEVER write to any file except .5/features/{name}/
|
|
25
|
+
- NEVER write to any file except .5/.planning-active, .5/features/{name}/codebase-scan.md, and .5/features/{name}/feature.md
|
|
23
26
|
- NEVER call EnterPlanMode — the workflow has its own planning process
|
|
24
27
|
- NEVER use Bash to create, write, or modify files — this bypasses the plan-guard and is a constraint violation
|
|
25
|
-
- NEVER continue past the completion message — when you output "Feature spec created at...", you are
|
|
28
|
+
- NEVER continue past the completion message — when you output "Feature spec created at...", you are FINISHED
|
|
26
29
|
- The feature spec describes WHAT and WHY, never HOW
|
|
27
|
-
- If you feel the urge to
|
|
28
|
-
- Your output is a SPECIFICATION, not a design document. No code. No file layouts. No API shapes.
|
|
30
|
+
- If you feel the urge to plan implementation or write code, STOP — ask a clarifying question instead
|
|
31
|
+
- Your output is a SPECIFICATION, not a design document. No code. No file layouts. No API shapes. No implementation plans.
|
|
29
32
|
</constraints>
|
|
30
33
|
|
|
31
34
|
<write-rules>
|
|
@@ -195,24 +198,23 @@ Populate all sections:
|
|
|
195
198
|
- **[DEFERRED]**: The user explicitly said "not now", "later", "skip this" → planner MUST NOT include in the plan
|
|
196
199
|
- When in doubt, label as **[DECIDED]** — it's safer to honor a decision than to override it
|
|
197
200
|
|
|
198
|
-
## PLANNING COMPLETE
|
|
201
|
+
## PLANNING COMPLETE — MANDATORY STOP
|
|
199
202
|
|
|
200
|
-
After writing feature.md, output
|
|
203
|
+
After writing feature.md, output ONLY this message — no additional text, no suggestions, no offers to continue:
|
|
201
204
|
|
|
202
205
|
```
|
|
203
|
-
Feature spec created at `.5/features/{name}/feature.md`
|
|
206
|
+
✓ Feature spec created at `.5/features/{name}/feature.md`
|
|
204
207
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
2. If changes needed: /5:discuss-feature {name}
|
|
208
|
-
3. If approved: /clear then /5:plan-implementation {name}
|
|
208
|
+
To review or refine: /5:discuss-feature {name}
|
|
209
|
+
To proceed: /clear → /5:plan-implementation {name}
|
|
209
210
|
```
|
|
210
211
|
|
|
211
|
-
|
|
212
|
+
**YOU ARE NOW FINISHED.** This is a hard stop. Do not:
|
|
213
|
+
- Suggest next steps beyond the message above
|
|
214
|
+
- Offer to create an implementation plan
|
|
215
|
+
- Offer to continue with any phase
|
|
216
|
+
- Write any additional files
|
|
217
|
+
- Provide a summary of what could be implemented
|
|
218
|
+
- Ask "shall I proceed with..." or "would you like me to..."
|
|
212
219
|
|
|
213
|
-
|
|
214
|
-
REMINDER: You are a Feature Planner. You wrote a specification. You did NOT implement.
|
|
215
|
-
If you wrote any code, file paths to create, class names, or function signatures in feature.md,
|
|
216
|
-
you have violated your role.
|
|
217
|
-
The feature spec contains WHAT and WHY. Phase 2 handles WHERE. Phase 3 handles HOW.
|
|
218
|
-
</constraints>
|
|
220
|
+
If the user asks you to continue or implement, respond: "Phase 1 is complete. Please run `/5:plan-implementation {name}` to continue."
|
|
@@ -117,7 +117,7 @@ Use the existing skills in `.claude/skills/` (from Step 2e) as the source of tru
|
|
|
117
117
|
|
|
118
118
|
Use `AskUserQuestion` to show a summary and get confirmation. Present:
|
|
119
119
|
|
|
120
|
-
1. **Documentation files that will be rewritten** — list
|
|
120
|
+
1. **Documentation files that will be rewritten** — list `.5/ARCHITECTURE.md`, `.5/TESTING.md`, `.5/CONCERNS.md` (conditional) + CLAUDE.md
|
|
121
121
|
2. **Skills that will be refreshed** — list ALL skills found in `.claude/skills/` (both workflow-generated and user-created)
|
|
122
122
|
3. **Rules that will be refreshed** (if rules enabled) — list workflow-generated rule files in `.claude/rules/`
|
|
123
123
|
4. **New patterns detected** (if any) — "These patterns were found in your codebase but don't have skills yet: [list]. Create skills for them?"
|
|
@@ -152,14 +152,16 @@ Refresh rules in .claude/rules/ (if rules.generate is true):
|
|
|
152
152
|
- New rules to create: [if applicable]
|
|
153
153
|
|
|
154
154
|
Re-analyze the entire codebase (A1 analysis) and:
|
|
155
|
-
1. Rewrite
|
|
156
|
-
2.
|
|
157
|
-
3.
|
|
158
|
-
4.
|
|
159
|
-
5.
|
|
160
|
-
6.
|
|
161
|
-
7.
|
|
162
|
-
8.
|
|
155
|
+
1. Rewrite .5/ARCHITECTURE.md and .5/TESTING.md
|
|
156
|
+
2. Rewrite .5/CONCERNS.md (or delete if no concerns found)
|
|
157
|
+
3. Delete legacy docs if they exist: .5/STACK.md, .5/STRUCTURE.md, .5/CONVENTIONS.md, .5/INTEGRATIONS.md
|
|
158
|
+
4. Update CLAUDE.md (preserve user-written sections)
|
|
159
|
+
5. Refresh ALL skills in .claude/skills/ — read current conventions from codebase and update each skill
|
|
160
|
+
6. Create new skills for newly-added patterns
|
|
161
|
+
7. Remove skills the user chose to drop
|
|
162
|
+
8. Refresh all workflow-generated rule files in .claude/rules/ with updated conventions
|
|
163
|
+
9. Create new rule files for newly-detected patterns
|
|
164
|
+
10. Remove rule files the user chose to drop"
|
|
163
165
|
```
|
|
164
166
|
|
|
165
167
|
Use `subagent_type: "general-purpose"` for the Task.
|
package/src/hooks/plan-guard.js
CHANGED
|
@@ -99,9 +99,15 @@ process.stdin.on('end', () => {
|
|
|
99
99
|
|
|
100
100
|
if (toolName === 'Write' || toolName === 'Edit') {
|
|
101
101
|
const filePath = toolInput.file_path || '';
|
|
102
|
-
if (
|
|
102
|
+
if (!filePath) {
|
|
103
|
+
process.exit(0);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const phase = getPlanningPhase(workspaceDir);
|
|
107
|
+
|
|
108
|
+
// First check: block anything outside .5/
|
|
109
|
+
if (!isInsideDotFive(filePath, workspaceDir)) {
|
|
103
110
|
const blockCount = incrementBlockCount(workspaceDir);
|
|
104
|
-
const phase = getPlanningPhase(workspaceDir);
|
|
105
111
|
const isSourceFile = !filePath.includes('.5/') && !filePath.includes('.claude/');
|
|
106
112
|
const escalation = blockCount >= 3
|
|
107
113
|
? ` CRITICAL: Block #${blockCount}. You have attempted to write source files ${blockCount} times. You are a PLANNER, not an implementer. Writing source code is Phase 3's job. Return to your Progress Checklist, finish your planning artifact, and STOP.`
|
|
@@ -118,6 +124,22 @@ process.stdin.on('end', () => {
|
|
|
118
124
|
);
|
|
119
125
|
process.exit(2);
|
|
120
126
|
}
|
|
127
|
+
|
|
128
|
+
// Second check: during plan-feature, only allow specific files
|
|
129
|
+
if (phase === 'plan-feature' && !isAllowedPlanFeatureFile(filePath, workspaceDir)) {
|
|
130
|
+
const blockCount = incrementBlockCount(workspaceDir);
|
|
131
|
+
const escalation = blockCount >= 3
|
|
132
|
+
? ` CRITICAL: Block #${blockCount}. You are attempting to create implementation artifacts during Phase 1. Phase 1 ONLY produces feature.md. STOP and output your completion message.`
|
|
133
|
+
: '';
|
|
134
|
+
process.stderr.write(
|
|
135
|
+
`BLOCKED: During plan-feature (Phase 1), you may only write to .planning-active, codebase-scan.md, and feature.md. ` +
|
|
136
|
+
`Attempted: "${filePath}". ` +
|
|
137
|
+
`You are creating implementation artifacts (e.g., plan.md) which belongs to Phase 2. ` +
|
|
138
|
+
`REDIRECT: If you have already written feature.md, output the completion message and STOP. ` +
|
|
139
|
+
`Do NOT create implementation plans, file lists, or any other artifacts.${escalation}`
|
|
140
|
+
);
|
|
141
|
+
process.exit(2);
|
|
142
|
+
}
|
|
121
143
|
}
|
|
122
144
|
|
|
123
145
|
process.exit(0);
|
|
@@ -127,6 +149,23 @@ process.stdin.on('end', () => {
|
|
|
127
149
|
}
|
|
128
150
|
});
|
|
129
151
|
|
|
152
|
+
function isAllowedPlanFeatureFile(filePath, workspaceDir) {
|
|
153
|
+
const resolved = path.resolve(workspaceDir, filePath);
|
|
154
|
+
const dotFiveDir = path.join(workspaceDir, '.5');
|
|
155
|
+
|
|
156
|
+
// Allow .5/.planning-active
|
|
157
|
+
if (resolved === path.join(dotFiveDir, '.planning-active')) return true;
|
|
158
|
+
|
|
159
|
+
// Allow .5/features/{name}/feature.md and .5/features/{name}/codebase-scan.md
|
|
160
|
+
const featuresDir = path.join(dotFiveDir, 'features');
|
|
161
|
+
if (resolved.startsWith(featuresDir + path.sep)) {
|
|
162
|
+
const basename = path.basename(resolved);
|
|
163
|
+
if (basename === 'feature.md' || basename === 'codebase-scan.md') return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
130
169
|
function isInsideDotFive(filePath, workspaceDir) {
|
|
131
170
|
const resolved = path.resolve(workspaceDir, filePath);
|
|
132
171
|
const dotFiveDir = path.join(workspaceDir, '.5');
|
package/src/hooks/statusline.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Claude Code Statusline
|
|
3
|
-
// Shows: model |
|
|
3
|
+
// Shows: model | folder | branch | off-peak | 5hr-usage | cost | context | reset-time
|
|
4
4
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
|
-
const
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
8
|
|
|
9
9
|
// Read JSON from stdin
|
|
10
10
|
let input = '';
|
|
@@ -13,77 +13,116 @@ process.stdin.on('data', chunk => input += chunk);
|
|
|
13
13
|
process.stdin.on('end', () => {
|
|
14
14
|
try {
|
|
15
15
|
const data = JSON.parse(input);
|
|
16
|
+
const parts = [];
|
|
17
|
+
|
|
18
|
+
// 🤖 Model
|
|
16
19
|
const model = data.model?.display_name || 'Claude';
|
|
20
|
+
parts.push(`\x1b[36m🤖 ${model}\x1b[0m`);
|
|
21
|
+
|
|
22
|
+
// 📁 Folder (basename only)
|
|
17
23
|
const dir = data.workspace?.current_dir || process.cwd();
|
|
18
|
-
const
|
|
19
|
-
|
|
24
|
+
const folderName = path.basename(dir);
|
|
25
|
+
parts.push(`\x1b[90m📁 ${folderName}\x1b[0m`);
|
|
20
26
|
|
|
21
|
-
//
|
|
22
|
-
let
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
// 🌿 Branch
|
|
28
|
+
let branch = data.worktree?.branch || '';
|
|
29
|
+
if (!branch) {
|
|
30
|
+
try {
|
|
31
|
+
branch = execSync('git rev-parse --abbrev-ref HEAD', {
|
|
32
|
+
encoding: 'utf8', cwd: dir, stdio: ['pipe', 'pipe', 'pipe']
|
|
33
|
+
}).trim();
|
|
34
|
+
} catch (e) { branch = ''; }
|
|
35
|
+
}
|
|
36
|
+
if (branch && branch !== 'HEAD') {
|
|
37
|
+
parts.push(`\x1b[32m🌿 ${branch}\x1b[0m`);
|
|
38
|
+
}
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
// 🚀 Off-peak indicator (weekdays before 5 AM or after 11 AM PT; all weekends)
|
|
41
|
+
// PT = UTC-8 (PST) or UTC-7 (PDT). Use UTC-7 as approximation (covers PDT/PST conservatively).
|
|
42
|
+
const nowUtc = new Date();
|
|
43
|
+
const ptHour = (nowUtc.getUTCHours() - 7 + 24) % 24; // approximate PT
|
|
44
|
+
const ptDay = new Date(nowUtc.getTime() - 7 * 3600 * 1000).getUTCDay(); // 0=Sun,6=Sat
|
|
45
|
+
const isWeekend = ptDay === 0 || ptDay === 6;
|
|
46
|
+
const isPeak = !isWeekend && ptHour >= 5 && ptHour < 11;
|
|
47
|
+
if (!isPeak) {
|
|
48
|
+
parts.push('\x1b[32m🚀 off-peak\x1b[0m');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ⚡ 5-hour session usage
|
|
52
|
+
const fiveHrUsed = data.rate_limits?.five_hour?.used_percentage;
|
|
53
|
+
if (fiveHrUsed != null) {
|
|
54
|
+
const pct = Math.round(fiveHrUsed);
|
|
55
|
+
const color = pct < 50 ? '\x1b[32m' : pct < 75 ? '\x1b[33m' : '\x1b[31m';
|
|
56
|
+
parts.push(`${color}⚡ ${pct}%\x1b[0m`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 💰 Cost
|
|
60
|
+
const costUsd = data.cost?.total_cost_usd;
|
|
61
|
+
if (costUsd != null) {
|
|
62
|
+
const fmt = costUsd < 0.01 ? costUsd.toFixed(3) : costUsd.toFixed(2);
|
|
63
|
+
parts.push(`\x1b[33m💰 $${fmt}\x1b[0m`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 📊 Context window (progress bar)
|
|
67
|
+
const ctxUsed = data.context_window?.used_percentage;
|
|
68
|
+
const ctxRemaining = data.context_window?.remaining_percentage;
|
|
69
|
+
if (ctxUsed != null || ctxRemaining != null) {
|
|
70
|
+
const used = ctxUsed != null
|
|
71
|
+
? Math.round(ctxUsed)
|
|
72
|
+
: Math.max(0, Math.min(100, 100 - Math.round(ctxRemaining)));
|
|
28
73
|
const filled = Math.floor(used / 10);
|
|
29
74
|
const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
|
|
75
|
+
let color;
|
|
76
|
+
if (used < 50) color = '\x1b[32m';
|
|
77
|
+
else if (used < 65) color = '\x1b[33m';
|
|
78
|
+
else if (used < 80) color = '\x1b[38;5;208m';
|
|
79
|
+
else color = '\x1b[5;31m';
|
|
80
|
+
parts.push(`${color}🧠 ${bar} ${used}%\x1b[0m`);
|
|
81
|
+
}
|
|
30
82
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
83
|
+
// ⏱ Reset time (time until 5hr window resets)
|
|
84
|
+
const resetAt = data.rate_limits?.five_hour?.resets_at;
|
|
85
|
+
if (resetAt) {
|
|
86
|
+
const remaining = resetAt - Math.floor(Date.now() / 1000);
|
|
87
|
+
if (remaining > 0) {
|
|
88
|
+
const h = Math.floor(remaining / 3600);
|
|
89
|
+
const m = Math.floor((remaining % 3600) / 60);
|
|
90
|
+
const label = h > 0 ? `${h}h${m}m` : `${m}m`;
|
|
91
|
+
parts.push(`\x1b[90m⏱ ${label}\x1b[0m`);
|
|
40
92
|
}
|
|
41
93
|
}
|
|
42
94
|
|
|
43
|
-
//
|
|
44
|
-
const shortDir = dir.replace(os.homedir(), '~');
|
|
45
|
-
|
|
46
|
-
// Check for available update and reconfigure reminder
|
|
47
|
-
let updateIndicator = '';
|
|
48
|
-
let reconfigIndicator = '';
|
|
95
|
+
// Update and reconfigure indicators
|
|
49
96
|
try {
|
|
50
97
|
const versionFile = path.join(dir, '.5', 'version.json');
|
|
51
98
|
const versionData = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
|
|
52
99
|
|
|
53
|
-
// Update check — read latestAvailableVersion from cache file (gitignored)
|
|
54
100
|
const cacheFile = path.join(dir, '.5', '.update-cache.json');
|
|
55
101
|
let latest = null;
|
|
56
102
|
if (fs.existsSync(cacheFile)) {
|
|
57
103
|
try {
|
|
58
104
|
const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
59
105
|
latest = cache.latestAvailableVersion || null;
|
|
60
|
-
} catch(e) {}
|
|
106
|
+
} catch (e) {}
|
|
61
107
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
updateIndicator = ` | \x1b[33m↑${latest} → /5:update\x1b[0m`;
|
|
108
|
+
if (latest && versionData.packageVersion && compareVersions(versionData.packageVersion, latest) < 0) {
|
|
109
|
+
parts.push(`\x1b[33m↑${latest} → /5:update\x1b[0m`);
|
|
65
110
|
}
|
|
66
111
|
|
|
67
|
-
// Reconfigure check (reads flag file in .5/, gitignored)
|
|
68
112
|
const flagFile = path.join(dir, '.5', '.reconfig-reminder');
|
|
69
113
|
if (fs.existsSync(flagFile)) {
|
|
70
|
-
|
|
114
|
+
parts.push(`\x1b[35m↻ /5:reconfigure\x1b[0m`);
|
|
71
115
|
}
|
|
72
|
-
} catch (e) {
|
|
73
|
-
// No version file or parse error — no indicator
|
|
74
|
-
}
|
|
116
|
+
} catch (e) {}
|
|
75
117
|
|
|
76
|
-
|
|
77
|
-
const statusline = `\x1b[36m${model}\x1b[0m | \x1b[90m${shortDir}\x1b[0m${ctx}${updateIndicator}${reconfigIndicator}`;
|
|
78
|
-
process.stdout.write(statusline);
|
|
118
|
+
process.stdout.write(parts.join(' | '));
|
|
79
119
|
|
|
80
120
|
} catch (e) {
|
|
81
|
-
// Silent fail
|
|
121
|
+
// Silent fail — don't break statusline on parse errors
|
|
82
122
|
}
|
|
83
123
|
});
|
|
84
124
|
|
|
85
125
|
// Compare semver versions: returns -1 if v1 < v2, 0 if equal, 1 if v1 > v2
|
|
86
|
-
// Uses parseInt to handle pre-release tags (e.g., "2-beta" → 2)
|
|
87
126
|
function compareVersions(v1, v2) {
|
|
88
127
|
const parts1 = v1.split('.').map(p => parseInt(p, 10) || 0);
|
|
89
128
|
const parts2 = v2.split('.').map(p => parseInt(p, 10) || 0);
|
|
@@ -92,4 +131,4 @@ function compareVersions(v1, v2) {
|
|
|
92
131
|
if (parts1[i] < parts2[i]) return -1;
|
|
93
132
|
}
|
|
94
133
|
return 0;
|
|
95
|
-
}
|
|
134
|
+
}
|