sumulige-claude 1.3.1 → 1.3.3
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/.claude/MEMORY.md +9 -0
- package/.claude/handoffs/INDEX.md +21 -0
- package/.claude/handoffs/LATEST.md +76 -0
- package/.claude/handoffs/handoff_2026-01-22T13-07-04-757Z.md +76 -0
- package/.claude/hooks/auto-handoff.cjs +353 -0
- package/.claude/hooks/memory-loader.cjs +208 -0
- package/.claude/hooks/memory-saver.cjs +268 -0
- package/.claude/sessions/session_2026-01-22T13-07-26-625Z.json +23 -0
- package/.claude/settings.json +40 -0
- package/.claude/settings.local.json +5 -1
- package/.claude/skills/api-tester/SKILL.md +61 -0
- package/.claude/skills/api-tester/examples/basic.md +3 -0
- package/.claude/skills/api-tester/metadata.yaml +30 -0
- package/.claude/skills/api-tester/templates/default.md +3 -0
- package/.claude/skills/code-reviewer-123/SKILL.md +61 -0
- package/.claude/skills/code-reviewer-123/examples/basic.md +3 -0
- package/.claude/skills/code-reviewer-123/metadata.yaml +30 -0
- package/.claude/skills/code-reviewer-123/templates/default.md +3 -0
- package/.claude/skills/my-skill/SKILL.md +61 -0
- package/.claude/skills/my-skill/examples/basic.md +3 -0
- package/.claude/skills/my-skill/metadata.yaml +30 -0
- package/.claude/skills/my-skill/templates/default.md +3 -0
- package/.claude/skills/template/SKILL.md +6 -0
- package/.claude/skills/template/metadata.yaml +30 -0
- package/.claude/skills/test-skill-name/SKILL.md +61 -0
- package/.claude/skills/test-skill-name/examples/basic.md +3 -0
- package/.claude/skills/test-skill-name/metadata.yaml +30 -0
- package/.claude/skills/test-skill-name/templates/default.md +3 -0
- package/CHANGELOG.md +35 -0
- package/README.md +62 -0
- package/cli.js +1 -1
- package/development/todos/.state.json +3 -1
- package/lib/commands.js +83 -0
- package/package.json +1 -1
- package/template/.claude/hooks/auto-handoff.cjs +353 -0
- package/template/.claude/hooks/memory-loader.cjs +208 -0
- package/template/.claude/hooks/memory-saver.cjs +268 -0
- package/template/.claude/settings.json +40 -0
package/.claude/MEMORY.md
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Handoffs Index
|
|
2
|
+
|
|
3
|
+
> Auto-generated context preservation documents
|
|
4
|
+
> Updated: 2026-01-22T13:07:04.758Z
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Recent Handoffs (1)
|
|
9
|
+
|
|
10
|
+
- [handoff_2026-01-22T13-07-04-757Z.md](./handoff_2026-01-22T13-07-04-757Z.md) - 2026-01-22T13:07:04.758Z
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Latest Handoff
|
|
16
|
+
|
|
17
|
+
See [LATEST.md](./LATEST.md) for the most recent context snapshot.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
*Index maintained by auto-handoff.cjs*
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Handoff: Pre-Compact Context Preservation
|
|
2
|
+
|
|
3
|
+
> Auto-generated before context compression
|
|
4
|
+
> Date: 2026-01-22T13:07:04.742Z
|
|
5
|
+
> Session: unknown
|
|
6
|
+
> Conversation: unknown
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Session Info
|
|
11
|
+
|
|
12
|
+
- **Project**: sumulige-claude
|
|
13
|
+
- **Version**: 1.3.1
|
|
14
|
+
- **Start Time**: 2026-01-22T13:06:23.872Z
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Memory State
|
|
19
|
+
|
|
20
|
+
- **Entries Loaded**: 4
|
|
21
|
+
- **Anchors Modules**: 0
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Active TODOs (0)
|
|
26
|
+
|
|
27
|
+
*No active TODOs*
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Recently Modified Files (Last 24h)
|
|
33
|
+
|
|
34
|
+
- `.claude/.session-state.json` (2026-01-22)
|
|
35
|
+
- `.claude/settings.local.json` (2026-01-22)
|
|
36
|
+
- `.claude/settings.json` (2026-01-22)
|
|
37
|
+
- `.claude/hooks/auto-handoff.cjs` (2026-01-22)
|
|
38
|
+
- `.claude/hooks/memory-saver.cjs` (2026-01-22)
|
|
39
|
+
- `.claude/hooks/memory-loader.cjs` (2026-01-22)
|
|
40
|
+
- `.claude/.kickoff-hint.txt` (2026-01-22)
|
|
41
|
+
- `.claude/skills/xlsx/LICENSE.txt` (2026-01-22)
|
|
42
|
+
- `.claude/skills/web-artifacts-builder/LICENSE.txt` (2026-01-22)
|
|
43
|
+
- `.claude/skills/webapp-testing/LICENSE.txt` (2026-01-22)
|
|
44
|
+
- *...and 10 more files*
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Context Preservation Notes
|
|
50
|
+
|
|
51
|
+
**Important**: This handoff was auto-generated before context compaction.
|
|
52
|
+
The following information should be re-loaded after compaction:
|
|
53
|
+
|
|
54
|
+
1. Read `.claude/MEMORY.md` for recent session context
|
|
55
|
+
2. Check `development/todos/INDEX.md` for task status
|
|
56
|
+
3. Review recent git commits for code changes
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Recovery Commands
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# View recent memory
|
|
64
|
+
cat .claude/MEMORY.md | head -100
|
|
65
|
+
|
|
66
|
+
# Check active TODOs
|
|
67
|
+
ls development/todos/active/
|
|
68
|
+
|
|
69
|
+
# View recent changes
|
|
70
|
+
git log --oneline -10
|
|
71
|
+
git status
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
*Auto-generated by auto-handoff.cjs at 2026-01-22T13:07:04.742Z*
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Handoff: Pre-Compact Context Preservation
|
|
2
|
+
|
|
3
|
+
> Auto-generated before context compression
|
|
4
|
+
> Date: 2026-01-22T13:07:04.742Z
|
|
5
|
+
> Session: unknown
|
|
6
|
+
> Conversation: unknown
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Session Info
|
|
11
|
+
|
|
12
|
+
- **Project**: sumulige-claude
|
|
13
|
+
- **Version**: 1.3.1
|
|
14
|
+
- **Start Time**: 2026-01-22T13:06:23.872Z
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Memory State
|
|
19
|
+
|
|
20
|
+
- **Entries Loaded**: 4
|
|
21
|
+
- **Anchors Modules**: 0
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Active TODOs (0)
|
|
26
|
+
|
|
27
|
+
*No active TODOs*
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Recently Modified Files (Last 24h)
|
|
33
|
+
|
|
34
|
+
- `.claude/.session-state.json` (2026-01-22)
|
|
35
|
+
- `.claude/settings.local.json` (2026-01-22)
|
|
36
|
+
- `.claude/settings.json` (2026-01-22)
|
|
37
|
+
- `.claude/hooks/auto-handoff.cjs` (2026-01-22)
|
|
38
|
+
- `.claude/hooks/memory-saver.cjs` (2026-01-22)
|
|
39
|
+
- `.claude/hooks/memory-loader.cjs` (2026-01-22)
|
|
40
|
+
- `.claude/.kickoff-hint.txt` (2026-01-22)
|
|
41
|
+
- `.claude/skills/xlsx/LICENSE.txt` (2026-01-22)
|
|
42
|
+
- `.claude/skills/web-artifacts-builder/LICENSE.txt` (2026-01-22)
|
|
43
|
+
- `.claude/skills/webapp-testing/LICENSE.txt` (2026-01-22)
|
|
44
|
+
- *...and 10 more files*
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Context Preservation Notes
|
|
50
|
+
|
|
51
|
+
**Important**: This handoff was auto-generated before context compaction.
|
|
52
|
+
The following information should be re-loaded after compaction:
|
|
53
|
+
|
|
54
|
+
1. Read `.claude/MEMORY.md` for recent session context
|
|
55
|
+
2. Check `development/todos/INDEX.md` for task status
|
|
56
|
+
3. Review recent git commits for code changes
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Recovery Commands
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# View recent memory
|
|
64
|
+
cat .claude/MEMORY.md | head -100
|
|
65
|
+
|
|
66
|
+
# Check active TODOs
|
|
67
|
+
ls development/todos/active/
|
|
68
|
+
|
|
69
|
+
# View recent changes
|
|
70
|
+
git log --oneline -10
|
|
71
|
+
git status
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
*Auto-generated by auto-handoff.cjs at 2026-01-22T13:07:04.742Z*
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Auto Handoff Hook - PreCompact Context Preservation
|
|
4
|
+
*
|
|
5
|
+
* Claude Official Hook: PreCompact
|
|
6
|
+
* Triggered: Before conversation context is compressed
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Auto-generate handoff document before context compression
|
|
10
|
+
* - Preserve critical context that might be lost during compaction
|
|
11
|
+
* - Save current state including progress, blockers, and next steps
|
|
12
|
+
*
|
|
13
|
+
* Environment Variables:
|
|
14
|
+
* - CLAUDE_PROJECT_DIR: Project directory path
|
|
15
|
+
* - CLAUDE_SESSION_ID: Unique session identifier
|
|
16
|
+
* - CLAUDE_CONVERSATION_ID: Conversation identifier
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
23
|
+
const CLAUDE_DIR = path.join(PROJECT_DIR, '.claude');
|
|
24
|
+
const HANDOFFS_DIR = path.join(CLAUDE_DIR, 'handoffs');
|
|
25
|
+
const SESSION_STATE_FILE = path.join(CLAUDE_DIR, '.session-state.json');
|
|
26
|
+
const STATE_FILE = path.join(PROJECT_DIR, 'development', 'todos', '.state.json');
|
|
27
|
+
const SESSION_ID = process.env.CLAUDE_SESSION_ID || 'unknown';
|
|
28
|
+
const CONVERSATION_ID = process.env.CLAUDE_CONVERSATION_ID || 'unknown';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Ensure handoffs directory exists
|
|
32
|
+
*/
|
|
33
|
+
function ensureHandoffsDir() {
|
|
34
|
+
if (!fs.existsSync(HANDOFFS_DIR)) {
|
|
35
|
+
fs.mkdirSync(HANDOFFS_DIR, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Load current session state
|
|
41
|
+
*/
|
|
42
|
+
function loadSessionState() {
|
|
43
|
+
if (!fs.existsSync(SESSION_STATE_FILE)) {
|
|
44
|
+
return {
|
|
45
|
+
session: { project: path.basename(PROJECT_DIR) },
|
|
46
|
+
memory: { entries: 0 },
|
|
47
|
+
todos: { active: 0, completed: 0 }
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
return JSON.parse(fs.readFileSync(SESSION_STATE_FILE, 'utf-8'));
|
|
53
|
+
} catch (e) {
|
|
54
|
+
return {
|
|
55
|
+
session: { project: path.basename(PROJECT_DIR) },
|
|
56
|
+
memory: { entries: 0 },
|
|
57
|
+
todos: { active: 0, completed: 0 }
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Load active TODOs
|
|
64
|
+
*/
|
|
65
|
+
function loadActiveTodos() {
|
|
66
|
+
const todosDir = path.join(PROJECT_DIR, 'development', 'todos', 'active');
|
|
67
|
+
if (!fs.existsSync(todosDir)) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const files = fs.readdirSync(todosDir)
|
|
73
|
+
.filter(f => f.endsWith('.md') && f !== '_README.md');
|
|
74
|
+
|
|
75
|
+
return files.map(f => {
|
|
76
|
+
const content = fs.readFileSync(path.join(todosDir, f), 'utf-8');
|
|
77
|
+
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
78
|
+
return {
|
|
79
|
+
file: f,
|
|
80
|
+
title: titleMatch ? titleMatch[1] : path.basename(f, '.md')
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
} catch (e) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get recently modified files
|
|
90
|
+
*/
|
|
91
|
+
function getRecentlyModifiedFiles(hours = 24) {
|
|
92
|
+
const recentFiles = [];
|
|
93
|
+
const cutoff = Date.now() - (hours * 60 * 60 * 1000);
|
|
94
|
+
|
|
95
|
+
// Check common source directories
|
|
96
|
+
const sourceDirs = ['src', 'lib', '.claude', 'development'];
|
|
97
|
+
|
|
98
|
+
for (const dir of sourceDirs) {
|
|
99
|
+
const fullPath = path.join(PROJECT_DIR, dir);
|
|
100
|
+
if (!fs.existsSync(fullPath)) continue;
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const walkDir = (dirPath, depth = 0) => {
|
|
104
|
+
if (depth > 3) return; // Limit depth
|
|
105
|
+
|
|
106
|
+
const items = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
107
|
+
for (const item of items) {
|
|
108
|
+
const itemPath = path.join(dirPath, item.name);
|
|
109
|
+
|
|
110
|
+
if (item.isDirectory() && !item.name.startsWith('.') && item.name !== 'node_modules') {
|
|
111
|
+
walkDir(itemPath, depth + 1);
|
|
112
|
+
} else if (item.isFile()) {
|
|
113
|
+
try {
|
|
114
|
+
const stat = fs.statSync(itemPath);
|
|
115
|
+
if (stat.mtimeMs > cutoff) {
|
|
116
|
+
const relativePath = path.relative(PROJECT_DIR, itemPath);
|
|
117
|
+
recentFiles.push({
|
|
118
|
+
path: relativePath,
|
|
119
|
+
modified: stat.mtime.toISOString()
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
} catch (e) {
|
|
123
|
+
// Ignore stat errors
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
walkDir(fullPath);
|
|
130
|
+
} catch (e) {
|
|
131
|
+
// Ignore directory errors
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Sort by modification time (most recent first)
|
|
136
|
+
recentFiles.sort((a, b) => b.modified.localeCompare(a.modified));
|
|
137
|
+
|
|
138
|
+
return recentFiles.slice(0, 20); // Return top 20
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Generate handoff document
|
|
143
|
+
*/
|
|
144
|
+
function generateHandoff(sessionState) {
|
|
145
|
+
const now = new Date();
|
|
146
|
+
const todos = loadActiveTodos();
|
|
147
|
+
const recentFiles = getRecentlyModifiedFiles();
|
|
148
|
+
|
|
149
|
+
let content = `# Handoff: Pre-Compact Context Preservation
|
|
150
|
+
|
|
151
|
+
> Auto-generated before context compression
|
|
152
|
+
> Date: ${now.toISOString()}
|
|
153
|
+
> Session: ${SESSION_ID}
|
|
154
|
+
> Conversation: ${CONVERSATION_ID}
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Session Info
|
|
159
|
+
|
|
160
|
+
- **Project**: ${sessionState.session?.project || 'unknown'}
|
|
161
|
+
- **Version**: ${sessionState.session?.version || 'unknown'}
|
|
162
|
+
- **Start Time**: ${sessionState.session?.startTime || 'unknown'}
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Memory State
|
|
167
|
+
|
|
168
|
+
- **Entries Loaded**: ${sessionState.memory?.entries || 0}
|
|
169
|
+
- **Anchors Modules**: ${sessionState.anchors?.modules || 0}
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Active TODOs (${todos.length})
|
|
174
|
+
|
|
175
|
+
`;
|
|
176
|
+
|
|
177
|
+
if (todos.length > 0) {
|
|
178
|
+
todos.forEach(todo => {
|
|
179
|
+
content += `- [ ] ${todo.title} (\`${todo.file}\`)\n`;
|
|
180
|
+
});
|
|
181
|
+
} else {
|
|
182
|
+
content += `*No active TODOs*\n`;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
content += `
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Recently Modified Files (Last 24h)
|
|
190
|
+
|
|
191
|
+
`;
|
|
192
|
+
|
|
193
|
+
if (recentFiles.length > 0) {
|
|
194
|
+
recentFiles.slice(0, 10).forEach(f => {
|
|
195
|
+
content += `- \`${f.path}\` (${f.modified.split('T')[0]})\n`;
|
|
196
|
+
});
|
|
197
|
+
if (recentFiles.length > 10) {
|
|
198
|
+
content += `- *...and ${recentFiles.length - 10} more files*\n`;
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
content += `*No recently modified files*\n`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
content += `
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Context Preservation Notes
|
|
209
|
+
|
|
210
|
+
**Important**: This handoff was auto-generated before context compaction.
|
|
211
|
+
The following information should be re-loaded after compaction:
|
|
212
|
+
|
|
213
|
+
1. Read \`.claude/MEMORY.md\` for recent session context
|
|
214
|
+
2. Check \`development/todos/INDEX.md\` for task status
|
|
215
|
+
3. Review recent git commits for code changes
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Recovery Commands
|
|
220
|
+
|
|
221
|
+
\`\`\`bash
|
|
222
|
+
# View recent memory
|
|
223
|
+
cat .claude/MEMORY.md | head -100
|
|
224
|
+
|
|
225
|
+
# Check active TODOs
|
|
226
|
+
ls development/todos/active/
|
|
227
|
+
|
|
228
|
+
# View recent changes
|
|
229
|
+
git log --oneline -10
|
|
230
|
+
git status
|
|
231
|
+
\`\`\`
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
*Auto-generated by auto-handoff.cjs at ${now.toISOString()}*
|
|
236
|
+
`;
|
|
237
|
+
|
|
238
|
+
return content;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Save handoff document
|
|
243
|
+
*/
|
|
244
|
+
function saveHandoff(content) {
|
|
245
|
+
ensureHandoffsDir();
|
|
246
|
+
|
|
247
|
+
const now = new Date();
|
|
248
|
+
const filename = `handoff_${now.toISOString().replace(/[:.]/g, '-')}.md`;
|
|
249
|
+
const filepath = path.join(HANDOFFS_DIR, filename);
|
|
250
|
+
|
|
251
|
+
fs.writeFileSync(filepath, content);
|
|
252
|
+
|
|
253
|
+
// Also save as latest handoff for easy access
|
|
254
|
+
const latestPath = path.join(HANDOFFS_DIR, 'LATEST.md');
|
|
255
|
+
fs.writeFileSync(latestPath, content);
|
|
256
|
+
|
|
257
|
+
// Clean up old handoffs (keep last 10)
|
|
258
|
+
const files = fs.readdirSync(HANDOFFS_DIR)
|
|
259
|
+
.filter(f => f.startsWith('handoff_') && f.endsWith('.md'))
|
|
260
|
+
.sort()
|
|
261
|
+
.reverse();
|
|
262
|
+
|
|
263
|
+
if (files.length > 10) {
|
|
264
|
+
files.slice(10).forEach(f => {
|
|
265
|
+
try {
|
|
266
|
+
fs.unlinkSync(path.join(HANDOFFS_DIR, f));
|
|
267
|
+
} catch (e) {
|
|
268
|
+
// Ignore deletion errors
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return filename;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Update handoffs index
|
|
278
|
+
*/
|
|
279
|
+
function updateHandoffsIndex() {
|
|
280
|
+
const indexPath = path.join(HANDOFFS_DIR, 'INDEX.md');
|
|
281
|
+
|
|
282
|
+
const files = fs.readdirSync(HANDOFFS_DIR)
|
|
283
|
+
.filter(f => f.startsWith('handoff_') && f.endsWith('.md'))
|
|
284
|
+
.sort()
|
|
285
|
+
.reverse();
|
|
286
|
+
|
|
287
|
+
let content = `# Handoffs Index
|
|
288
|
+
|
|
289
|
+
> Auto-generated context preservation documents
|
|
290
|
+
> Updated: ${new Date().toISOString()}
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Recent Handoffs (${files.length})
|
|
295
|
+
|
|
296
|
+
`;
|
|
297
|
+
|
|
298
|
+
files.slice(0, 20).forEach(f => {
|
|
299
|
+
const filepath = path.join(HANDOFFS_DIR, f);
|
|
300
|
+
const stat = fs.statSync(filepath);
|
|
301
|
+
content += `- [${f}](./${f}) - ${stat.mtime.toISOString()}\n`;
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
content += `
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Latest Handoff
|
|
309
|
+
|
|
310
|
+
See [LATEST.md](./LATEST.md) for the most recent context snapshot.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
*Index maintained by auto-handoff.cjs*
|
|
315
|
+
`;
|
|
316
|
+
|
|
317
|
+
fs.writeFileSync(indexPath, content);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Main execution
|
|
322
|
+
*/
|
|
323
|
+
function main() {
|
|
324
|
+
try {
|
|
325
|
+
const sessionState = loadSessionState();
|
|
326
|
+
const content = generateHandoff(sessionState);
|
|
327
|
+
const filename = saveHandoff(content);
|
|
328
|
+
updateHandoffsIndex();
|
|
329
|
+
|
|
330
|
+
console.log(`\n⚡ PreCompact: Context preserved → ${filename}`);
|
|
331
|
+
console.log(` Recovery: .claude/handoffs/LATEST.md\n`);
|
|
332
|
+
|
|
333
|
+
process.exit(0);
|
|
334
|
+
} catch (e) {
|
|
335
|
+
// Silent failure - don't interrupt compaction
|
|
336
|
+
console.error(`PreCompact handoff error: ${e.message}`);
|
|
337
|
+
process.exit(0);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Run
|
|
342
|
+
if (require.main === module) {
|
|
343
|
+
main();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
module.exports = {
|
|
347
|
+
loadSessionState,
|
|
348
|
+
loadActiveTodos,
|
|
349
|
+
getRecentlyModifiedFiles,
|
|
350
|
+
generateHandoff,
|
|
351
|
+
saveHandoff,
|
|
352
|
+
updateHandoffsIndex
|
|
353
|
+
};
|