All cas subcommands now output JSON via writeJson(), consistent with
other uwf commands. schema list includes meta-schema. Removed --json
flag and --format tree (tree is human-only, not machine-friendly).
Refs #319
小橘 🍊(NEKO Team)
- Remove CAS ref string support from workflow YAML outputSchema
- Simplify validate.ts: no string check for outputSchema
- Auto-set title from role name (workflow.role format)
Refs #319
小橘 🍊(NEKO Team)
When uwf workflow put processes inline JSON Schema for a role,
auto-inject title=roleName if not already set. Makes uwf cas schema list
show meaningful names like 'planner', 'coder' instead of (unnamed).
小橘 🍊(NEKO Team)
- Remove uwf cas list (CAS grows unbounded, listing all hashes is useless)
- Add title to Workflow/StartNode/StepNode schemas so schema list shows names
小橘 🍊(NEKO Team)
1. threads.yaml race condition: reload threads index after agent subprocess
completes before updating head pointer (cli-uwf/commands/thread.ts)
2. evaluateJsonata not awaited: jsonata evaluate() returns Promise for async
expressions — now properly awaited (uwf-moderator/evaluate.ts)
3. resolveWorkflowHash dead code: function always returns a value, removed
impossible null return type and dead null-check branches at call sites
(cli-uwf/store.ts, commands/thread.ts, commands/workflow.ts)
The agent subprocess writes StepNode to CAS on disk, but the parent
process had an in-memory cache from createFsStore init. Fix: re-create
store after agent spawn to pick up new nodes.
Also centralized JSON Schemas in uwf-protocol so cli-uwf and agent-kit
produce identical type hashes.
E2E smoke test passing: workflow put → thread start → 3x step → done
Refs #309
- thread start: ULID generation, StartNode to CAS, threads.yaml
- thread show: active (done:false) or archived (done:true)
- thread list: active threads, --all includes history
- thread kill: archive to history.jsonl
Refs #309, #313
Refactor dashboard graph/schema helpers and descriptor role validation
into smaller functions so bun run check passes without warnings.
Co-authored-by: Cursor <cursoragent@cursor.com>
Make AgentFn<Opt> always take a mandatory options argument, removing
the void conditional overload. Simplify createAgentAdapter, restore
exports needed by tests, and fix CLI test bundles to use cas.put
instead of disallowed @uncaged/* imports.
Co-authored-by: Cursor <cursoragent@cursor.com>
Now that bundles are fully self-contained (no external @uncaged/* imports),
the symlink mechanism is no longer needed.
- Delete ensure-uncaged-workflow-symlink.ts
- Remove ensureUncagedWorkflowSymlink from all imports/exports
- Remove ExtractBundleExportsOptions type (storageRoot param)
- Simplify extractBundleExports to single-arg signature
- Clean up stale comments
- Remove uncagedWorkflowExternals() from scaffold build script
- Remove --external from Bun.build config
- Tighten bundle validator: only Node built-ins allowed, all deps must be inlined
- Update skill.ts documentation
Bundles are now deterministic — same Node/Bun version = same behavior,
no dependency resolution at runtime.
Bundles must run without env vars — env vars are overrides, not requirements.
Single function: env(name, fallback) always returns string with a default.
- Removed requireEnv and optionalEnv
- Updated bundle entries, tests, and skill docs
小橘 🍊
requireEnv causes silent worker crash when env vars are missing —
thread shows 0 steps with no error. Use optionalEnv + sensible defaults.
Also added pitfall guidance in skill author docs.
小橘 🍊
The previous computeLayers used a reachability-based relation (a « b)
with depth tiebreaker to define a < b, then grouped nodes by == into
equivalence classes. However == is NOT an equivalence relation (fails
transitivity), making the grouping order-dependent and incorrect for
graphs with parallel branches.
Replace with standard Sugiyama longest-path layering:
1. DFS to detect and remove back-edges (break cycles)
2. Kahn's topological sort on the resulting DAG
3. rank(n) = max(rank(pred) + 1) for longest-path assignment
4. Group nodes by rank into layers
Also removes the experimental dagre layout strategy that was added
for comparison — longest-path produces better results for our
workflow graphs.
Replace linear spine walk with a proper partial order:
- a « b = a ~> b AND NOT b ~> a (strict precedence)
- a ~ b = incomparable under «
- depth tiebreaker for incomparable nodes
- Equivalent nodes (same layer) placed side-by-side horizontally
- scripts/publish-all.mjs: pins workspace:^ before npm publish, restores after
- Workaround for bun publish workspace:^ resolution bug in pre mode
小橘 🍊
- Add systemPrompt to WorkflowRoleDescriptor (protocol)
- Propagate systemPrompt through buildDescriptor and validateWorkflowDescriptor
- Display system prompt as collapsible <details> in RoleCard