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.
|
|
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
|
|
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.
|
|
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
|
|
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 讀完命中後用自己的話回答(必要時附檔名/標題/行號)。純讀取,不核對工作區、不等確認、不寫檔。 |
|
package/commands/keep-all.md
CHANGED
|
@@ -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
|
|
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`。
|
package/core/scripts/keep-all.js
CHANGED
|
@@ -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
|
|
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
|
@@ -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>`
|