metame-cli 1.5.9 → 1.5.11
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 +49 -6
- package/index.js +218 -64
- package/package.json +6 -3
- package/scripts/daemon-admin-commands.js +34 -0
- package/scripts/daemon-bridges.js +18 -1
- package/scripts/daemon-claude-engine.js +41 -1
- package/scripts/daemon-default.yaml +3 -1
- package/scripts/daemon-ops-commands.js +25 -11
- package/scripts/daemon-reactive-lifecycle.js +355 -70
- package/scripts/daemon-utils.js +55 -0
- package/scripts/daemon.js +79 -2
- package/scripts/distill.js +1 -1
- package/scripts/docs/maintenance-manual.md +55 -2
- package/scripts/docs/orphan-files-review.md +72 -0
- package/scripts/docs/pointer-map.md +34 -0
- package/scripts/feishu-adapter.js +25 -0
- package/scripts/hooks/intent-auto-rules.js +50 -0
- package/scripts/memory-extract.js +29 -1
- package/scripts/memory-nightly-reflect.js +104 -0
- package/scripts/signal-capture.js +3 -3
- package/scripts/skill-evolution.js +11 -2
- package/scripts/daemon.yaml +0 -444
|
@@ -8,6 +8,7 @@ function createOpsCommandHandler(deps) {
|
|
|
8
8
|
path,
|
|
9
9
|
spawn,
|
|
10
10
|
execSync,
|
|
11
|
+
execFileSync,
|
|
11
12
|
log,
|
|
12
13
|
loadConfig,
|
|
13
14
|
loadState,
|
|
@@ -86,19 +87,30 @@ function createOpsCommandHandler(deps) {
|
|
|
86
87
|
}
|
|
87
88
|
try {
|
|
88
89
|
let diffFiles = '';
|
|
90
|
+
let diffFailed = false;
|
|
89
91
|
const _wh = process.platform === 'win32' ? { windowsHide: true } : {};
|
|
90
|
-
try { diffFiles = execSync(`git diff --name-only HEAD ${match.hash}`, { cwd, encoding: 'utf8', timeout: 5000, ..._wh }).trim(); } catch { }
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
|
|
92
|
+
try { diffFiles = execSync(`git diff --name-only HEAD ${match.hash}`, { cwd, encoding: 'utf8', timeout: 5000, ..._wh }).trim(); } catch { diffFailed = true; }
|
|
93
|
+
const changedFiles = diffFiles ? diffFiles.split('\n').filter(Boolean) : [];
|
|
94
|
+
if (changedFiles.length > 0 || diffFailed) {
|
|
95
|
+
// Save current state before rollback (safety net)
|
|
96
|
+
gitCheckpoint(cwd, '[metame-safety] before rollback');
|
|
97
|
+
// Reset HEAD to checkpoint's parent (removes any commits Claude made)
|
|
98
|
+
if (match.parentHash) {
|
|
99
|
+
execSync(`git reset --hard ${match.parentHash}`, { cwd, stdio: 'ignore', timeout: 10000, ..._wh });
|
|
100
|
+
}
|
|
101
|
+
// Restore only changed files (not entire worktree) to preserve user's manual edits
|
|
102
|
+
if (changedFiles.length > 0) {
|
|
103
|
+
execFileSync('git', ['checkout', match.hash, '--', ...changedFiles], { cwd, stdio: 'ignore', timeout: 10000 });
|
|
104
|
+
} else {
|
|
105
|
+
// diff failed but we still reset — fallback to full restore
|
|
106
|
+
execFileSync('git', ['checkout', match.hash, '--', '.'], { cwd, stdio: 'ignore', timeout: 10000 });
|
|
107
|
+
}
|
|
94
108
|
}
|
|
95
|
-
// Restore working tree to exact checkpoint state (recovers pre-Claude uncommitted changes)
|
|
96
|
-
execSync(`git checkout ${match.hash} -- .`, { cwd, stdio: 'ignore', timeout: 10000, ..._wh });
|
|
97
109
|
// Truncate context to checkpoint time (covers multi-turn rollback)
|
|
98
110
|
truncateSessionToCheckpoint(session.id, match.message);
|
|
99
|
-
const
|
|
100
|
-
const fileCount = diffFiles ? diffFiles.split('\n').length : 0;
|
|
111
|
+
const fileCount = changedFiles.length;
|
|
101
112
|
let msg = `⏪ 已回退到 ${cpDisplayLabel(match.message)}`;
|
|
113
|
+
const fileList = changedFiles.map(f => path.basename(f)).join(', ');
|
|
102
114
|
if (fileCount > 0) msg += `\n📁 ${fileCount} 个文件恢复: ${fileList}`;
|
|
103
115
|
log('INFO', `/undo <hash> executed for ${chatId}: reset to ${match.hash.slice(0, 8)}, files=${fileCount}`);
|
|
104
116
|
await bot.sendMessage(chatId, msg);
|
|
@@ -232,14 +244,16 @@ function createOpsCommandHandler(deps) {
|
|
|
232
244
|
let diffFiles2 = '';
|
|
233
245
|
const _wh2 = process.platform === 'win32' ? { windowsHide: true } : {};
|
|
234
246
|
try { diffFiles2 = execSync(`git diff --name-only HEAD ${cpMatch.hash}`, { cwd: cwd2, encoding: 'utf8', timeout: 5000, ..._wh2 }).trim(); } catch { }
|
|
235
|
-
|
|
247
|
+
const changedFiles2 = diffFiles2 ? diffFiles2.split('\n').filter(Boolean) : [];
|
|
248
|
+
if (changedFiles2.length > 0) {
|
|
236
249
|
// Save current state before rollback (excluded from normal /undo list)
|
|
237
250
|
gitCheckpoint(cwd2, '[metame-safety] before rollback');
|
|
238
251
|
if (cpMatch.parentHash) {
|
|
239
252
|
execSync(`git reset --hard ${cpMatch.parentHash}`, { cwd: cwd2, stdio: 'ignore', timeout: 10000, ..._wh2 });
|
|
240
253
|
}
|
|
241
|
-
|
|
242
|
-
|
|
254
|
+
// Restore only changed files (not entire worktree) to preserve user's manual edits
|
|
255
|
+
execFileSync('git', ['checkout', cpMatch.hash, '--', ...changedFiles2], { cwd: cwd2, stdio: 'ignore', timeout: 10000 });
|
|
256
|
+
gitMsg2 = `\n📁 ${changedFiles2.length} 个文件已恢复`;
|
|
243
257
|
cleanupCheckpoints(cwd2);
|
|
244
258
|
}
|
|
245
259
|
}
|