devlog-tracker 0.24.0 → 0.25.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # devlog-tracker
2
2
 
3
- **版本** 0.24.0
3
+ **版本** 0.25.1
4
4
 
5
5
  在專案中維護一份 `.devlog/devlog.md`,把每一輪對話的請求、決策與結果寫成永久紀錄。對話一 `/clear` 或換 session 就沒了;這份檔案取代那個缺口,讓工作可以中斷再接。沒下過 `/devlog-tracker:start` 時,裝著也不會動任何檔案。
6
6
 
@@ -46,10 +46,12 @@ npx devlog-tracker init --codex --cursor
46
46
  其他工具已設定的 hook)。重新執行 `npx devlog-tracker init` 可以升級到套件目前的
47
47
  版本;`npx devlog-tracker status` 可以查目前裝的版本是否落後。
48
48
 
49
- 裝 Codex 時,`init` 還會在專案根目錄的 `AGENTS.md` 加上(或更新)一段以
50
- `<!-- devlog-tracker:begin/end -->` 包住的說明,告訴 Codex 沒有 slash 指令時該讀
51
- `.devlog-tracker/commands/*.md`。區塊外的內容不會動,重跑 `init` 只會換掉區塊本身;
52
- 區塊裡只有相對路徑,可以 commit。
49
+ 裝 Codex 時,`init` 會從 `.devlog-tracker/commands/*.md` 產生對應的專案 skill 到
50
+ `.agents/skills/devlog-<名稱>/SKILL.md`,例如在 Codex 打 `$devlog-start`(或用 `/skills`
51
+ 選)啟動追蹤。舊版(0.25.0)寫到 `.codex/prompts/` 的檔案會在重跑 `init` 時清掉——
52
+ Codex 不讀專案層級的 custom prompts。也會在專案根目錄的
53
+ `AGENTS.md` 加上(或更新)一段以 `<!-- devlog-tracker:begin/end -->` 包住的 fallback
54
+ 說明。區塊外的內容不會動,重跑 `init` 只會換掉區塊本身;區塊裡只有相對路徑,可以 commit。
53
55
 
54
56
  裝完 Codex 之後,第一次還要在 Codex 裡核准這些 hook,否則不會記錄(見下方〈Codex(選用)〉的「hook 需要審核」)。
55
57
 
@@ -106,8 +108,8 @@ Codex 目前沒有對應「使用者中斷」(Claude Code 的 `PostToolUseFail
106
108
  Codex 上不會被標記成 `INTERRUPTED`;核心強制記錄機制(`Stop` 事件擋住未寫完的
107
109
  輪次)不受影響。
108
110
 
109
- Codex 沒有 `/devlog-tracker:*` slash 指令面;hooks 裝好後,請用與 Claude commands
110
- 相同的腳本(`commands/*.md` 會優先讀 `CLAUDE_PLUGIN_ROOT`,否則讀
111
+ Codex 使用 `$devlog-<名稱>`(例如 `$devlog-start`)執行指令;它們會讀與 Claude
112
+ commands 相同的內容。若使用的 Codex 環境沒有載入專案 skills,仍可直接使用以下腳本(`commands/*.md` 會優先讀 `CLAUDE_PLUGIN_ROOT`,否則讀
111
113
  `DEVLOG_TRACKER_ROOT`):
112
114
 
113
115
  ```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 沒有 \`/devlog-tracker:*\` slash 指令,請照下面對照做:
11
+ 這個專案用 devlog-tracker 在 \`.devlog/devlog.md\` 維護逐輪紀錄(Claude Code 與 Codex 共用同一份)。Codex 指令是 \`.agents/skills/devlog-<名稱>/\` 底下的 skill,用 \`/skills\` 選或打 \`$devlog-<名稱>\` 執行;若 skill 不可用,請照下面對照做:
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 | \`commands/start.md\` |
19
- | 暫停 / pause | \`commands/pause.md\` |
20
- | 狀態 / status | \`commands/status.md\` |
18
+ | 開始追蹤 / start | \`$devlog-start\`;\`commands/start.md\` |
19
+ | 暫停 / pause | \`$devlog-pause\`;\`commands/pause.md\` |
20
+ | 狀態 / status | \`$devlog-status\`;\`commands/status.md\` |
21
21
  | 接續上一題 / continue(換過工具或 \`/clear\` 之後) | \`commands/continue.md\` |
22
22
  | 歸檔 / compact | \`commands/compact.md\` |
23
23
  | 清空重編 / clean(不可復原,先問使用者確認) | \`commands/clean.md\` |
@@ -40,19 +40,35 @@ 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 so Codex has an entry for each', () => {
43
+ test('block mentions every command doc and Codex skill 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('$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 project skills; --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 name = `devlog-${path.basename(file, '.md')}`;
59
+ const skill = fs.readFileSync(path.join(withCodex, '.agents', 'skills', name, 'SKILL.md'), 'utf8');
60
+ assert.match(skill, new RegExp(`^---\\nname: ${name}\\ndescription: ".+"\\n---\\n`));
61
+ }
62
+ assert.ok(!fs.existsSync(path.join(withCodex, '.codex', 'prompts')));
63
+
64
+ const upgraded = tmp();
65
+ const legacy = path.join(upgraded, '.codex', 'prompts');
66
+ fs.mkdirSync(legacy, { recursive: true });
67
+ fs.writeFileSync(path.join(legacy, 'devlog-start.md'), 'old');
68
+ fs.writeFileSync(path.join(legacy, 'mine.md'), 'keep');
69
+ await run(['--codex'], { repoRoot, targetDir: upgraded, version: '0.0.0' });
70
+ assert.ok(!fs.existsSync(path.join(legacy, 'devlog-start.md')));
71
+ assert.ok(fs.existsSync(path.join(legacy, 'mine.md')));
56
72
 
57
73
  const cursorOnly = tmp();
58
74
  await run(['--cursor'], { repoRoot, targetDir: cursorOnly, version: '0.0.0' });
@@ -1,15 +1,52 @@
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
+ // Codex 只從 ~/.codex/prompts/ 讀 custom prompts(且已棄用),不會讀專案內的
8
+ // .codex/prompts/;專案層級的指令要做成 .agents/skills/<name>/SKILL.md,以 $<name> 叫用。
9
+ function parseCommand(text) {
10
+ const match = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(text);
11
+ if (!match) return { description: '', body: text };
12
+ const description = /^description:\s*(.*)$/m.exec(match[1]);
13
+ return { description: description ? description[1].trim() : '', body: match[2] };
14
+ }
15
+
16
+ // 0.25.0 曾把 prompts 寫到 .codex/prompts/devlog-*.md,Codex 讀不到;升級時清掉。
17
+ function removeLegacyPrompts(targetDir) {
18
+ const promptsDir = path.join(targetDir, '.codex', 'prompts');
19
+ if (!fs.existsSync(promptsDir)) return;
20
+ for (const file of fs.readdirSync(promptsDir)) {
21
+ if (/^devlog-.*\.md$/.test(file)) fs.rmSync(path.join(promptsDir, file));
22
+ }
23
+ if (fs.readdirSync(promptsDir).length === 0) fs.rmdirSync(promptsDir);
24
+ }
25
+
26
+ function installSkills({ targetDir, vendorRoot }) {
27
+ const commandsDir = path.join(vendorRoot, 'commands');
28
+ for (const file of fs.readdirSync(commandsDir)) {
29
+ if (!file.endsWith('.md')) continue;
30
+ const name = `devlog-${path.basename(file, '.md')}`;
31
+ const { description, body } = parseCommand(fs.readFileSync(path.join(commandsDir, file), 'utf8'));
32
+ const skillDir = path.join(targetDir, '.agents', 'skills', name);
33
+ fs.mkdirSync(skillDir, { recursive: true });
34
+ fs.writeFileSync(
35
+ path.join(skillDir, 'SKILL.md'),
36
+ `---\nname: ${name}\ndescription: ${JSON.stringify(description)}\n---\n\n${body.trim()}\n\n使用者提供的額外參數:請看觸發這個 skill 的使用者訊息。\n`
37
+ );
38
+ }
39
+ removeLegacyPrompts(targetDir);
40
+ }
41
+
6
42
  function install({ repoRoot, targetDir, vendorRoot }) {
7
43
  mergeHooksTemplate({
8
44
  templatePath: path.join(repoRoot, 'codex', 'hooks.json'),
9
45
  targetPath: path.join(targetDir, '.codex', 'hooks.json'),
10
46
  vendorRoot,
11
47
  });
48
+ installSkills({ targetDir, vendorRoot });
12
49
  upsertAgentsMd(targetDir);
13
50
  }
14
51
 
15
- module.exports = { install };
52
+ module.exports = { install, installSkills };
@@ -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/.agents/skills/devlog-start/SKILL.md" ] && echo "PASS: Codex start skill written" || { echo "FAIL: no Codex start skill"; 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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devlog-tracker",
3
- "version": "0.24.0",
3
+ "version": "0.25.1",
4
4
  "description": "npx installer for the devlog-tracker Claude Code plugin's Cursor and Codex adapters.",
5
5
  "bin": {
6
6
  "devlog-tracker": "bin/devlog-tracker.js"