fix(cli-workflow): resolve step/thread commands on completed threads

Fixed issue #469 where `uwf step list`, `uwf step show`, and `uwf thread read`
failed with "thread not active" error when called on completed threads.

The root cause was that resolveHeadHash() in shared.ts only checked threads.yaml
(active threads index) but never fell back to history.jsonl (completed threads log).

Changes:
- Updated resolveHeadHash() in shared.ts to check history.jsonl as fallback
- Changed error message from "thread not active" to "thread not found"
- Added comprehensive test coverage:
  - Unit tests for resolveHeadHash() with active/completed/missing threads
  - Integration tests for cmdStepList() with completed threads
  - Integration tests for cmdStepShow() with completed threads
  - Regression tests for cmdThreadRead() with completed threads

All commands now work identically for active and completed threads.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 16:14:12 +00:00
parent c2c849df7e
commit dfdf0ac073
3 changed files with 499 additions and 7 deletions
+9 -5
View File
@@ -6,7 +6,7 @@ import type {
StepNodePayload,
ThreadId,
} from "@uncaged/workflow-protocol";
import { loadThreadsIndex, type UwfStore } from "../store.js";
import { findThreadInHistory, loadThreadsIndex, type UwfStore } from "../store.js";
type ChainState = {
startHash: CasRef;
@@ -203,11 +203,15 @@ function collectOrderedSteps(
async function resolveHeadHash(storageRoot: string, threadId: ThreadId): Promise<CasRef> {
const index = await loadThreadsIndex(storageRoot);
const head = index[threadId];
if (head === undefined) {
fail(`thread not active: ${threadId}`);
const activeHead = index[threadId];
if (activeHead !== undefined) {
return activeHead;
}
return head;
const hist = await findThreadInHistory(storageRoot, threadId);
if (hist !== null) {
return hist.head;
}
fail(`thread not found: ${threadId}`);
}
export {