@codename_inc/spectre 3.7.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/LICENSE +21 -0
- package/README.md +411 -0
- package/bin/spectre.js +8 -0
- package/package.json +23 -0
- package/plugins/spectre/.claude-plugin/plugin.json +5 -0
- package/plugins/spectre/agents/analyst.md +122 -0
- package/plugins/spectre/agents/dev.md +70 -0
- package/plugins/spectre/agents/finder.md +105 -0
- package/plugins/spectre/agents/patterns.md +207 -0
- package/plugins/spectre/agents/reviewer.md +128 -0
- package/plugins/spectre/agents/sync.md +151 -0
- package/plugins/spectre/agents/tester.md +209 -0
- package/plugins/spectre/agents/web-research.md +109 -0
- package/plugins/spectre/commands/architecture_review.md +120 -0
- package/plugins/spectre/commands/clean.md +313 -0
- package/plugins/spectre/commands/code_review.md +408 -0
- package/plugins/spectre/commands/create_plan.md +117 -0
- package/plugins/spectre/commands/create_tasks.md +374 -0
- package/plugins/spectre/commands/create_test_guide.md +120 -0
- package/plugins/spectre/commands/evaluate.md +50 -0
- package/plugins/spectre/commands/execute.md +87 -0
- package/plugins/spectre/commands/fix.md +61 -0
- package/plugins/spectre/commands/forget.md +58 -0
- package/plugins/spectre/commands/handoff.md +161 -0
- package/plugins/spectre/commands/kickoff.md +115 -0
- package/plugins/spectre/commands/learn.md +15 -0
- package/plugins/spectre/commands/plan.md +170 -0
- package/plugins/spectre/commands/plan_review.md +33 -0
- package/plugins/spectre/commands/quick_dev.md +101 -0
- package/plugins/spectre/commands/rebase.md +73 -0
- package/plugins/spectre/commands/recall.md +5 -0
- package/plugins/spectre/commands/research.md +159 -0
- package/plugins/spectre/commands/scope.md +119 -0
- package/plugins/spectre/commands/ship.md +172 -0
- package/plugins/spectre/commands/sweep.md +82 -0
- package/plugins/spectre/commands/test.md +380 -0
- package/plugins/spectre/commands/ux_spec.md +91 -0
- package/plugins/spectre/commands/validate.md +343 -0
- package/plugins/spectre/hooks/hooks.json +34 -0
- package/plugins/spectre/hooks/scripts/bootstrap.cjs +99 -0
- package/plugins/spectre/hooks/scripts/handoff-resume.cjs +410 -0
- package/plugins/spectre/hooks/scripts/lib.cjs +83 -0
- package/plugins/spectre/hooks/scripts/load-knowledge.cjs +120 -0
- package/plugins/spectre/hooks/scripts/precompact-warning.cjs +19 -0
- package/plugins/spectre/hooks/scripts/register_learning.cjs +144 -0
- package/plugins/spectre/hooks/scripts/test_bootstrap.cjs +84 -0
- package/plugins/spectre/hooks/scripts/test_handoff-resume.cjs +858 -0
- package/plugins/spectre/hooks/scripts/test_load-knowledge.cjs +285 -0
- package/plugins/spectre/hooks/scripts/test_register-learning.cjs +146 -0
- package/plugins/spectre/skills/spectre-apply/SKILL.md +189 -0
- package/plugins/spectre/skills/spectre-guide/SKILL.md +358 -0
- package/plugins/spectre/skills/spectre-learn/SKILL.md +635 -0
- package/plugins/spectre/skills/spectre-learn/references/recall-template.md +31 -0
- package/plugins/spectre/skills/spectre-tdd/SKILL.md +111 -0
- package/src/config.test.js +134 -0
- package/src/install.test.js +273 -0
- package/src/lib/config.js +516 -0
- package/src/lib/constants.js +60 -0
- package/src/lib/doctor.js +168 -0
- package/src/lib/install.js +482 -0
- package/src/lib/knowledge.js +217 -0
- package/src/lib/paths.js +98 -0
- package/src/lib/project.js +473 -0
- package/src/main.js +150 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: π» | Comprehensive post implementation requirement validation using subagents
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# validate: Scope delivery verification and gap analysis
|
|
6
|
+
|
|
7
|
+
## Description
|
|
8
|
+
|
|
9
|
+
- **What** β Validate implementation against scope/tasks docs, dispatch parallel subagents per area, produce single actionable gap remediation document.
|
|
10
|
+
- **Approach** β Primary agent chunks work by scope items or parent tasks, dispatches one @analyst per area IN PARALLEL. Each subagent validates their area including E2E UX accessibility.
|
|
11
|
+
- **Outcome** β Single `validation_gaps.md` with actionable tasks ready for immediate implementation.
|
|
12
|
+
|
|
13
|
+
## Core Validation Principle
|
|
14
|
+
|
|
15
|
+
> **"Definition β Connection β Reachability"**
|
|
16
|
+
|
|
17
|
+
Three levels of implementation completeness:
|
|
18
|
+
1. **Defined**: Code exists in a file
|
|
19
|
+
2. **Connected**: Code is imported/called by other code
|
|
20
|
+
3. **Reachable**: A user action can trigger the code path
|
|
21
|
+
|
|
22
|
+
Validation must verify all three levels. A feature with Level 1 but not Level 2 or 3 is NOT completeβit's dead code that happens to match the requirement description.
|
|
23
|
+
|
|
24
|
+
When verifying any implementation:
|
|
25
|
+
- Don't stop at "function X exists in file Y"
|
|
26
|
+
- Continue to "function X is called by Z at file:line"
|
|
27
|
+
- Continue to "Z is triggered when user does W"
|
|
28
|
+
|
|
29
|
+
## ARGUMENTS Input
|
|
30
|
+
|
|
31
|
+
**REQUIRED**: User must provide scope documents to validate against.
|
|
32
|
+
|
|
33
|
+
<ARGUMENTS> $ARGUMENTS </ARGUMENTS>
|
|
34
|
+
|
|
35
|
+
## Step (1/4) - Gather Validation Inputs
|
|
36
|
+
|
|
37
|
+
- **Action** β CheckArguments: Verify user provided scope documents.
|
|
38
|
+
|
|
39
|
+
- **If** ARGUMENTS contains file paths or "use thread context" β proceed
|
|
40
|
+
|
|
41
|
+
- **Else** β Immediately reply:
|
|
42
|
+
|
|
43
|
+
> "What should I validate against? Please provide:
|
|
44
|
+
>
|
|
45
|
+
> - Path to scope document (e.g., `docs/tasks/main/scope.md`)
|
|
46
|
+
> - Path to tasks document (e.g., `docs/tasks/main/tasks.md`)
|
|
47
|
+
> - Or say 'use thread context' to validate against our conversation"
|
|
48
|
+
|
|
49
|
+
- **Wait** β User provides validation inputs
|
|
50
|
+
|
|
51
|
+
- **Action** β ReadScopeDocs: Read provided documents completely (no limits).
|
|
52
|
+
|
|
53
|
+
- Extract all requirements, acceptance criteria, deliverables
|
|
54
|
+
- Document scope boundaries (in-scope / out-of-scope)
|
|
55
|
+
- Note constraints and success metrics
|
|
56
|
+
|
|
57
|
+
- **Action** β ChunkIntoValidationAreas: Break scope into discrete validation areas.
|
|
58
|
+
|
|
59
|
+
- **From tasks.md**: Each parent task (e.g., \[1.1\], \[1.2\]) = one validation area
|
|
60
|
+
- **From scope.md**: Each "In Scope" item = one validation area
|
|
61
|
+
- **From thread context**: Each discussed feature/requirement = one validation area
|
|
62
|
+
- Aim for 3-8 validation areas (merge small items, split large ones)
|
|
63
|
+
|
|
64
|
+
- **Action** β CreateValidationManifest: Document chunks before dispatch.
|
|
65
|
+
|
|
66
|
+
```plaintext
|
|
67
|
+
Validation Areas:
|
|
68
|
+
1. {Area Name} β {What to validate}
|
|
69
|
+
- Source: {requirement text from scope doc}
|
|
70
|
+
- Expected: {what should exist}
|
|
71
|
+
2. ...
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Step (2/4) - Dispatch Parallel Validation Agents
|
|
75
|
+
|
|
76
|
+
**CRITICAL**: Dispatch ALL validation agents in parallel in a SINGLE message with multiple Task tool calls. Do NOT dispatch sequentially.
|
|
77
|
+
|
|
78
|
+
- **Action** β DispatchValidators: Launch one @analyst per validation area IN PARALLEL.
|
|
79
|
+
|
|
80
|
+
**Subagent Prompt Template**:
|
|
81
|
+
|
|
82
|
+
```plaintext
|
|
83
|
+
You are validating scope delivery for ONE specific area.
|
|
84
|
+
|
|
85
|
+
## Context Documents
|
|
86
|
+
- Scope: {path or "thread context"}
|
|
87
|
+
- Tasks: {path if provided}
|
|
88
|
+
- Branch: {branch_name}
|
|
89
|
+
|
|
90
|
+
## Your Validation Area
|
|
91
|
+
**Area**: {area_name}
|
|
92
|
+
**Source Requirement**: {exact text from scope/tasks doc}
|
|
93
|
+
**Expected Deliverables**: {what should exist}
|
|
94
|
+
|
|
95
|
+
## Your Task
|
|
96
|
+
1. Investigate YOUR SPECIFIC AREA only
|
|
97
|
+
2. For each requirement, determine:
|
|
98
|
+
- **Status**: β
Delivered | β οΈ Partial | π Dead Code | β Missing
|
|
99
|
+
- β
**Delivered**: Defined AND connected AND reachable from user action
|
|
100
|
+
- β οΈ **Partial**: Code exists but has broken/missing connections
|
|
101
|
+
- π **Dead Code**: Code exists but has zero usage sites
|
|
102
|
+
- β **Missing**: Code does not exist
|
|
103
|
+
- **Evidence**: Must include BOTH:
|
|
104
|
+
1. Definition site: `file:line` where code is defined
|
|
105
|
+
2. Usage site: `file:line` where code is called/rendered
|
|
106
|
+
- If you can only cite definition without usage β status is β οΈ or π
|
|
107
|
+
- **Gap**: What's missing (if any)
|
|
108
|
+
|
|
109
|
+
3. **CRITICAL - Reachability Verification**:
|
|
110
|
+
- Trace the COMPLETE chain from user action to implementation:
|
|
111
|
+
- Entry point: What user action triggers this? (click, route, event)
|
|
112
|
+
- Call chain: How does execution flow to the implementation?
|
|
113
|
+
- Terminal point: What side effect/UI change occurs?
|
|
114
|
+
- A broken link at ANY point = β οΈ NOT FULLY DELIVERED
|
|
115
|
+
- For every function/component, grep for USAGE not just DEFINITION:
|
|
116
|
+
- Functions: Search for `functionName(` to find invocations
|
|
117
|
+
- Components: Search for `<ComponentName` to find render sites
|
|
118
|
+
- Hooks: Search for `useHookName(` to find consumers
|
|
119
|
+
- Props: Search for `propName={` to find where passed
|
|
120
|
+
- Zero usage sites = π Dead Code
|
|
121
|
+
|
|
122
|
+
4. **CRITICAL - Consumer-First Validation (Render-Backward Trace)**:
|
|
123
|
+
For UI features, start from the FINAL RENDER and trace BACKWARDS:
|
|
124
|
+
- What component renders the feature output? (exact JSX location)
|
|
125
|
+
- What variable does that JSX use? (exact variable name)
|
|
126
|
+
- Where does that variable come from? (hook, prop, computed value)
|
|
127
|
+
- Trace back to the user action. Is every link connected?
|
|
128
|
+
|
|
129
|
+
Example (filter feature):
|
|
130
|
+
- Renders: `BoardColumn` receives `tasks` prop at line 45
|
|
131
|
+
- Variable: `tasks` comes from `getFilteredTasksForBoard(board.id)`
|
|
132
|
+
- Source: `getFilteredTasksForBoard` uses... `getTasksForBoard` from drag hook
|
|
133
|
+
- β BROKEN: This bypasses `displayTasks` from filter hook!
|
|
134
|
+
|
|
135
|
+
If you can only trace forward (definition β usage) but NOT backward
|
|
136
|
+
(render β source), you haven't verified the last mile.
|
|
137
|
+
|
|
138
|
+
5. **CRITICAL - Dead Computation Detection**:
|
|
139
|
+
List every computed value that is NOT directly consumed by a render:
|
|
140
|
+
- For each hook return value, grep for where it's destructured/used
|
|
141
|
+
- For each computed const, grep for where it's referenced
|
|
142
|
+
- A value that's computed but never reaches JSX = π Dead Code
|
|
143
|
+
|
|
144
|
+
Example:
|
|
145
|
+
- `displayTasks` from `useKanbanFilters` β used where?
|
|
146
|
+
- Passed to `TasksHeroHeader` β
|
|
147
|
+
- Used in `getFilteredTasksForBoard`? β NO β uses different source
|
|
148
|
+
- Computed but not in render chain = BUG
|
|
149
|
+
|
|
150
|
+
6. **Old Code Path Audit**:
|
|
151
|
+
When new functionality replaces old patterns:
|
|
152
|
+
- What OLD code handled this before? (imports, hooks, functions)
|
|
153
|
+
- Is the old code still being called anywhere?
|
|
154
|
+
- Are there duplicate data sources for the same concern?
|
|
155
|
+
- If old path still active β β οΈ Partial (new code bypassed)
|
|
156
|
+
|
|
157
|
+
7. Check for scope creep: anything beyond the requirement
|
|
158
|
+
|
|
159
|
+
## Output Format
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
AREA: {area_name} STATUS: {overall: Delivered | Partial | Dead Code | Missing}
|
|
163
|
+
|
|
164
|
+
REQUIREMENTS:
|
|
165
|
+
|
|
166
|
+
- \[REQ-1\] {requirement}
|
|
167
|
+
Status: {β
|β οΈ|π|β}
|
|
168
|
+
Definition: {file:line where defined}
|
|
169
|
+
Usage: {file:line where called/rendered, or "NONE FOUND"}
|
|
170
|
+
Reachability: {user action β ... β this code, or "NOT REACHABLE"}
|
|
171
|
+
Render Chain: {JSX β variable β source β user action, or "BROKEN AT {link}"}
|
|
172
|
+
Gap: {what's missing}
|
|
173
|
+
Remediation: {specific fix β what to wire, what to replace, what to add}
|
|
174
|
+
- Produces: {what the fix outputs}
|
|
175
|
+
- Consumed by: {what should use it}
|
|
176
|
+
- Replaces: {old path to remove, or "N/A"}
|
|
177
|
+
|
|
178
|
+
DEAD COMPUTATIONS:
|
|
179
|
+
- {variable name} in {file}: computed but not consumed by render
|
|
180
|
+
- Remediation: {wire to X, or delete if unnecessary}
|
|
181
|
+
|
|
182
|
+
OLD CODE PATHS:
|
|
183
|
+
- {old function/hook}: still active at {file:line}, bypasses new implementation
|
|
184
|
+
- Remediation: {replace calls with new path, or remove}
|
|
185
|
+
|
|
186
|
+
SCOPE CREEP: {any features beyond scope}
|
|
187
|
+
|
|
188
|
+
SUMMARY: {1-2 sentences}
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Verification Patterns for Subagents**:
|
|
193
|
+
|
|
194
|
+
| Checking | Search Pattern | Meaning |
|
|
195
|
+
|----------|---------------|---------|
|
|
196
|
+
| Function called | `functionName\(` | Invocation exists |
|
|
197
|
+
| Component renders | `<ComponentName` | JSX usage exists |
|
|
198
|
+
| Hook consumed | `useHookName\(` | Hook is used |
|
|
199
|
+
| Prop passed | `propName={` | Parent passes prop |
|
|
200
|
+
| Export imported | `import.*Name` | Module consumed |
|
|
201
|
+
|
|
202
|
+
**Common broken link patterns to check**:
|
|
203
|
+
- Callback defined but never passed as prop
|
|
204
|
+
- Prop received but never used in component body
|
|
205
|
+
- Function exported but never imported elsewhere
|
|
206
|
+
- Type defined but never used in signatures
|
|
207
|
+
- Switch case exists but condition never triggers
|
|
208
|
+
- **Hook returns value that's destructured but never used in JSX**
|
|
209
|
+
- **New data source created but old source still used in render**
|
|
210
|
+
- **Computed value stored in variable but render uses different variable**
|
|
211
|
+
- **Filter/transform function created but rendering bypasses it**
|
|
212
|
+
|
|
213
|
+
**Last-Mile Anti-Patterns** (these cause "works in code, broken in UI"):
|
|
214
|
+
- `displayTasks` computed but `getTasksForBoard` called in render
|
|
215
|
+
- Handler created but onClick still points to old handler
|
|
216
|
+
- New hook created but component still imports old hook
|
|
217
|
+
- State updated correctly but wrong variable passed to child component
|
|
218
|
+
|
|
219
|
+
- **Wait** β All validation agents complete
|
|
220
|
+
|
|
221
|
+
## Step (3/4) - Consolidate & Create Gap Remediation Tasks
|
|
222
|
+
|
|
223
|
+
- **Action** β ConsolidateFindings: Merge all subagent outputs.
|
|
224
|
+
|
|
225
|
+
- Aggregate status across all areas
|
|
226
|
+
- Compile gaps by priority (Critical/Medium/Low)
|
|
227
|
+
- Note any scope creep findings
|
|
228
|
+
|
|
229
|
+
- **Action** β FinalWiringChecklist: Before marking any area complete, verify:
|
|
230
|
+
|
|
231
|
+
| Check | Question |
|
|
232
|
+
|-------|----------|
|
|
233
|
+
| Consumer connected? | Does every new function/hook have a consumer that uses its output? |
|
|
234
|
+
| Render chain complete? | Can you trace from JSX β variable β hook β user action without breaks? |
|
|
235
|
+
| Old paths removed? | If replacing old code, is the old path dead or redirected? |
|
|
236
|
+
| No orphaned computation? | Is every computed value actually used in a render path? |
|
|
237
|
+
| No duplicate sources? | Is there only ONE data source for each concern (not old + new)? |
|
|
238
|
+
|
|
239
|
+
**CRITICAL**: If any check fails for an area marked β
, downgrade to β οΈ and add gap task.
|
|
240
|
+
|
|
241
|
+
- **Action** β DetermineOutputDir:
|
|
242
|
+
|
|
243
|
+
- `branch_name=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)`
|
|
244
|
+
- **If** user specifies path β `OUT_DIR={that value}`
|
|
245
|
+
- **Else** β `OUT_DIR=docs/tasks/{branch_name}`
|
|
246
|
+
- `mkdir -p "${OUT_DIR}/validation"`
|
|
247
|
+
|
|
248
|
+
- **Action** β CreateValidationGapsDoc: Generate `{OUT_DIR}/validation/validation_gaps.md`.
|
|
249
|
+
|
|
250
|
+
**Document Structure**:
|
|
251
|
+
|
|
252
|
+
```markdown
|
|
253
|
+
# Validation Gaps: {task_name}
|
|
254
|
+
*Generated: {timestamp}*
|
|
255
|
+
|
|
256
|
+
## Summary
|
|
257
|
+
- **Overall Status**: {Complete | Needs Work | Significant Gaps}
|
|
258
|
+
- **Requirements**: {X of Y} delivered
|
|
259
|
+
- **Gaps Found**: {count} requiring remediation
|
|
260
|
+
- **Scope Creep**: {count} items (document or remove)
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Gap Remediation Tasks
|
|
265
|
+
|
|
266
|
+
### π¦ Phase 1: Critical Gaps
|
|
267
|
+
|
|
268
|
+
#### π [1.1] {Gap Title - e.g., "Connect auth flow to login page"}
|
|
269
|
+
**Requirement**: {original requirement text}
|
|
270
|
+
**Current State**: {what exists now β definition site if code exists}
|
|
271
|
+
**Gap**: {what's missing β broken link in the chain}
|
|
272
|
+
|
|
273
|
+
- [ ] **1.1.1** {Specific action - e.g., "Wire LoginButton onClick to auth handler"}
|
|
274
|
+
- **Produces**: {output this creates β e.g., "onClick handler calling authService.login()"}
|
|
275
|
+
- **Consumed by**: {what uses this β e.g., "LoginButton component render"}
|
|
276
|
+
- **Replaces**: {old code path β e.g., "inline console.log in onClick" or "N/A"}
|
|
277
|
+
- [ ] {Verifiable outcome 1}
|
|
278
|
+
- [ ] {Verifiable outcome 2}
|
|
279
|
+
|
|
280
|
+
- [ ] **1.1.2** {Specific action - e.g., "Add login route to app router"}
|
|
281
|
+
- **Produces**: {output β e.g., "/login route rendering LoginPage"}
|
|
282
|
+
- **Consumed by**: {consumer β e.g., "App router, navigated via authService redirect"}
|
|
283
|
+
- [ ] {Verifiable outcome 1}
|
|
284
|
+
- [ ] {Verifiable outcome 2}
|
|
285
|
+
|
|
286
|
+
#### π [1.2] {Next Gap Title}
|
|
287
|
+
...
|
|
288
|
+
|
|
289
|
+
### π¦ Phase 2: Medium Priority Gaps
|
|
290
|
+
...
|
|
291
|
+
|
|
292
|
+
### π¦ Phase 3: Low Priority / Polish
|
|
293
|
+
...
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Scope Creep Review
|
|
298
|
+
Items implemented beyond original scope:
|
|
299
|
+
- [ ] **{Feature}**: {Keep and document | Remove | Discuss}
|
|
300
|
+
- Evidence: {file:line}
|
|
301
|
+
- Recommendation: {action}
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Validation Coverage
|
|
306
|
+
| Area | Status | Definition | Usage | Render Chain |
|
|
307
|
+
|------|--------|------------|-------|--------------|
|
|
308
|
+
| {area 1} | β
| {file:line} | {file:line} | JSX β var β source β |
|
|
309
|
+
| {area 2} | β οΈ | {file:line} | {file:line} | Broken at {link} |
|
|
310
|
+
| {area 3} | π | {file:line} | NONE | Dead computation |
|
|
311
|
+
| {area 4} | β | β | β | β |
|
|
312
|
+
|
|
313
|
+
## Dead Computations Found
|
|
314
|
+
| Variable | File | Computed By | Should Be Consumed By |
|
|
315
|
+
|----------|------|-------------|----------------------|
|
|
316
|
+
| {displayTasks} | {useKanbanFilters.ts} | {applyTaskFilters} | {KanbanBoard render} |
|
|
317
|
+
|
|
318
|
+
## Old Code Paths Still Active
|
|
319
|
+
| Old Path | Location | Should Be Replaced By | Impact |
|
|
320
|
+
|----------|----------|----------------------|--------|
|
|
321
|
+
| {getTasksForBoard} | {useKanbanDrag:45} | {displayTasks from useKanbanFilters} | Bypasses new filter |
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Step (4/4) - Present Results
|
|
326
|
+
|
|
327
|
+
- **Action** β PresentResults: Show validation summary.
|
|
328
|
+
|
|
329
|
+
> ## Validation Complete
|
|
330
|
+
**> **Status**: {Complete | Needs Work | Significant Gaps}
|
|
331
|
+
>
|
|
332
|
+
> - {X of Y} requirements delivered
|
|
333
|
+
> - {N} gaps requiring remediation
|
|
334
|
+
> - {N} scope creep items to review
|
|
335
|
+
**> **Gap Remediation Doc**: `{OUT_DIR}/validation/validation_gaps.md`
|
|
336
|
+
>
|
|
337
|
+
> {1-2 sentence summary of key findings}
|
|
338
|
+
|
|
339
|
+
- **Action** β RenderFooter: Render Next Steps footer using `@skill-spectre:spectre-guide` skill
|
|
340
|
+
|
|
341
|
+
## Next Steps
|
|
342
|
+
|
|
343
|
+
See `/skill-spectre:spectre` skill for footer format and command options.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PreCompact": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "*",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/precompact-warning.cjs"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"SessionStart": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "startup|clear|compact",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/bootstrap.cjs"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"type": "command",
|
|
24
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/handoff-resume.cjs"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"type": "command",
|
|
28
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/load-knowledge.cjs"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* bootstrap.cjs
|
|
6
|
+
*
|
|
7
|
+
* SessionStart hook that removes stale files from older plugin versions.
|
|
8
|
+
*
|
|
9
|
+
* When users update the plugin via marketplace, old files that were deleted
|
|
10
|
+
* from the repo may still linger in their cached copy. This script runs on
|
|
11
|
+
* every session start and cleans them up.
|
|
12
|
+
*
|
|
13
|
+
* To add new files to the cleanup list, append to STALE_PATHS below.
|
|
14
|
+
* Paths are relative to CLAUDE_PLUGIN_ROOT.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
const { readStdinWithTimeout } = require('./lib.cjs');
|
|
20
|
+
|
|
21
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
22
|
+
// Stale paths to remove (relative to CLAUDE_PLUGIN_ROOT)
|
|
23
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
24
|
+
|
|
25
|
+
const STALE_PATHS = [
|
|
26
|
+
// Python scripts replaced by .cjs equivalents (v3.x migration)
|
|
27
|
+
'hooks/scripts/capture-todos.py',
|
|
28
|
+
'hooks/scripts/handoff-resume.py',
|
|
29
|
+
'hooks/scripts/load-knowledge.py',
|
|
30
|
+
'hooks/scripts/precompact-warning.py',
|
|
31
|
+
'hooks/scripts/register_learning.py',
|
|
32
|
+
'hooks/scripts/test_handoff_resume.py',
|
|
33
|
+
'hooks/scripts/test_load_knowledge.py',
|
|
34
|
+
|
|
35
|
+
// Old skill directory replaced by spectre-guide
|
|
36
|
+
'skills/spectre-next-steps',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
40
|
+
// Cleanup logic
|
|
41
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
42
|
+
|
|
43
|
+
function cleanupStalePaths(pluginRoot) {
|
|
44
|
+
let removed = 0;
|
|
45
|
+
|
|
46
|
+
for (const relPath of STALE_PATHS) {
|
|
47
|
+
const fullPath = path.join(pluginRoot, relPath);
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const stat = fs.statSync(fullPath);
|
|
51
|
+
|
|
52
|
+
if (stat.isDirectory()) {
|
|
53
|
+
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
54
|
+
removed++;
|
|
55
|
+
} else {
|
|
56
|
+
fs.unlinkSync(fullPath);
|
|
57
|
+
removed++;
|
|
58
|
+
}
|
|
59
|
+
} catch (_) {
|
|
60
|
+
// File doesn't exist or can't be removed β skip silently
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return removed;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
68
|
+
// Main
|
|
69
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
70
|
+
|
|
71
|
+
async function main() {
|
|
72
|
+
// Drain stdin so the hook system doesn't hang
|
|
73
|
+
await readStdinWithTimeout();
|
|
74
|
+
|
|
75
|
+
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
|
|
76
|
+
if (!pluginRoot) {
|
|
77
|
+
process.stdout.write(JSON.stringify({}) + '\n');
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const removed = cleanupStalePaths(pluginRoot);
|
|
82
|
+
|
|
83
|
+
if (removed > 0) {
|
|
84
|
+
process.stdout.write(JSON.stringify({
|
|
85
|
+
systemMessage: `bootstrap: cleaned ${removed} stale file${removed > 1 ? 's' : ''} from previous plugin version`
|
|
86
|
+
}) + '\n');
|
|
87
|
+
} else {
|
|
88
|
+
process.stdout.write(JSON.stringify({}) + '\n');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Export for testing
|
|
95
|
+
if (typeof module !== 'undefined') {
|
|
96
|
+
module.exports = { cleanupStalePaths, STALE_PATHS };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
main();
|