dev-memory-cli 0.22.1 → 0.23.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 +255 -291
- package/bin/dev-memory.js +125 -2
- package/hooks/README.md +181 -47
- package/hooks/codex-hooks.json +1 -1
- package/hooks/hooks.json +1 -1
- package/lib/dev_memory_capture.py +152 -11
- package/lib/dev_memory_common.py +68 -19
- package/lib/dev_memory_graduate.py +1 -1
- package/lib/dev_memory_session_scan.py +1565 -0
- package/lib/dev_memory_setup.py +8 -3
- package/lib/dev_memory_summary.py +25 -16
- package/lib/maintenance/archive.md +84 -0
- package/lib/maintenance/tidy.md +103 -0
- package/lib/ui-app.html +128 -1
- package/lib/ui-server.js +67 -1
- package/package.json +2 -1
- package/scripts/hooks/_common.py +48 -12
- package/scripts/hooks/stop.py +6 -0
- package/suite-manifest.json +4 -4
package/bin/dev-memory.js
CHANGED
|
@@ -56,7 +56,11 @@ function runPython(scriptPath, args, cwd = process.cwd(), extraEnv = {}) {
|
|
|
56
56
|
// inject DEFAULT_STORAGE_ROOT here — that would short-circuit Python's
|
|
57
57
|
// fallback chain (which prefers legacy ~/.dev-assets if it has data and
|
|
58
58
|
// ~/.dev-memory does not).
|
|
59
|
-
const env = {
|
|
59
|
+
const env = {
|
|
60
|
+
...process.env,
|
|
61
|
+
DEV_MEMORY_CLI_PATH: process.env.DEV_MEMORY_CLI_PATH || path.resolve(process.argv[1]),
|
|
62
|
+
...extraEnv,
|
|
63
|
+
};
|
|
60
64
|
const result = spawnSync(python, [scriptPath, ...args], {
|
|
61
65
|
cwd,
|
|
62
66
|
env,
|
|
@@ -136,7 +140,7 @@ function detectSessionSummaryCommand() {
|
|
|
136
140
|
if (commandExists("codex")) {
|
|
137
141
|
return {
|
|
138
142
|
provider: "codex",
|
|
139
|
-
command: "codex exec --ignore-user-config --ignore-rules --skip-git-repo-check --sandbox danger-full-access {prompt}",
|
|
143
|
+
command: "codex exec --ephemeral --ignore-user-config --ignore-rules --skip-git-repo-check --sandbox danger-full-access {prompt}",
|
|
140
144
|
};
|
|
141
145
|
}
|
|
142
146
|
if (commandExists("claude")) {
|
|
@@ -361,6 +365,7 @@ const PY_SUBCOMMAND_SCRIPTS = {
|
|
|
361
365
|
graduate: "dev_memory_graduate.py",
|
|
362
366
|
tidy: "dev_memory_tidy.py",
|
|
363
367
|
summary: "dev_memory_summary.py",
|
|
368
|
+
"session-scan": "dev_memory_session_scan.py",
|
|
364
369
|
};
|
|
365
370
|
|
|
366
371
|
function commandPySubcommand(name, rawArgs) {
|
|
@@ -371,6 +376,112 @@ function commandPySubcommand(name, rawArgs) {
|
|
|
371
376
|
runPython(scriptPath, rawArgs);
|
|
372
377
|
}
|
|
373
378
|
|
|
379
|
+
const MAINTENANCE_MODES = new Set(["tidy", "archive"]);
|
|
380
|
+
const MAINTENANCE_MARKER = "DEV_MEMORY_INTERNAL_MAINTENANCE_AGENT_V1";
|
|
381
|
+
|
|
382
|
+
function maintenanceHelp() {
|
|
383
|
+
process.stdout.write(`Usage:
|
|
384
|
+
dev-memory-cli maintain tidy [--repo PATH] [--branch NAME] [--scope branch|branch+repo]
|
|
385
|
+
[--executor auto|codex|coco] [--model MODEL]
|
|
386
|
+
dev-memory-cli maintain archive [--repo PATH] [--branch NAME]
|
|
387
|
+
[--executor auto|codex|coco] [--model MODEL]
|
|
388
|
+
dev-memory-cli maintain <tidy|archive> --print-prompt [other options]
|
|
389
|
+
|
|
390
|
+
The command starts a dedicated interactive maintenance-agent session. Tidy
|
|
391
|
+
must not apply destructive changes before HTML review; archive must not apply
|
|
392
|
+
before dry-run review and explicit confirmation.
|
|
393
|
+
`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function resolveMaintenanceExecutor(requested) {
|
|
397
|
+
const name = requested || process.env.DEV_MEMORY_MAINTENANCE_EXECUTOR || "auto";
|
|
398
|
+
if (!new Set(["auto", "codex", "coco"]).has(name)) {
|
|
399
|
+
fail(`unsupported maintenance executor: ${name}`);
|
|
400
|
+
}
|
|
401
|
+
if (name !== "auto") return name;
|
|
402
|
+
for (const candidate of ["codex", "coco"]) {
|
|
403
|
+
if (commandExists(candidate)) return candidate;
|
|
404
|
+
}
|
|
405
|
+
fail("no maintenance executor found; install codex/coco or use --print-prompt");
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function buildMaintenancePrompt(mode, options, repoRoot) {
|
|
409
|
+
const promptPath = packageScript("lib", "maintenance", `${mode}.md`);
|
|
410
|
+
if (!fs.existsSync(promptPath)) fail(`missing maintenance prompt: ${promptPath}`);
|
|
411
|
+
const workflow = fs.readFileSync(promptPath, "utf8").trim();
|
|
412
|
+
const cliPath = path.resolve(process.argv[1]);
|
|
413
|
+
const branch = options.branch || "<current-git-branch>";
|
|
414
|
+
const scope = mode === "tidy" ? (options.scope || "branch") : "branch";
|
|
415
|
+
return `${MAINTENANCE_MARKER}
|
|
416
|
+
|
|
417
|
+
你是 dev-memory 的专用维护 Agent。本会话只处理下面指定仓库的记忆维护,不承担普通开发任务。
|
|
418
|
+
|
|
419
|
+
目标仓库:${repoRoot}
|
|
420
|
+
目标分支:${branch}
|
|
421
|
+
维护模式:${mode}
|
|
422
|
+
整理范围:${scope}
|
|
423
|
+
本次必须使用的 CLI:node ${JSON.stringify(cliPath)}
|
|
424
|
+
|
|
425
|
+
不要依赖全局 dev-memory capture/setup/tidy/graduate Skill;完整维护流程已经随本提示提供。
|
|
426
|
+
涉及删除、改写或归档时,必须遵守下面流程中的人工审核和确认门禁。
|
|
427
|
+
|
|
428
|
+
${workflow}
|
|
429
|
+
`;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function commandMaintain(rawArgs) {
|
|
433
|
+
const mode = rawArgs[0];
|
|
434
|
+
if (!mode || mode === "--help" || mode === "-h") {
|
|
435
|
+
maintenanceHelp();
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (!MAINTENANCE_MODES.has(mode)) {
|
|
439
|
+
fail(`unknown maintenance mode: ${mode}`);
|
|
440
|
+
}
|
|
441
|
+
const { positional, options } = parseArgs(rawArgs.slice(1));
|
|
442
|
+
if (positional.length) fail(`unexpected maintenance argument: ${positional[0]}`);
|
|
443
|
+
const repoRoot = path.resolve(options.repo || process.cwd());
|
|
444
|
+
if (!fs.existsSync(repoRoot) || !fs.statSync(repoRoot).isDirectory()) {
|
|
445
|
+
fail(`maintenance repo does not exist: ${repoRoot}`);
|
|
446
|
+
}
|
|
447
|
+
if (mode === "tidy" && options.scope && !new Set(["branch", "branch+repo"]).has(options.scope)) {
|
|
448
|
+
fail(`unsupported tidy scope: ${options.scope}`);
|
|
449
|
+
}
|
|
450
|
+
const prompt = buildMaintenancePrompt(mode, options, repoRoot);
|
|
451
|
+
if (options["print-prompt"] || options["dry-run"]) {
|
|
452
|
+
process.stdout.write(prompt);
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const executor = resolveMaintenanceExecutor(options.executor);
|
|
457
|
+
let args;
|
|
458
|
+
if (executor === "codex") {
|
|
459
|
+
const modelArgs = options.model ? ["--model", String(options.model)] : [];
|
|
460
|
+
args = [
|
|
461
|
+
"-C", repoRoot,
|
|
462
|
+
"--sandbox", "danger-full-access",
|
|
463
|
+
"--ask-for-approval", "on-request",
|
|
464
|
+
"--dangerously-bypass-hook-trust",
|
|
465
|
+
...modelArgs,
|
|
466
|
+
prompt,
|
|
467
|
+
];
|
|
468
|
+
} else {
|
|
469
|
+
const modelArgs = options.model ? ["--config", `model=${String(options.model)}`] : [];
|
|
470
|
+
args = ["--permission-mode", "default", ...modelArgs, prompt];
|
|
471
|
+
}
|
|
472
|
+
const result = spawnSync(executor, args, {
|
|
473
|
+
cwd: repoRoot,
|
|
474
|
+
env: {
|
|
475
|
+
...process.env,
|
|
476
|
+
DEV_MEMORY_MAINTENANCE_AGENT: "1",
|
|
477
|
+
DEV_MEMORY_MAINTENANCE_MODE: mode,
|
|
478
|
+
},
|
|
479
|
+
stdio: "inherit",
|
|
480
|
+
});
|
|
481
|
+
if (result.error) fail(`unable to start ${executor}: ${result.error.message}`);
|
|
482
|
+
if (result.status !== 0) process.exit(result.status || 1);
|
|
483
|
+
}
|
|
484
|
+
|
|
374
485
|
function branchScript() {
|
|
375
486
|
return packageScript("lib", "dev_memory_branch.py");
|
|
376
487
|
}
|
|
@@ -687,13 +798,17 @@ function printHelp() {
|
|
|
687
798
|
dev-memory-cli install-hooks --all [--repo PATH] [--global]
|
|
688
799
|
dev-memory-cli ui [--port N] [--host HOST] [--no-open] [--read-only]
|
|
689
800
|
dev-memory-cli workspace <show|primary> [...]
|
|
801
|
+
dev-memory-cli init [--repo PATH] [--branch NAME]
|
|
690
802
|
dev-memory-cli read <show|search> [...]
|
|
803
|
+
dev-memory-cli maintain <tidy|archive> [...] # starts a dedicated interactive agent
|
|
691
804
|
dev-memory-cli context <show|...> [...]
|
|
805
|
+
# Low-level mutation/admin commands used by session-scan and maintenance agents:
|
|
692
806
|
dev-memory-cli capture <record|show|sync-working-tree|record-head|suggest-kind|classify> [...]
|
|
693
807
|
dev-memory-cli setup <init|merge-unsorted|mark-completed> [...]
|
|
694
808
|
dev-memory-cli graduate <dry-run|apply|index> [...]
|
|
695
809
|
dev-memory-cli tidy <prepare|apply> [...]
|
|
696
810
|
dev-memory-cli summary <extract-core> [...]
|
|
811
|
+
dev-memory-cli session-scan <run|install|status|stats|history|show|uninstall|config> [...]
|
|
697
812
|
dev-memory-cli branch [list|inspect|rename|fork|delete|init|inherit-worktree-base] [...] # no subcommand = interactive
|
|
698
813
|
|
|
699
814
|
Environment:
|
|
@@ -713,6 +828,14 @@ function main() {
|
|
|
713
828
|
commandPySubcommand(command, argv.slice(1));
|
|
714
829
|
return;
|
|
715
830
|
}
|
|
831
|
+
if (command === "init") {
|
|
832
|
+
commandPySubcommand("setup", ["init", ...argv.slice(1)]);
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
if (command === "maintain") {
|
|
836
|
+
commandMaintain(argv.slice(1));
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
716
839
|
if (command === "branch") {
|
|
717
840
|
commandBranch(argv.slice(1));
|
|
718
841
|
return;
|
package/hooks/README.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# Lifecycle Hooks
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
现在采用的是接近 ECC 的生命周期 hooks,并同时支持 Claude 和 Codex 两种 agent。
|
|
3
|
+
本项目使用 agent 生命周期 hook,不使用 Git hook。Claude Code 与 Codex 的可用事件不同,模板分别维护。
|
|
6
4
|
|
|
7
5
|
## 当前仓库里的接入方式
|
|
8
6
|
|
|
9
|
-
-
|
|
7
|
+
- repo-local 配置位置:
|
|
10
8
|
- Claude: `.claude/settings.local.json`
|
|
11
9
|
- Codex: `.codex/hooks.json`
|
|
12
10
|
- 可复用模板:
|
|
13
11
|
- Claude: [hooks/hooks.json](hooks.json)
|
|
14
12
|
- Codex: [hooks/codex-hooks.json](codex-hooks.json)
|
|
15
13
|
- `dev-memory-cli` 是这两套配置共用的稳定执行入口
|
|
16
|
-
-
|
|
14
|
+
- hook 仅在模板内容合并到对应 agent 配置后生效
|
|
17
15
|
|
|
18
16
|
### Codex 快速安装
|
|
19
17
|
|
|
@@ -40,48 +38,184 @@ dev-memory-cli install-hooks claude
|
|
|
40
38
|
|
|
41
39
|
已有旧配置如果还写着 `dev-memory hook ...` 或 `npx dev-memory hook ...`,重新执行安装命令会按 hook id 覆盖为 `dev-memory-cli hook ...`。
|
|
42
40
|
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- `
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
41
|
+
## Hook 行为
|
|
42
|
+
|
|
43
|
+
| 事件 | Codex CLI | Claude Code CLI | 行为 |
|
|
44
|
+
| --- | :-: | :-: | --- |
|
|
45
|
+
| `SessionStart` | ✓ | ✓ | 读取当前 repo+branch 记忆并注入会话;同一 session 的重复触发幂等跳过 |
|
|
46
|
+
| `Stop` | ✓ | ✓ | 每次回复后记录轻量 HEAD marker;Codex 同时登记定时扫描候选 |
|
|
47
|
+
| `PreCompact` | | ✓ | 兼容占位;当前不执行额外刷新 |
|
|
48
|
+
| `SessionEnd` | | ✓ | 记录最终 HEAD,创建 transcript 总结任务并启动后台 worker |
|
|
49
|
+
|
|
50
|
+
`SessionStart` 的幂等记录位于 `<repo-memory>/jobs/session-start/injected/*.json`。重复触发只记录 skip 日志,不重复注入上下文。
|
|
51
|
+
|
|
52
|
+
## 会话总结
|
|
53
|
+
|
|
54
|
+
### 生效范围
|
|
55
|
+
|
|
56
|
+
`SessionEnd` 自动总结仅由 **Claude Code CLI** 的生命周期事件触发。Codex CLI hook 模板没有 `SessionEnd`;它的 `Stop` 只登记候选,不在每轮回答后启动模型。Codex Desktop 不使用这组项目 hook。
|
|
57
|
+
|
|
58
|
+
总结任务的触发端与执行端是两个独立概念:
|
|
59
|
+
|
|
60
|
+
- **触发端**:Claude Code CLI 的 `SessionEnd` hook。
|
|
61
|
+
- **执行端**:本机可用的 `coco`、`codex` 或 `claude` CLI。
|
|
62
|
+
|
|
63
|
+
因此,执行总结所用的 CLI 与产生原会话的客户端没有绑定关系。
|
|
64
|
+
|
|
65
|
+
### 总结工具选择
|
|
66
|
+
|
|
67
|
+
`install-hooks` 检测本地命令并初始化 `~/.dev-memory/config.json`。已有非空 `session_summary.command` 时保留现有配置,否则按以下顺序选择第一个可用工具:
|
|
68
|
+
|
|
69
|
+
单独执行 `install-hooks codex` 也会初始化这项 CLI 配置,但不会为 Codex CLI 增加 `SessionEnd` 事件;没有 Claude Code `SessionEnd` 或其它显式 enqueue 来源时,该配置不会自动启动总结任务。
|
|
70
|
+
|
|
71
|
+
| 优先级 | 工具 | 默认命令 |
|
|
72
|
+
| --- | --- | --- |
|
|
73
|
+
| 1 | `coco` | `coco -p --yolo --session-id {summary_session_id} {prompt}` |
|
|
74
|
+
| 2 | `codex` | `codex exec --ephemeral --ignore-user-config --ignore-rules --skip-git-repo-check --sandbox danger-full-access {prompt}` |
|
|
75
|
+
| 3 | `claude` | `claude -p --permission-mode bypassPermissions --session-id {summary_session_uuid} {prompt}` |
|
|
76
|
+
|
|
77
|
+
示例配置:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"session_summary": {
|
|
82
|
+
"provider": "codex",
|
|
83
|
+
"command": "codex exec --ephemeral --ignore-user-config --ignore-rules --skip-git-repo-check --sandbox danger-full-access {prompt}",
|
|
84
|
+
"max_attempts": 3
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
该机制依赖本地 CLI 命令,模型、账号和认证配置沿用被选 CLI;dev-memory 不直接集成 provider HTTP API。`session_summary.command` 支持自定义其它命令,`DEV_MEMORY_SESSION_SUMMARY_CMD` 提供进程级临时 override;`DEV_MEMORY_DISABLE_SESSION_SUMMARY_AGENT=1` 禁用后台总结执行。
|
|
90
|
+
|
|
91
|
+
### 总结作用
|
|
92
|
+
|
|
93
|
+
`SessionEnd` 总结用于从一次会话中提取对后续开发仍然有效的语义信息,而不是保存 transcript 副本或生成 changelog。处理流程如下:
|
|
94
|
+
|
|
95
|
+
1. `SessionEnd` 记录最终 HEAD,并把 job 写入 `<repo-memory>/jobs/session-summary/pending/`。
|
|
96
|
+
2. worker 从 transcript 中提取核心 user/assistant 文本,并加载现有 branch/repo 记忆。
|
|
97
|
+
3. 总结 CLI 只生成 summary-output JSON,不直接调用 dev-memory 命令。
|
|
98
|
+
4. worker 校验 JSON,最多重试 `max_attempts` 次,再通过代码应用结构化 patch。
|
|
99
|
+
5. job 根据结果移动到 `done/`、`skipped/` 或 `failed/`。
|
|
100
|
+
|
|
101
|
+
允许写入或修正的内容包括:
|
|
102
|
+
|
|
103
|
+
- decisions、risks、glossary
|
|
104
|
+
- 功能文件索引 `file_map`
|
|
105
|
+
- repo 级 shared decisions、context、sources
|
|
106
|
+
- 已有 entry 的 rewrite 或 delete
|
|
107
|
+
|
|
108
|
+
以下内容不会写入:
|
|
109
|
+
|
|
110
|
+
- 工具调用流水账、system 消息、reasoning
|
|
111
|
+
- 完整 transcript 或提交历史副本
|
|
112
|
+
- “当前进展”“下一步”“当前阶段”等时效性状态
|
|
113
|
+
- 与现有记忆相比没有有效变化的内容
|
|
114
|
+
|
|
115
|
+
无有效变化的 job 进入 `skipped/`,不会刷新 capture manifest,也不计为真实记忆写入。hook 采用后台执行,不等待总结完成。
|
|
116
|
+
|
|
117
|
+
## Codex 定时扫描
|
|
118
|
+
|
|
119
|
+
Codex CLI 和 Desktop 共用本地 rollout 文件:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl
|
|
123
|
+
~/.codex/archived_sessions/
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
安装 macOS LaunchAgent:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
dev-memory-cli session-scan install
|
|
130
|
+
dev-memory-cli session-scan status
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
任务默认每天本地时间 03:00 和 13:00 运行。LaunchAgent 使用 `session-scan run --scheduled`,运行前检查 macOS HID 空闲时长;最近 10 分钟有键鼠输入时写入 `skipped_active` 记录并退出,不读取会话正文、不调用模型。检测不可用时默认保守跳过。手工执行 `session-scan run` 不启用活跃检测。
|
|
134
|
+
|
|
135
|
+
首次扫描只回看最近 3 天;后续使用持久化字节游标补扫上次成功处理后产生的全部数据。`install-hooks codex` 与 `session-scan install` 相互独立。
|
|
136
|
+
|
|
137
|
+
扫描器只提取尚未处理的 user/assistant 语义消息,不限制消息数量,也不截断单条消息。材料超过单次模型上下文时按顺序分块,每个分块都进入中间摘要,再结合现有 memory 生成最终结构化结果。游标只在最终结果成功应用后推进。
|
|
138
|
+
|
|
139
|
+
### 执行器配置
|
|
140
|
+
|
|
141
|
+
`~/.dev-memory/config.json` 中的 `session_scan` 独立配置扫描执行器。默认提供 `coco`、`codex`、`claude` 三个 preset,并按顺序选择第一个已安装且启用的命令:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"session_scan": {
|
|
146
|
+
"executor": "auto",
|
|
147
|
+
"order": ["coco", "codex", "claude"],
|
|
148
|
+
"schedule_times": ["03:00", "13:00"],
|
|
149
|
+
"skip_when_computer_active": true,
|
|
150
|
+
"active_within_minutes": 10,
|
|
151
|
+
"activity_check_fail_closed": true,
|
|
152
|
+
"chunk_chars": 60000,
|
|
153
|
+
"idle_minutes": 60,
|
|
154
|
+
"first_lookback_days": 3,
|
|
155
|
+
"executors": {
|
|
156
|
+
"coco": {"enabled": true, "command": "coco", "model": null, "profile": null, "extra_args": [], "env": {}},
|
|
157
|
+
"codex": {"enabled": true, "command": "codex", "model": null, "profile": null, "extra_args": [], "env": {}},
|
|
158
|
+
"claude": {"enabled": true, "command": "claude", "model": null, "profile": null, "extra_args": [], "env": {}}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`model` 由内置适配器转换为对应 CLI 参数。`profile`、`extra_args` 和 `env` 用于选择账号、模型供应商、本地 provider 或代理。也可以增加自定义 preset;自定义命令需要自行保证结构化 JSON 输出。
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
dev-memory-cli session-scan config show
|
|
168
|
+
dev-memory-cli session-scan config set-executor codex
|
|
169
|
+
dev-memory-cli session-scan config set-model codex <model>
|
|
170
|
+
dev-memory-cli session-scan config set-profile codex <profile>
|
|
171
|
+
dev-memory-cli session-scan config set-schedule 03:00 13:00
|
|
172
|
+
dev-memory-cli session-scan config set-active-minutes 10
|
|
173
|
+
dev-memory-cli session-scan config set-active-check on
|
|
174
|
+
dev-memory-cli session-scan config validate
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
已安装定时任务时,`set-schedule` 会自动重载 LaunchAgent;活跃阈值和开关由每次运行动态读取,无需重装。
|
|
178
|
+
|
|
179
|
+
`auto` 只在命令不存在或 preset 被禁用时选择下一个执行器。模型调用失败不会自动换供应商,以免重复产生不可控费用。
|
|
180
|
+
|
|
181
|
+
### 递归防护
|
|
182
|
+
|
|
183
|
+
Codex preset 固定使用 `codex exec --ephemeral --json`,总结调用不会写入新的 rollout。扫描器还会登记内部 session/thread ID,并排除 `dev-memory-summary-` session 和带内部 prompt marker 的会话。即使自定义执行器产生持久化会话,也不会被下一轮当成业务会话重复总结。
|
|
184
|
+
|
|
185
|
+
### 账本与用量
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
~/.dev-memory/jobs/session-scan/
|
|
189
|
+
candidates/ # Codex Stop 登记
|
|
190
|
+
state/ # 会话字节游标
|
|
191
|
+
sessions/ # 原始大小、分块和用量摘要
|
|
192
|
+
runs/ # 每次扫描记录
|
|
193
|
+
logs/ # LaunchAgent stdout/stderr
|
|
194
|
+
events.jsonl
|
|
195
|
+
internal-sessions.jsonl
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
每个 run 记录原文件大小、本轮新增字节、语义消息和字符数、原会话累计 token、每次总结调用的执行器/模型/耗时/token,以及成功、跳过和失败状态。执行器没有返回 usage 时写为 `unavailable`,不会伪装成 0。
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
dev-memory-cli session-scan run --dry-run --json
|
|
202
|
+
dev-memory-cli session-scan run
|
|
203
|
+
dev-memory-cli session-scan stats --json
|
|
204
|
+
dev-memory-cli session-scan history --limit 20
|
|
205
|
+
dev-memory-cli session-scan show <run-id>
|
|
206
|
+
dev-memory-cli session-scan uninstall
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`dev-memory-cli ui` 的“会话扫描”视图读取同一账本,展示仓库扫描次数、会话数量、原始大小、新增数据量和每次总结 token。
|
|
210
|
+
|
|
211
|
+
## 接入边界
|
|
212
|
+
|
|
213
|
+
这个仓库是 skill suite,不是自动注入所有项目的独立插件:
|
|
214
|
+
|
|
215
|
+
- Claude 把 [hooks/hooks.json](hooks.json) 合并到 `.claude/settings.local.json`。
|
|
216
|
+
- Codex CLI 把 [hooks/codex-hooks.json](codex-hooks.json) 合并到 `.codex/hooks.json`。
|
|
217
|
+
- Codex Desktop 通过本地 rollout 定时扫描覆盖,不依赖项目 hook。
|
|
218
|
+
- 其他仓库需要先安装 CLI,再安装对应 hook;hook 运行时统一调用 `dev-memory-cli hook ...`。
|
|
85
219
|
|
|
86
220
|
## 原则
|
|
87
221
|
|
package/hooks/codex-hooks.json
CHANGED
package/hooks/hooks.json
CHANGED