devlog-tracker 0.33.0 → 0.33.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  *English | [繁體中文](README.zh-TW.md)*
4
4
 
5
- **Version** 0.33.0
5
+ **Version** 0.33.1
6
6
 
7
7
  Maintains a `.devlog/devlog.md` in your project, turning each conversation round's requests, decisions, and outcomes into a permanent record. A conversation disappears the moment you `/clear` or switch sessions; this file fills that gap so work can pause and resume. Nothing is touched until you explicitly run `/devlog-tracker:start` — installing the plugin alone doesn't create or modify any files.
8
8
 
@@ -116,7 +116,7 @@ The table below uses the plugin's `/devlog-tracker:*` namespace; `npx init --cla
116
116
  | `/devlog-tracker:pause` | Pauses enforced recording; history files are untouched, and you can `start` again later. |
117
117
  | `/devlog-tracker:compact` | A script moves older `DONE` rounds into `devlog.archive.md` (Checkpoints and unfinished rounds stay in the main file). |
118
118
  | `/devlog-tracker:keep` | Scans the current branch's main file (to reorganize every devlog at once, use `keep-all`), groups it by topic, lists suggestions at once, then — after confirmation — moves each section out into its own `devlog.<name>.md` (leaving a `## Kept index` pointer line with a one-sentence topic description in the main file); can also extract a single section or merge everything into one history file. Not the same as compact. See [`docs/design/keep.md`](docs/design/keep.md). |
119
- | `/devlog-tracker:keep-all` | Reorganizes **every** devlog, not just the current branch's: the current main file, every other branch's `devlog.<branch>.md`, `devlog.archive.md`, and all files earlier `keep`/`keep-all` runs produced. Claude regroups their Rounds by topic across files (one topic spread over main, a feature branch and the archive ends up in one file), lists every proposed file at once, and after confirmation one script run writes them all or nothing. Existing kept files are broken up and rebuilt; each branch's unfinished tail (Rounds after its last `DONE`) and the open Round never move; branch files are never deleted. Every touched file is backed up to `.devlog/.keep-all-backup/<timestamp>/` first. Needs Node ≥18. See [`docs/design/keep-all.md`](docs/design/keep-all.md). |
119
+ | `/devlog-tracker:keep-all` | Reorganizes **every** devlog, not just the current branch's: the current main file, every other branch's `devlog.<branch>.md`, `devlog.archive.md`, and all files earlier `keep`/`keep-all` runs produced. Claude regroups their Rounds by topic across files (one topic spread over main, a feature branch and the archive ends up in one file), lists every proposed file at once, and after confirmation one script run writes them all or nothing. Existing kept files are broken up and rebuilt; each branch's unfinished tail (Rounds after its last `DONE`) and the open Round never move; a branch file left empty is deleted (except for a still-active branch, the current file and `devlog.md`). Every touched file is backed up to `.devlog/.keep-all-backup/<timestamp>/` first. Needs Node ≥18. See [`docs/design/keep-all.md`](docs/design/keep-all.md). |
120
120
  | `/devlog-tracker:overview` | Reads all kept `devlog.<name>.md` files and merges them into a cross-topic overview, plus a list of candidate rules that look like they belong in `CLAUDE.md`. Read-only — no workspace check, no confirmation, no writes. See the Kept index section of [`docs/design/keep.md`](docs/design/keep.md). |
121
121
  | `/devlog-tracker:promote` | Picks rule candidates from kept files, lessons files and Checkpoint `### 決策` sections, lists them numbered, and — only for the ones you choose — appends them to a managed `<!-- devlog-tracker:rules:begin/end -->` block in `CLAUDE.md` (or `AGENTS.md` when `CLAUDE.md` is just `@AGENTS.md`, or on Codex-only projects). Append-only, exact duplicates skipped; `init` never rewrites this block. |
122
122
  | `/devlog-tracker:search <keyword>` | Case-insensitive string search across `devlog.md`/`devlog.archive.md`/kept `devlog.<name>.md`/`devlog.lessons.<topic>.md`; Claude answers in its own words from the hits (with file/heading/line as evidence). Read-only — no workspace check, no confirmation, no writes. |
package/README.zh-TW.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  *[English](README.md) | 繁體中文*
4
4
 
5
- **版本** 0.33.0
5
+ **版本** 0.33.1
6
6
 
7
7
  在專案中維護一份 `.devlog/devlog.md`,把每一輪對話的請求、決策與結果寫成永久紀錄。對話一 `/clear` 或換 session 就沒了;這份檔案取代那個缺口,讓工作可以中斷再接。沒下過 `/devlog-tracker:start` 時,裝著也不會動任何檔案。
8
8
 
@@ -116,7 +116,7 @@ $devlog-start # npx init --codex
116
116
  | `/devlog-tracker:pause` | 暫停強制記錄,歷史檔不動,之後可再 `start`。 |
117
117
  | `/devlog-tracker:compact` | 腳本把較舊的 `DONE` 輪次搬到 `devlog.archive.md`(Checkpoint 與未完成輪留在主檔)。 |
118
118
  | `/devlog-tracker:keep` | 掃目前分支的主檔分主題(要一次整理所有 devlog 用 `keep-all`),一次列出建議,確認後把各段各自搬走成 `devlog.<name>.md`(並在主檔留一個 `## Kept 索引` 指標行,含一句主題描述);也可抽出一段或合併成全部歷史一檔。不是 compact。細節見 [`docs/design/keep.md`](docs/design/keep.md)。 |
119
- | `/devlog-tracker:keep-all` | 整理**所有** devlog,不只目前分支:目前的主檔、其他分支的 `devlog.<branch>.md`、`devlog.archive.md`,以及先前 `keep`/`keep-all` 產生的所有具名檔。Claude 跨檔依主題重新分段(同一個主題散在 main、feature 分支與 archive 的片段會合回同一檔),一次列出所有建議檔案,確認後由一支腳本整批寫入,全有或全無。既有的具名檔會被拆開重組;各分支未完成的尾巴(最後一個 `DONE` 之後的 Round)與開著的那一輪不會被搬,分支檔也不會被刪。動手前會先把所有會動到的檔備份到 `.devlog/.keep-all-backup/<時間戳>/`。需要 Node ≥18。細節見 [`docs/design/keep-all.md`](docs/design/keep-all.md)。 |
119
+ | `/devlog-tracker:keep-all` | 整理**所有** devlog,不只目前分支:目前的主檔、其他分支的 `devlog.<branch>.md`、`devlog.archive.md`,以及先前 `keep`/`keep-all` 產生的所有具名檔。Claude 跨檔依主題重新分段(同一個主題散在 main、feature 分支與 archive 的片段會合回同一檔),一次列出所有建議檔案,確認後由一支腳本整批寫入,全有或全無。既有的具名檔會被拆開重組;各分支未完成的尾巴(最後一個 `DONE` 之後的 Round)與開著的那一輪不會被搬,搬空的分支檔會被刪除(仍在開發的分支、目前主檔與 `devlog.md` 除外)。動手前會先把所有會動到的檔備份到 `.devlog/.keep-all-backup/<時間戳>/`。需要 Node ≥18。細節見 [`docs/design/keep-all.md`](docs/design/keep-all.md)。 |
120
120
  | `/devlog-tracker:overview` | 讀完所有已 keep 的 `devlog.<name>.md`,整合成跨主題總覽,並列出看起來該進 `CLAUDE.md` 的規範候選。純讀取,不核對工作區、不等確認、不寫檔。細節見 [`docs/design/keep.md`](docs/design/keep.md) Kept index。 |
121
121
  | `/devlog-tracker:promote` | 從已 keep 的檔、lessons 檔與 Checkpoint 的 `### 決策` 挑出規範候選並編號列出;只有你選定的才追加到 `CLAUDE.md`(`CLAUDE.md` 只有 `@AGENTS.md` 或只裝 Codex 時改寫 `AGENTS.md`)的 `<!-- devlog-tracker:rules:begin/end -->` 受管區塊。只追加、一字不差的重複會跳過;`init` 不會覆寫這個區塊。 |
122
122
  | `/devlog-tracker:search <關鍵字>` | 在 `devlog.md`/`devlog.archive.md`/已 keep 的 `devlog.<name>.md`/`devlog.lessons.<topic>.md` 裡做不分大小寫的字串搜尋;Claude 讀完命中後用自己的話回答(必要時附檔名/標題/行號)。純讀取,不核對工作區、不等確認、不寫檔。 |
@@ -45,6 +45,7 @@ DEVLOG_PROJECT_DIR="<專案根目錄絕對路徑>" bash "${PLUGIN_ROOT}/core/scr
45
45
  <來源檔> Round <編號…>(#<id…>)、<來源檔> Round <編號…>(#<id…>,分支 <origin> <state>)
46
46
  2. ...
47
47
  會被重整並刪除的既有 keep 檔:<檔名,逗號分隔,或「無」>
48
+ 會被搬空並刪除的分支檔:<檔名,逗號分隔,或「無」>
48
49
  可搬但偏瑣碎、留在原檔:<來源檔與 Round,或「無」>
49
50
  不能搬、保持原樣:<各分支未完成尾巴與開著的 Round,或「無」>
50
51
 
@@ -57,6 +58,8 @@ DEVLOG_PROJECT_DIR="<專案根目錄絕對路徑>" bash "${PLUGIN_ROOT}/core/scr
57
58
 
58
59
  同一則回覆可以合併多條修改;`N` 一律對應原始編號。使用者用文字要求把某些 Round 換段,照做後重新列一次再等。然後停止,使用者回覆前不要寫任何檔。
59
60
 
61
+ 「會被搬空並刪除的分支檔」=所有 Round 都分進某段、`state` 不是 `active`、且不是 `devlog.md` 的 `kind=branch` 來源(腳本會照這個規則刪)。
62
+
60
63
  - 取消 → 不改檔,結束。
61
64
  - `移除第 N 段`:該段若含 `kind=kept` 的 Round,拒絕並說明只能 `併入`;其餘 Round 留在原檔。
62
65
  - `第 N 段併入第 M 段`:合併 id,沿用第 M 段的檔名與描述。
@@ -77,7 +80,7 @@ DEVLOG_PROJECT_DIR="<專案根目錄絕對路徑>" bash "${PLUGIN_ROOT}/core/scr
77
80
  --apply "<專案根目錄絕對路徑>/.devlog/.keep-all-plan.tsv" --fingerprint <fp> --count <n>
78
81
  ```
79
82
 
80
- `<fp>`/`<n>` 用步驟 1 的值。不要自己搬檔、刪檔或改索引——腳本是唯一的實作:驗證計畫、把所有會動到的檔備份到 `.devlog/.keep-all-backup/<時間戳>/`、組好新檔、改寫來源、刪除被整理掉的 kept 檔與清空的 archive、重建 `## Kept 索引`(新索引行寫在目前分支的主檔)。分支檔與目前主檔即使搬空也不會被刪。
83
+ `<fp>`/`<n>` 用步驟 1 的值。不要自己搬檔、刪檔或改索引——腳本是唯一的實作:驗證計畫、把所有會動到的檔備份到 `.devlog/.keep-all-backup/<時間戳>/`、組好新檔、改寫來源、刪除被整理掉的 kept 檔、清空的 archive 與搬空的分支檔、重建 `## Kept 索引`(新索引行寫在目前分支的主檔)。搬空的分支檔只在該分支不是 `active` 時才刪;目前主檔與 `devlog.md` 一律不刪。
81
84
 
82
85
  - exit 1:原樣顯示 stderr,不要自行重試或手動補做。驗證錯誤時不會寫任何檔;fingerprint 不符代表掃描後檔案被改過,回到步驟 1 重新掃描。
83
86
  - 成功後刪除 `.devlog/.keep-all-plan.tsv`。
@@ -267,6 +267,7 @@ function apply(c, planText, expected, count) {
267
267
  const prefixes = new Map(segs.map(seg => [seg, []]));
268
268
  const rewritten = new Map(); // file -> new text | null (delete)
269
269
  const movedFromCurrent = new Set();
270
+ const touchedFiles = new Set();
270
271
 
271
272
  for (const src of s.sources) {
272
273
  const { lines, blocks, firstBlock } = src.parsed;
@@ -310,6 +311,7 @@ function apply(c, planText, expected, count) {
310
311
  continue;
311
312
  }
312
313
  if (!touched) continue;
314
+ touchedFiles.add(src.file);
313
315
  const text = joinPieces([lines.slice(0, firstBlock), ...stay]);
314
316
  const left = stay.length && parseBlocks(text).blocks.some(b => b.round !== null);
315
317
  rewritten.set(src.file, src.kind === 'archive' && !left && trimBlank(lines.slice(0, firstBlock)).length === 0 ? null : text);
@@ -331,6 +333,15 @@ function apply(c, planText, expected, count) {
331
333
  const updated = rewriteIndex(base, staleIndex, src.kind === 'current' ? newIndex : []);
332
334
  if (updated !== base) rewritten.set(src.file, updated);
333
335
  }
336
+ // A branch file keep-all emptied (only its origin marker left) is
337
+ // deleted, unless the branch is still active: checking it out again
338
+ // would migrate main's unfinished tail into a fresh file.
339
+ for (const src of s.sources) {
340
+ const t = rewritten.get(src.file);
341
+ if (src.kind !== 'branch' || src.file === 'devlog.md' || src.state === 'active' || typeof t !== 'string') continue;
342
+ if (!touchedFiles.has(src.file)) continue;
343
+ if (t.split('\n').every(l => l.trim() === '' || ORIGIN.test(l))) rewritten.set(src.file, null);
344
+ }
334
345
  if (!s.sources.some(x => x.kind === 'current')) {
335
346
  const head = c.origin ? `<!-- devlog-origin: ${c.origin} -->\n` : '';
336
347
  rewritten.set(c.current, rewriteIndex(head, staleIndex, newIndex));
@@ -135,6 +135,26 @@ test('apply moves a cross-file topic into one file in time order and consumes ke
135
135
  assert.ok(fs.existsSync(path.join(backup, 'devlog.md')));
136
136
  });
137
137
 
138
+ test('apply deletes a branch file it emptied, but not an active branch or devlog.md', () => {
139
+ const d = setup({
140
+ 'devlog.feat-main.md': '<!-- devlog-origin: branch=feat/main -->\n\n' + round(1, '2026-09-05T10:00:00+0800', 'IN_PROGRESS'),
141
+ 'devlog.md': '# proj\n\n' + round(1, '2026-09-01T10:00:00+0800', 'DONE'),
142
+ 'devlog.old.md': '<!-- devlog-origin: branch=old -->\n\n' + round(1, '2026-09-02T10:00:00+0800', 'DONE'),
143
+ 'devlog.keep-me.md': '<!-- devlog-origin: branch=keep-me -->\n\n' + round(1, '2026-09-03T10:00:00+0800', 'DONE') +
144
+ '\n' + round(2, '2026-09-03T11:00:00+0800', 'DONE'),
145
+ });
146
+ const c = ctx(d, { current: 'devlog.feat-main.md', open: '1' });
147
+ const s = scan(c);
148
+ const ids = [...idsOf(s, 'devlog.md', [1]), ...idsOf(s, 'devlog.old.md', [1]), ...idsOf(s, 'devlog.keep-me.md', [1])];
149
+ const out = apply(c, `alpha\t\t${ids.join(',')}\n`, s.fingerprint, s.rounds.length);
150
+ assert.ok(!exists(d, 'devlog.old.md'), 'emptied branch file deleted');
151
+ assert.match(out, /^DELETED=.*devlog\.old\.md$/m);
152
+ assert.ok(exists(d, 'devlog.keep-me.md'), 'branch file with rounds left stays');
153
+ assert.ok(exists(d, 'devlog.md'), 'devlog.md is never deleted');
154
+ const backup = out.match(/^BACKUP=(.*)$/m)[1];
155
+ assert.ok(fs.existsSync(path.join(backup, 'devlog.old.md')), 'deleted branch file is backed up');
156
+ });
157
+
138
158
  test('apply may reuse the name of a kept file it consumes', () => {
139
159
  const d = world();
140
160
  const c = ctx(d);
@@ -44,7 +44,7 @@ APPLY="$(bash "$SCRIPT_DIR/keep-all.sh" --apply "$TMP/plan.tsv" --fingerprint "$
44
44
  if [ $? -eq 0 ]; then echo "PASS: apply exits 0"; else echo "FAIL: apply exits 0"; FAIL=1; fi
45
45
  [ -f "$R/.devlog/devlog.old-branches.md" ] && grep -q "^KEPT=.*devlog.old-branches.md ROUNDS=2" <<<"$APPLY" \
46
46
  && echo "PASS: named file written" || { echo "FAIL: named file written"; FAIL=1; }
47
- check "branch files keep their marker and are not deleted" '[ "$(head -n 1 "$R/.devlog/devlog.feat-merged.md")" = "<!-- devlog-origin: branch=feat/merged -->" ]'
47
+ check "emptied merged/gone branch files deleted" '[ ! -e "$R/.devlog/devlog.feat-merged.md" ] && [ ! -e "$R/.devlog/devlog.feat-deleted.md" ] && grep -q "^DELETED=.*devlog.feat-merged.md" <<<"$APPLY"'
48
48
  check "index written to the current branch file" 'grep -q "devlog.old-branches.md\`:keep-all,2 輪" "$R/.devlog/devlog.feat-live.md"'
49
49
  check "lock released" '[ ! -e "$R/.devlog/.lock" ] && [ ! -d "$R/.devlog/.lock.d" ]'
50
50
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devlog-tracker",
3
- "version": "0.33.0",
3
+ "version": "0.33.1",
4
4
  "description": "npx installer for devlog-tracker's Claude Code, Cursor and Codex adapters.",
5
5
  "bin": {
6
6
  "devlog-tracker": "bin/devlog-tracker.js"
@@ -432,7 +432,7 @@ keep 只整理目前分支的主檔;keep-all 一次整理 `.devlog/` 裡**所
432
432
  主檔、其他分支的 `devlog.<branch>.md`、`devlog.archive.md`,以及既有的具名檔。Round 依時間
433
433
  拿到全域編號,Claude 跨檔依主題重新分段、一次列出建議,確認後 `core/scripts/keep-all.sh`
434
434
  整批執行(全有或全無,先備份到 `.devlog/.keep-all-backup/`)。既有 kept 檔的 Round 必須全部
435
- 重新分配;各分支最後一個 `DONE` 之後的未完成尾巴與開著的那一輪不搬;分支檔搬空也不刪。
435
+ 重新分配;各分支最後一個 `DONE` 之後的未完成尾巴與開著的那一輪不搬;搬空的分支檔(分支非 `active`)會刪除,目前主檔與 `devlog.md` 不刪。
436
436
  新索引行寫進目前分支主檔的 `## Kept 索引`。需要 Node。步驟見 `commands/keep-all.md`。不要自動觸發。
437
437
 
438
438
  ## 接續具名保存:`/devlog-tracker:resume <name>`