fix(tracker): drain item description into worktree on first attach - #227
Conversation
createItem no longer writes any files to <projectPath>/tracker/items/<slug>/. The user-typed body is stashed on index.sessions[slug].description, and ensureItemFiles drains it into notes.md inside the worktree on first run. No requirements.md stub is created — that file only appears when the requirements stage produces real content. Legacy main-project source dirs are still migrated, then deleted so the project root gets cleaned up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Use leading-underscore parameter and destructure variable names so TS sees them as intentionally unused, instead of `void item;` / `void _drop;` noise lines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fuse readSessionDescription + clearSessionDescription into one read-modify- write inside ensureItemFiles. Each cold-path call now reads the index at most once and only writes when a description was actually stashed; old shape did two reads (one always wasted) and one wasted write per attach. Drop the now-unused TrackerItem parameter from ensureItemFiles; readItem already reads the title from index.sessions[slug].title. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review: fix(tracker): drain item description into worktree on first attachOverviewThis PR fixes a design flaw where This is a clean, well-reasoned architectural fix. The logic is sound and the tests are thorough. A few issues worth flagging: Potential Bug: delete-after-copy on same-path edge caseIn for (const src of legacySources) {
for (const file of fs.readdirSync(src)) {
const destFile = path.join(destDir, file);
if (fs.existsSync(destFile)) continue;
fs.copyFileSync(path.join(src, file), destFile);
wroteAnything = true;
}
fs.rmSync(src, {recursive: true, force: true}); // ← deletes immediately after copy
}
Potential Data Loss: description silently discarded when notes.md already exists from legacy migrationThe comment acknowledges this is intentional, but it creates a silent drop scenario: if (!fs.existsSync(notesPath)) {
fs.writeFileSync(notesPath, `${entry.description}\n`);
wroteAnything = true;
}
// description cleared regardless
const {description: _, ...rest} = entry;If a legacy Tracker item file included in PR diff
Style / Minor
Test CoverageThe new tests are solid:
Missing test: the edge case where legacy migration populates Summary: The core logic and architecture are correct. The delete-after-copy on same-path and the silent description-discard are the two items worth addressing before merging. |
|
Thanks for the review. Triaged:
|
Summary
createItemno longer writes any files to<projectPath>/tracker/items/<slug>/. The user-typed description is stashed onindex.sessions[slug].descriptionand drained into<worktree>/tracker/items/<slug>/notes.mdon the firstensureItemFilescall.requirements.mdstub anywhere — that file only appears when the requirements stage produces real content. Existing orphan probes (!currentItem.requirementsPath) keep working because they check the path string, not file existence.ensureItemFilesmigrates files from any legacy main-project location (the oldtracker/items/<slug>/staging dir, plus pre-refactortracker/{backlog,implementation}/<slug>/layouts) and deletes the source dir so the project root gets cleaned up.readItemtitle fallback now readsindex.sessions[slug].titleso the kanban renders the correct title even without the stub.Test plan
npm run typecheckcleannpm test— 724/724 passtests/unit/tracker.test.ts,tests/unit/tracker-board-create-flow.test.ts,tests/unit/tracker-proposal-create.test.tsto reflect index-onlycreateItemandensureItemFilesdoing the file writesnotes.mdlands in the worktree (not the project root) andindex.sessions[slug].descriptionis cleared<projectPath>/tracker/items/<slug>/is migrated into the worktree and the source dir is removed🤖 Generated with Claude Code