devlog-tracker 0.24.0 → 0.25.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 +8 -7
- package/cli/agents-md.js +4 -4
- package/cli/agents-md.test.js +10 -2
- package/cli/platforms/codex.js +19 -1
- package/hooks/scripts/tests/test-cli-init-e2e.sh +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# devlog-tracker
|
|
2
2
|
|
|
3
|
-
**版本** 0.
|
|
3
|
+
**版本** 0.25.0
|
|
4
4
|
|
|
5
5
|
在專案中維護一份 `.devlog/devlog.md`,把每一輪對話的請求、決策與結果寫成永久紀錄。對話一 `/clear` 或換 session 就沒了;這份檔案取代那個缺口,讓工作可以中斷再接。沒下過 `/devlog-tracker:start` 時,裝著也不會動任何檔案。
|
|
6
6
|
|
|
@@ -46,10 +46,10 @@ npx devlog-tracker init --codex --cursor
|
|
|
46
46
|
其他工具已設定的 hook)。重新執行 `npx devlog-tracker init` 可以升級到套件目前的
|
|
47
47
|
版本;`npx devlog-tracker status` 可以查目前裝的版本是否落後。
|
|
48
48
|
|
|
49
|
-
裝 Codex 時,`init`
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
裝 Codex 時,`init` 會從 `.devlog-tracker/commands/*.md` 產生對應的專案指令到
|
|
50
|
+
`.codex/prompts/`,例如以 `/prompts:devlog-start` 啟動追蹤。也會在專案根目錄的
|
|
51
|
+
`AGENTS.md` 加上(或更新)一段以 `<!-- devlog-tracker:begin/end -->` 包住的 fallback
|
|
52
|
+
說明。區塊外的內容不會動,重跑 `init` 只會換掉區塊本身;區塊裡只有相對路徑,可以 commit。
|
|
53
53
|
|
|
54
54
|
裝完 Codex 之後,第一次還要在 Codex 裡核准這些 hook,否則不會記錄(見下方〈Codex(選用)〉的「hook 需要審核」)。
|
|
55
55
|
|
|
@@ -106,8 +106,9 @@ Codex 目前沒有對應「使用者中斷」(Claude Code 的 `PostToolUseFail
|
|
|
106
106
|
Codex 上不會被標記成 `INTERRUPTED`;核心強制記錄機制(`Stop` 事件擋住未寫完的
|
|
107
107
|
輪次)不受影響。
|
|
108
108
|
|
|
109
|
-
Codex
|
|
110
|
-
|
|
109
|
+
Codex 使用 `/prompts:devlog-<名稱>`(例如 `/prompts:devlog-start`)執行指令;它們會
|
|
110
|
+
讀與 Claude commands 相同的內容。若使用的 Codex 環境沒有載入 custom prompts,仍可直接
|
|
111
|
+
使用以下腳本(`commands/*.md` 會優先讀 `CLAUDE_PLUGIN_ROOT`,否則讀
|
|
111
112
|
`DEVLOG_TRACKER_ROOT`):
|
|
112
113
|
|
|
113
114
|
```bash
|
package/cli/agents-md.js
CHANGED
|
@@ -8,16 +8,16 @@ const END = '<!-- devlog-tracker:end -->';
|
|
|
8
8
|
const BLOCK = `${BEGIN}
|
|
9
9
|
## devlog-tracker
|
|
10
10
|
|
|
11
|
-
這個專案用 devlog-tracker 在 \`.devlog/devlog.md\` 維護逐輪紀錄(Claude Code 與 Codex 共用同一份)。Codex
|
|
11
|
+
這個專案用 devlog-tracker 在 \`.devlog/devlog.md\` 維護逐輪紀錄(Claude Code 與 Codex 共用同一份)。Codex 指令在 \`.codex/prompts/\`,以 \`/prompts:devlog-<名稱>\` 執行;若 slash command 不可用,請照下面對照做:
|
|
12
12
|
|
|
13
13
|
1. 先 \`source .devlog-tracker/env.sh\`(設定 \`DEVLOG_TRACKER_ROOT\`)。
|
|
14
14
|
2. 依使用者意圖讀對應的 \`.devlog-tracker/commands/<名稱>.md\`,照裡面的步驟做(腳本在 \`.devlog-tracker/hooks/scripts/\`,執行時 \`CLAUDE_PROJECT_DIR\` 設成專案根目錄)。
|
|
15
15
|
|
|
16
16
|
| 使用者說 | 讀這份 |
|
|
17
17
|
|---|---|
|
|
18
|
-
| 開始追蹤 / start |
|
|
19
|
-
| 暫停 / pause |
|
|
20
|
-
| 狀態 / status |
|
|
18
|
+
| 開始追蹤 / start | \`/prompts:devlog-start\`;\`commands/start.md\` |
|
|
19
|
+
| 暫停 / pause | \`/prompts:devlog-pause\`;\`commands/pause.md\` |
|
|
20
|
+
| 狀態 / status | \`/prompts:devlog-status\`;\`commands/status.md\` |
|
|
21
21
|
| 接續上一題 / continue(換過工具或 \`/clear\` 之後) | \`commands/continue.md\` |
|
|
22
22
|
| 歸檔 / compact | \`commands/compact.md\` |
|
|
23
23
|
| 清空重編 / clean(不可復原,先問使用者確認) | \`commands/clean.md\` |
|
package/cli/agents-md.test.js
CHANGED
|
@@ -40,19 +40,27 @@ test('is idempotent and replaces the block in place', () => {
|
|
|
40
40
|
assert.equal(once.split(BEGIN).length, 2);
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
test('block mentions every command doc
|
|
43
|
+
test('block mentions every command doc and Codex prompt naming convention', () => {
|
|
44
44
|
const commandsDir = path.join(__dirname, '..', 'commands');
|
|
45
45
|
const text = fs.readFileSync(upsertAgentsMd(tmp()), 'utf8');
|
|
46
46
|
for (const file of fs.readdirSync(commandsDir).filter((f) => f.endsWith('.md'))) {
|
|
47
47
|
assert.ok(text.includes(`commands/${file}`), `AGENTS.md block is missing commands/${file}`);
|
|
48
48
|
}
|
|
49
|
+
assert.ok(text.includes('/prompts:devlog-start'));
|
|
49
50
|
});
|
|
50
51
|
|
|
51
|
-
test('init --codex writes AGENTS.md; --cursor alone does not', async () => {
|
|
52
|
+
test('init --codex writes AGENTS.md and custom prompts; --cursor alone does not', async () => {
|
|
52
53
|
const repoRoot = path.join(__dirname, '..');
|
|
53
54
|
const withCodex = tmp();
|
|
54
55
|
await run(['--codex'], { repoRoot, targetDir: withCodex, version: '0.0.0' });
|
|
55
56
|
assert.ok(fs.existsSync(path.join(withCodex, 'AGENTS.md')));
|
|
57
|
+
for (const file of fs.readdirSync(path.join(repoRoot, 'commands')).filter((file) => file.endsWith('.md'))) {
|
|
58
|
+
const prompt = fs.readFileSync(
|
|
59
|
+
path.join(withCodex, '.codex', 'prompts', `devlog-${path.basename(file, '.md')}.md`),
|
|
60
|
+
'utf8'
|
|
61
|
+
);
|
|
62
|
+
assert.match(prompt, /\$ARGUMENTS/);
|
|
63
|
+
}
|
|
56
64
|
|
|
57
65
|
const cursorOnly = tmp();
|
|
58
66
|
await run(['--cursor'], { repoRoot, targetDir: cursorOnly, version: '0.0.0' });
|
package/cli/platforms/codex.js
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
const { mergeHooksTemplate } = require('../merge-hooks');
|
|
4
5
|
const { upsertAgentsMd } = require('../agents-md');
|
|
5
6
|
|
|
7
|
+
function installPrompts({ targetDir, vendorRoot }) {
|
|
8
|
+
const commandsDir = path.join(vendorRoot, 'commands');
|
|
9
|
+
const promptsDir = path.join(targetDir, '.codex', 'prompts');
|
|
10
|
+
fs.mkdirSync(promptsDir, { recursive: true });
|
|
11
|
+
for (const file of fs.readdirSync(commandsDir)) {
|
|
12
|
+
if (!file.endsWith('.md')) continue;
|
|
13
|
+
const command = path.basename(file, '.md');
|
|
14
|
+
const source = path.join(commandsDir, file);
|
|
15
|
+
const destination = path.join(promptsDir, `devlog-${command}.md`);
|
|
16
|
+
fs.writeFileSync(
|
|
17
|
+
destination,
|
|
18
|
+
`${fs.readFileSync(source, 'utf8').trimEnd()}\n\n使用者提供的額外參數:$ARGUMENTS\n`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
6
23
|
function install({ repoRoot, targetDir, vendorRoot }) {
|
|
7
24
|
mergeHooksTemplate({
|
|
8
25
|
templatePath: path.join(repoRoot, 'codex', 'hooks.json'),
|
|
9
26
|
targetPath: path.join(targetDir, '.codex', 'hooks.json'),
|
|
10
27
|
vendorRoot,
|
|
11
28
|
});
|
|
29
|
+
installPrompts({ targetDir, vendorRoot });
|
|
12
30
|
upsertAgentsMd(targetDir);
|
|
13
31
|
}
|
|
14
32
|
|
|
15
|
-
module.exports = { install };
|
|
33
|
+
module.exports = { install, installPrompts };
|
|
@@ -19,6 +19,7 @@ NODE_BIN="$(command -v node)"
|
|
|
19
19
|
[ -f "$PROJECT/.devlog-tracker/VERSION" ] && echo "PASS: vendored VERSION exists" || { echo "FAIL: no VERSION"; FAIL=1; }
|
|
20
20
|
[ -f "$PROJECT/.devlog-tracker/env.sh" ] && echo "PASS: vendored env.sh exists" || { echo "FAIL: no env.sh"; FAIL=1; }
|
|
21
21
|
[ -f "$PROJECT/.codex/hooks.json" ] && echo "PASS: .codex/hooks.json written" || { echo "FAIL: no .codex/hooks.json"; FAIL=1; }
|
|
22
|
+
[ -f "$PROJECT/.codex/prompts/devlog-start.md" ] && echo "PASS: Codex start prompt written" || { echo "FAIL: no Codex start prompt"; FAIL=1; }
|
|
22
23
|
[ -f "$PROJECT/.cursor/hooks.json" ] && echo "PASS: .cursor/hooks.json written" || { echo "FAIL: no .cursor/hooks.json"; FAIL=1; }
|
|
23
24
|
|
|
24
25
|
# re-running must not duplicate entries
|