- Replace resolvePathInWorkspace with simple resolvePath (no boundary check)
- Remove UWF_BUILTIN_ALLOW_SHELL env gate from run_command
- Update tests accordingly
Per review: sandbox was false security with shell=true, and path
restrictions are unnecessary for a trusted agent environment.
Built-in role agent that uses workflow config models directly,
with its own tool-calling run loop. No external agent dependency.
- OpenAI-compatible chat completion client with tool_calls support
- P0 toolkit: read_file, write_file, run_command
- Integrates via createAgent factory from workflow-agent-kit
- CAS detail recording for each turn
- Path sandboxing and shell opt-in (UWF_BUILTIN_ALLOW_SHELL)
- uwf log list: list log files with sizes
- uwf log show --thread <id>: filter by thread ID
- uwf log show --process <pid>: filter by process ID
- uwf log clean --before <date>: delete old log files
- Tests: 12 new tests covering all subcommands
Implemented by solve-issue workflow, biome fixes applied manually.
Closes#413
Refs #411, #410
- cmdLogList: list log files with sizes, sorted by date descending
- cmdLogShow: filter entries by thread, process, and/or date
- cmdLogClean: delete log files older than given date
- 12 tests covering all functions and edge cases
Fixes#413
- Add isFirstVisit: boolean to AgentContext
- Compute from steps history: !steps.some(s => s.role === role)
- hermes.ts: use isFirstVisit for first-entry vs re-entry logic
- buildInitialPrompt: always append edgePrompt as Moderator Instruction
- edgePrompt is never blanked — always the real moderator instruction
- New tests for first-visit, re-entry, and fallback scenarios
Refs #405, #407, #404
Two bugs fixed:
1. request_permission messages (JSON-RPC requests with both id+method) were
silently swallowed by the response handler, causing hermes to hang waiting
for permission approval. Now properly distinguish responses (id only) from
server requests (id+method).
2. uwf-hermes process never exited after completing because the hermes ACP
subprocess was still alive. Now explicitly close the ACP client after
agent completion so the subprocess terminates.
小橘 <xiaoju@shazhou.work>
The official TS SDK's ndJsonStream hangs indefinitely on prompt()
for sessions with 20+ messages (solve-issue planner). Root cause
appears to be a stream backpressure issue in the SDK's ReadableStream
adapter.
Switch back to readline-based line parsing which reliably receives
all JSON-RPC responses. Also handle session/request_permission
inline (auto-approve, yolo mode equivalent).
Ref #398
UwfAcpClient now tracks all session/update events:
- agent_message_chunk → assistant message content
- agent_thought_chunk → assistant reasoning
- tool_call → pending tool invocation (name + rawInput)
- tool_call_update (completed/failed) → assistant tool_call + tool result
Messages are accumulated across prompts (same session) and stored
via storeHermesSessionDetail, restoring the full structured detail
(turns with tool calls, reasoning) that was lost in the initial ACP
migration.
Ref #398
The client is now created once in createHermesAgent() and shared by
runHermes and continueHermes closures. This preserves conversation
context during frontmatter retry loops — continue() sends a follow-up
prompt on the same ACP session instead of starting a new one.
Client is cleaned up via process.on('exit').
Ref #398
Replace 250-line custom ACP client with official TypeScript SDK.
Uses ClientSideConnection + ndJsonStream for stdio transport.
Same public API (connect/prompt/close), 115 lines, zero custom protocol code.
Ref #398
Remove spawnHermes, spawnHermesChat, spawnHermesResume, parseSessionId,
and buildResultFromSession. runHermes and continueHermes now use
HermesAcpClient for structured JSON-RPC communication.
Session ID comes directly from ACP protocol, eliminating #380 race
condition. Agent output collected via streaming chunks instead of
session file loading.
Phase 2 of RFC #398Fixes#380
Implements JSON-RPC client that communicates with `hermes acp` via
stdin/stdout. Replaces fragile stdout/stderr parsing with structured
protocol: initialize → session/new → session/prompt → collect chunks.
Session ID comes directly from protocol response, eliminating the
race condition in #380.
Phase 1 of RFC #398
buildOutputFormatInstruction now includes explicit language telling agents to
output ONLY schema-defined fields and to focus on their role's deliverable.
Fixes#394
Claude Code CLI adapter for the workflow engine, mirroring
workflow-agent-hermes architecture. Spawns `claude -p` with
`--output-format json` for structured output parsing.
Refs #391
Send a test completion request after configuration to verify the model
is reachable. If validation fails, warn the user and suggest trying a
different model or checking their settings.
Fixes#335
Replace hardcoded 5-field example with schema-driven generation.
Now shows actual enum values, types, and required markers for
each role's frontmatter schema.
Fixes#389
小橘 <xiaoju@shazhou.work>
Replace hardcoded 5-field candidate with schema-driven extraction.
Now reads outputSchema properties and picks matching fields from
parsed frontmatter, supporting role-specific fields like plan,
approved, success.
Falls back to standard 5 fields when schema has no properties.
Fixes#388
小橘 <xiaoju@shazhou.work>
Agent CLI outputs plain CAS hash (not JSON), engine parses plain hash.
StepOutput no longer carries sessionId — session info is already in CAS detail.
Keeps the valuable parts of #385: sessionId in AgentRunResult (process-internal),
continue support, and frontmatter retry loop.
Breaking changes:
- AgentRunResult now requires sessionId field
- AgentOptions now requires continue function
- Agent CLI outputs JSON {stepHash, sessionId} instead of plain CAS hash
- Engine parses JSON output (with legacy CAS hash fallback)
New features:
- Frontmatter validation retry: if agent output lacks valid frontmatter,
engine calls agent.continue() up to 2 times with correction message
- Session tracking: sessionId flows from agent → engine → StepOutput
- Hermes agent: session parse failure is now a hard error (no raw text fallback)
- Hermes agent: supports --resume for continue sessions
Closes#384
Agent output must contain valid YAML frontmatter matching the role schema.
If frontmatter parsing fails, the step fails immediately with a clear error
instead of falling back to an LLM extraction that can fabricate values.
The extract module remains as a public API export but is no longer used
in the agent run loop.
Breaking change: agents that relied on LLM extraction to produce valid
output will now fail. They must output proper frontmatter.
Add --count/-c flag to 'uwf thread step' for running N steps in one
invocation, stopping early if $END is reached.
- cmdThreadStep now loops up to count times, delegates to cmdThreadStepOnce
- CLI parses -c/--count, defaults to 1 (backward compatible single output)
- Validation rejects 0, negative, and non-integer counts
- 7 new tests covering CLI parsing and count validation
Fixes#373
Co-authored-by: uwf-hermes (solve-issue workflow)
Fallback transitions (last entry in graph node) omit the condition
field in YAML, resulting in undefined instead of null. The validator
and materializer now handle this:
- validate.ts: accept undefined as valid condition value
- workflow.ts: normalizeGraph() coerces undefined → null before CAS put
This was broken by the graph fallback pattern introduced in #370.
Register custom $first(role) and $last(role) functions in the JSONata
evaluator. These search the steps array and return the matching role's
frontmatter (output) directly, replacing verbose steps[-1].output.x
expressions with semantic $last('role').field syntax.
- workflow-moderator: register functions via expr.registerFunction()
- Updated all condition expressions in .workflows/ and examples/
- Added tests for $last, $first, and unmatched role (undefined)
Fixes#376
- Move generateCliReference() to @uncaged/workflow-util
- buildRolePrompt inlines CLI reference directly (no agent tool call)
- Fix Role terminology to use new field names
- Add maintenance comment in cli-reference.ts
- Fix test assertions
- Add legacy-packages/ and scripts/ to biome ignore
- Allow noDefaultExport in vitest.config.* and .d.ts
- Allow console in cli.ts and setup.ts (CLI user output)
- Fix unused imports in cas.ts and setup.ts
- Add .workflows/*.yaml scanning from project root (cwd)
- Resolution: project-local first, then global registry
- On-the-fly CAS materialization for local workflows
- Filename/name consistency check
- uwf workflow list shows origin (local/global)
Fixes#365
Breaking change per review:
- Remove systemPrompt from RoleDefinition entirely
- identity/prepare/execute/report are now required (string, not nullable)
- Remove all legacy fallback logic in buildRolePrompt
- Simplify validate.ts, workflow.ts materialize
- Migrate all test fixtures and example workflows
Refs #359
- New buildRolePrompt() in workflow-agent-kit: four-phase prompt assembly
with fallback to systemPrompt
- Export from agent-kit index
- Update uwf-hermes to use buildRolePrompt instead of raw systemPrompt
- Add tests for all modes: four-phase, legacy, mixed
Refs #359, #362