Three scenarios testing the full CLI pipeline:
1. Linear workflow (planner → worker → $END): CAS chain integrity
2. Loop workflow (developer ↔ reviewer): moderator routing through cycles
3. Role mismatch detection: agent catches routing bugs
Uses workflow add → thread start → thread exec with uwf-mock,
verifying CAS state, thread lifecycle, and error handling.
Updated assertions to use getThread().status === 'completed'
(aligned with PR #45 unified thread storage).
Refs #33
New package @united-workforce/agent-mock (uwf-mock CLI):
- Reads pre-scripted outputs from a YAML mock data file (--mock-data)
- Counts existing CAS chain steps to determine step index
- Validates expected role matches actual moderator routing
- Stores minimal detail node in CAS for valid step refs
- Zero LLM, instant execution, 100% deterministic
Usage in config.yaml:
agents:
mock:
command: uwf-mock
args: ["--mock-data", "./fixtures/scenario.yaml"]
Refs #33
Instead of hardcoding workflow as empty string for completed/cancelled
threads, use resolveWorkflowFromHead to get the actual workflow hash
from the CAS chain, consistent with active thread handling.
Closes#46
uwf thread resume now supports completed threads:
- Evaluates workflow graph from $START to find first role
- Clears completed state (status → idle, completedAt → null)
- Builds resume prompt with supplement context
- Full CAS chain preserved for rich context
Suspended resume behavior unchanged.
Cancelled/idle threads still rejected.
425 tests pass.
Part of #39, closes#43
- store.ts: all threads in @uwf/thread/* with status tag
- Remove HISTORY_VAR_PREFIX, ThreadHistoryLine, deleteThread
- Add loadActiveThreads, loadHistoryThreads, completeThread
- Add migrateHistoryVarsToThreadVars migration
- thread.ts: replace deleteThread+addHistoryEntry with completeThread
- shared.ts: remove findHistoryEntry fallback
- Update all tests for unified storage model
422 tests pass.
Part of #39, closes#41, closes#42
- ThreadIndexEntry gains status and completedAt fields
- createThreadIndexEntry defaults to idle/null
- normalizeThreadIndexEntry backward-compat defaults
- updateThreadHead resets to idle (衔尾蛇 resume prep)
- markThreadSuspended sets status=suspended
- New markThreadCompleted(entry, status, now) function
- serializeThreadIndexEntry includes new fields
Part of #39, closes#40
- @ocas/core and @ocas/fs upgraded from ^0.2.2 to ^0.3.0
- agent-hermes: replace better-sqlite3 with node:sqlite (DatabaseSync)
- Remove better-sqlite3 and @types/better-sqlite3 dependencies
- Fix remaining bun references in cli test helpers (execFileSync)
Refs #28
- Add missing await on store.cas.put() in run.ts:192
- Replace #!/usr/bin/env bun → #!/usr/bin/env node in all CLI bins
- Update issue-551 test to assert node shebang
- Update issue-551 test: assert bun engines removed (not present)
- Migrate session-detail tests from bun:sqlite to better-sqlite3 API
(db.exec for DDL, db.prepare().run() for inserts)
Refs #26
Remove migrateStorageIfNeeded() which created symlinks from
~/.uncaged/workflow → ~/.uwf and ~/.uncaged/json-cas → ~/.ocas.
This was temporary migration support. Users who still have old paths
can run a one-time copy manually.
Zero 'uncaged' references remain in active codebase.
createAgentStore was calling getCasDir(storageRoot) which resolves to
~/.uwf/cas/, but since Phase 3 all CAS data lives in ~/.ocas/.
getActiveThreadEntry already used getGlobalCasDir() correctly, causing
a split where thread lookup succeeded but CAS node reads failed.
Found during e2e walkthrough after Phase 0-5 migration.
- Remove entire 'uwf cas' command group from CLI
- Delete commands/cas.ts (only used by CLI + tests)
- Delete cas.test.ts and cas-exit-code.test.ts
- Update workflow YAMLs: uwf cas get/has/refs/walk → ocas
- Update e2e-walkthrough script to use ocas
- Update docs and reference files
- Keep store-global-cas.test.ts (internal CAS store tests)
CAS operations now go through 'ocas' CLI exclusively.
Agent text storage handled internally by uwf pipeline.
Closes#10
- thread list: suspended threads show [suspended] marker via statusDisplay
- thread show: displays suspendedRole, suspendMessage, and resume hint
- New ThreadShowOutput type with hint field
- Tests: 3 cases for display formatting
Closes#591
- Add GraphPseudoRole type ($END | $SUSPEND) to workflow-protocol
- Add 'suspended' to ThreadStatus
- evaluate() returns EvaluateSuspendResult for $SUSPEND targets
- Thread show/list derive suspended status from moderator evaluation
- validate-semantic treats $SUSPEND like $END (valid target, no outgoing edges)
- Tests: routing to $SUSPEND, mustache rendering, thread status display
Closes#588
- Add !include custom YAML tag for referencing external files (Fixes#582)
- .md/.txt files included as strings
- .json files parsed as JSON objects
- .yaml/.yml files parsed as YAML objects
- Paths resolved relative to the workflow YAML file
- Support foo/index.yaml as alternative to foo.yaml (Fixes#583)
- Updated discoverProjectWorkflows(), findWorkflowInDir()
- Updated workflowNameFromPath() for index.yaml detection
- Flat files take priority over folder layout
- Added tests for both features
Fixes hallucination issues observed in thread 06F7FSTXQGY3D5CY5YPQFK2Y3W:
1. Developer self-verification (critical): Added step 12 requiring
mandatory verification of branch, file existence, and git status
before reporting done status. Prevents hallucinated completions
without actual tool execution.
2. Reviewer hard-check enforcement (critical): Added critical warning
and step 0 requiring cd/pwd verification before review. Prevents
false rejections based on assumptions without actual path checks.
3. Test debugging escalation (medium): Added structured debugging
guidance with escalation path after 3 test cycles. Prevents
infinite retry loops by providing strategy and fail-fast guidance.
Also added 3 test cases to verify the new procedure steps exist.
Based on change plan 9EVZPDTS16PMG analyzing execution anomalies
that resulted in 58% waste (13 of 23 minutes).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>