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
Two fixes:
1. cmdThreadRemove: always call both removeThreadEntry and
removeThreadHistoryEntries regardless of resolved source,
preventing race where thread moves from active to history
between resolve and delete.
2. Test: add waitUntilRunningFileAbsent before thread show/rm,
matching the pattern used by adjacent test cases.
Verified 5x consecutive runs with 0 failures.
Closes#265
- Workflow list is now a simple clickable list (no expand/collapse)
- Clicking a workflow navigates to dedicated detail page (#client/workflows/name)
- Detail page: fixed graph sidebar on left, scrollable role cards on right
- Back button returns to workflow list
- Route: added workflowName to hash routing
- Nested object: expand properties with └─ indentation
- object[]: show type as 'object[]', expand items.properties
- string[]/number[]: show type directly, no expansion
- oneOf/discriminatedUnion: variant headers with ├/└ connectors
- Auto-detect discriminator field (const values)
- Skip discriminator in variant field list
- Recursive to arbitrary depth
Phase 1+2 of #258
Left sidebar: compact workflow graph with clickable nodes for navigation.
Right panel: workflow overview card + per-role cards with meta schema tables.
Clicking a node in the graph scrolls to the corresponding role card.
All nodes are lit in static view (workflow definition, not a thread).
- Reduce feedback edge offset (140→80) for tighter layout
- Terminal nodes (start/end) now clickable when lit
- Unlit nodes have no cursor-pointer and ignore clicks
- Role nodes cycle through occurrences on repeated clicks
- Start node click scrolls to thread prompt
- End node click scrolls to bottom
- All records get data-record-index for scroll targeting
Ref: #247
What: Feedback (back) edges now connect from the left/right side of nodes
instead of top/bottom, making the routing visually clearer.
Changes:
- role-node.tsx: add Left/Right handles for feedback edge connections
- use-layout.ts: set sourceHandle/targetHandle for feedback edges
- condition-edge.tsx + use-layout.ts: increase FEEDBACK_OFFSET_X to 140
Ref: #247
What: Feedback (back) edges now alternate between left and right sides
instead of all routing to the right.
Why: Multiple feedback edges targeting the same node (e.g. reviewer→coder
and tester→coder) were overlapping on the right side.
Changes:
- types.ts: add feedbackSide field to ConditionEdgeData
- use-layout.ts: track feedback count per target, alternate sides
- condition-edge.tsx: feedbackPath() accepts side param, mirrors path for left
Ref: #247, closes#249
- Remove llmProvider and workspace from CursorAgentConfig (now just command/model/timeout)
- extractWorkspacePath uses runtime.extract + runtime.cas instead of standalone reactor
- TextProducerFn signature gains runtime parameter: (ctx, prompt, runtime)
- develop-entry.ts hardcodes cursor-agent path, no more env var dependency
- Drop @uncaged/workflow-reactor dep from workflow-agent-cursor
- Update tests for simplified config
小橘 <xiaoju@shazhou.work>
- wrangler.toml: keep first migration as AgentSocket (already applied),
second migration handles the rename
- index.ts: pathAfterAgent → pathAfterClient
- WS client receives app.fetch function instead of localPort
- Gateway mode no longer starts a local HTTP server
- Local-only mode (no secret) still starts HTTP server as before
- Removes unnecessary HTTP round-trip for gateway requests
- Delete tunnel.ts (startTunnel/cloudflared), rename to gateway.ts
- Remove --no-tunnel, --tunnel-url flags
- ServeOptions: drop noTunnel, tunnelUrl fields
- Two modes: gateway (with WORKFLOW_GATEWAY_SECRET) or local-only
- WS reverse connection is the only gateway transport
- PlannerMeta is now a discriminated union: planned | aborted
- Moderator routes aborted planner → END (no coder invocation)
- System prompt requires absolute workspace path, instructs abort if missing
- extractRefs handles both variants
- Test: 'planner aborted → END'
Signed-off-by: 小橘 <xiaoju@shazhou.work>
Planner, coder, reviewer, and tester system prompts now explicitly
instruct the agent to keep responses short and avoid pasting diffs,
code blocks, or full build logs. This reduces CAS storage and token
waste when downstream roles read the thread.
Signed-off-by: 小橘 <xiaoju@shazhou.work>