| 1 | # Workflows and goal mode — parity audit (Grok Build, DeepSeek Harness, Codewhale) |
| 2 | |
| 3 | Date: 2026-08-15. Evidence: the local Grok Build source sync at |
| 4 | `/Volumes/VIXinSSD/CW/grokbuild` (SOURCE_REV |
| 5 | `e6a67a5408288c98380cd13f3b1fe1fbc01c9f1f`, `crates/codegen/xai-workflow`, |
| 6 | `xai-grok-shell/src/session/{goal_*,workflow/*}.rs`), the installed DeepSeek |
| 7 | Harness `@deepseek-ai/dsh@0.1.0-rc.6` package READMEs (`dsh-goal`, |
| 8 | `dsh-tool-goal`, `dsh-goal-round-driver`, `dsh-command-goal`, |
| 9 | `dsh-tool-workflow`, `dsh-workflow`, `dsh-tool-ralph`, `dsh-tool-todo`, |
| 10 | `dsh-schedule`) and `config/agent-presets/standard/agent.cordis.yml`, plus a |
| 11 | real Codewhale dogfood run (Ollama `qwen3:4b`, isolated home) captured under |
| 12 | `scratchpad/wfgoal-captures/` (`g0*-*.txt`, `w0*-*.txt`, `wf-cli-run.log`). |
| 13 | Public Grok Build docs found by search: |
| 14 | [Developers Digest guide](https://www.developersdigest.tech/blog/grok-build-developer-guide-2026) |
| 15 | (`grok goal "…"`, `grok goal status|pause|resume|clear`, `--max-turns`, |
| 16 | Arena Mode) — official docs at x.ai/cli returned 404 for the deep pages. |
| 17 | |
| 18 | ## What Grok Build does (from source) |
| 19 | |
| 20 | - Goal mode is a state machine (`GoalTracker`): phases Idle → Planning → |
| 21 | Executing; statuses `active`, `user_paused`, `back_off_paused` (run cap), |
| 22 | `no_progress_paused` (verifier flagged the same gaps twice), `infra_paused` |
| 23 | (turn error), `blocked`, `budget_limited`, `complete`. Unknown persisted |
| 24 | statuses restore as `user_paused` — a goal never resurrects as |
| 25 | self-driving after a restart. A goal planner, an adversarial "skeptic |
| 26 | panel" classifier, a strategist that can restructure after stalls, a |
| 27 | summarizer, and a next-step generator sit around it. `/goal status`, |
| 28 | `/goal pause`, `/goal resume`, `/goal clear` are native. |
| 29 | - Workflows are Rhai scripts (`agent()`, `parallel()`, `phase`, `log`, |
| 30 | `budget`, scratch files, `git_diff_since`) with `meta {name, description, |
| 31 | whenToUse, phases}`, a call budget (`DEFAULT_AGENT_BUDGET = 128`), a |
| 32 | request-hash journal that replays completed calls so an edited or resumed |
| 33 | workflow does not repeat work, persisted run manifests (up to 128 restored |
| 34 | runs), pause kinds `user|back_off|no_progress|verification|infra`, saved |
| 35 | workflows in `.grok/workflows/*.rhai` (project + user scope, trust-checked |
| 36 | paths, name == meta.name), one builtin (`deep-research`), and native |
| 37 | `/workflows`, `/workflow resume <name>`, `/workflow stop <name>`, |
| 38 | `/workflow review`. |
| 39 | |
| 40 | ## What DeepSeek Harness does (from the installed package) |
| 41 | |
| 42 | - The goal domain is event-sourced session state (`goal/change` events with |
| 43 | full snapshots, compare-and-set `{id, revision}`), one current goal, phases |
| 44 | active/paused/blocked/complete, `defaultMaxGoalRounds = 256`. Activation |
| 45 | (permission to auto-continue) is process-local and never persisted: every |
| 46 | session start/fork disarms it and a human `/goal resume` rearms. |
| 47 | - The model-facing policy is what makes it enter goal mode readily: |
| 48 | "`create_goal` may infer goal intent from a direct human request in any |
| 49 | language; do not create a goal for routine single-turn work … Mark |
| 50 | complete only when the objective is actually achieved. Mark blocked only |
| 51 | after the same blocking condition persists for at least 3 consecutive goal |
| 52 | rounds." Creation is only accepted from a direct human turn of a root |
| 53 | agent — subagents and non-human producers are rejected at execution. |
| 54 | - The round driver queues one retained `<goal_round>` user message per round |
| 55 | naming the objective and `round/maxGoalRounds`; human messages never |
| 56 | consume rounds; cancellation pauses the goal so it cannot auto-restart. |
| 57 | - `/goal` (native command, no model turn) shows objective, phase, rounds and |
| 58 | the valid next commands; `/goal <objective>` never replaces an unfinished |
| 59 | goal without an explicit clear; `/goal edit|pause|resume|clear`. |
| 60 | - Workflows: the model writes a JavaScript script (`agent()`, `parallel()`, |
| 61 | `pipeline()`, `phase`, `log`, `args`) run by a worker-thread engine; |
| 62 | guidance says to use it "ONLY when the user explicitly asks for a workflow |
| 63 | or for large multi-agent orchestration"; foreground collection only, no |
| 64 | journaling/resume, no saved or nested workflows, no token budget |
| 65 | vocabulary (all stated in the package's Known Limitations). `ralph` runs a |
| 66 | fixed fresh-child loop (`maxRounds` 64 in the standard preset); |
| 67 | `todo_write` is the standing plan strip; `dsh-schedule` gives durable |
| 68 | reminders (`after_seconds`, `at`, `every_seconds` ≥ 5 min). |
| 69 | |
| 70 | ## What Codewhale does today (release candidate 533c530be + integration tip) |
| 71 | |
| 72 | - `/goal <objective> [budget: N]`, `pause|resume|done|blocked|clear`, |
| 73 | `declare-hunted`; state Active/Paused/Complete/Blocked with pause reasons |
| 74 | `user|backoff|no_progress|usage_limit|budget_limit`, gap-fingerprint stall |
| 75 | detection, completion verification (critical/advisory reviews), unlimited |
| 76 | continuations by default (`[goal] max_continuations` backstop, like Grok |
| 77 | Build's call cap), typed continuation prompt, thread-scoped goal |
| 78 | persistence for app-server clients (`thread/goal/*`). Interrupting a turn |
| 79 | keeps the goal active (design decision 2026-07-24) and only cancels the |
| 80 | auto-continuation timer. |
| 81 | - Workflows: JS authoring lowered to a typed `WorkflowSpec` (compile-only |
| 82 | subset), `task()/parallel()/pipeline()/phase()/log()/budget/args`, soft-auto |
| 83 | launch policy, plan-approval cards, per-run token budgets, worktree write |
| 84 | ownership, gates, per-event run journal `.codewhale/workflow-runs.jsonl` |
| 85 | with restart reconciliation, live workflow panel + history card, |
| 86 | `codewhale workflow run <name|--source-path> --runtime tmux|inline|vm|ci`. |
| 87 | |
| 88 | ## Dogfood findings (before this lane) |
| 89 | |
| 90 | 1. `/goal help` created a goal named "help" (no reserved help/status words). |
| 91 | 2. Bare `/goal` on an empty session spent a model turn asking the model to |
| 92 | invent an objective; a 4B local model answered with tool-syntax noise |
| 93 | (`g02-goal-bare-nogoal.txt`). |
| 94 | 3. `/goal` status used bracket tags (`Goal [HUNTING]: …`) and, after Esc, gave |
| 95 | no hint that nothing was driving the goal any more. |
| 96 | 4. `/workflow status` and `/workflow cancel` were routed *through the model* |
| 97 | ("Call the `workflow` tool with action `status`…") — a status check cost a |
| 98 | model turn and a cancel depended on a busy model obeying; the panel's |
| 99 | cancel control pre-filled that same command. |
| 100 | 5. The `[workflow]` table documented in `docs/AUTOMATIC_WORKFLOWS.md` |
| 101 | (`automatic`, `auto_start_read_only`, `require_approval_for_writes`, …) |
| 102 | was parsed but ignored: the tool consulted `WorkflowConfigToml::default()` |
| 103 | ("Product defaults … when the tool has no live Config handle"). |
| 104 | 6. The example workflows' header says `Run: /workflow run <path>` but the |
| 105 | slash command had no `run` verb (it became an objective for the model). |
| 106 | 7. `create_goal` was gated on "only when the user explicitly asks" — the |
| 107 | entry-path difference from DSH. |
| 108 | 8. A checked-in workflow ran end to end through the CLI with the local model |
| 109 | (`wf-cli-run.log`: two children, result `{"a":"hello","b":"world"}`, |
| 110 | journal + report written), and the TUI status can now read it. |
| 111 | |
| 112 | ## Matrix |
| 113 | |
| 114 | | Row | Grok Build | DeepSeek Harness | Codewhale | Verdict | |
| 115 | | --- | --- | --- | --- | --- | |
| 116 | | Authoring | Rhai script + meta; builtins; saved `.grok/workflows` | model-written JS script only | JS compile-only subset + structured `plan` + checked-in `.workflow.js`; `codewhale workflow run` | parity (different surface); saved-workflow *registry* with names is missing — checked-in files exist but no `/workflow list <saved>` | |
| 117 | | Triggering | manual `/workflow`, `/workflow resume` | model tool; `dsh-schedule` reminders | manual `/workflow`, soft-auto launch, `codewhale workflow run`, automations (`~/.codewhale/automations`) | parity; scheduled workflow runs deliberately not added here | |
| 118 | | Goal definition | `/goal`, planner phase | `/goal`, model-inferred `create_goal` | `/goal`, model `create_goal` — now inferable (this lane) | parity | |
| 119 | | Checkpoints / resume | journal replay of completed calls; run manifests; `/workflow resume` | none (documented limitation) | per-event journal + restart reconciliation; no replay-resume | partial (Codewhale ≥ DSH, < Grok Build) — follow-up | |
| 120 | | Approvals inside runs | plan-approve loop | tool approvals per child | plan-approval card gated by `[workflow]` (`require_approval_for_writes` / `auto_start_read_only`); session auto-approve still bypasses the card; writes inside a running VM step follow the VM runtime contract | parity | |
| 121 | | Progress / state visibility | `/workflows`, `/goal status`, tasks pane | web plan strip, `/goal` | workflow panel, work bar, `/workflow status` (now native), `/goal` (now plain, idle hint) | parity | |
| 122 | | Receipts / history | run manifests | session log | `.codewhale/workflow-runs.jsonl`, `/workflow status` lists journaled runs, trophy cards | parity | |
| 123 | | Failure handling / retry | pause kinds; strategist restructure | model judgment; ralph rounds | verifier gates, no-progress pause, blocked, `[goal] max_continuations` | parity; auto-restructure (strategist) deliberately absent | |
| 124 | | Cancellation | `/workflow stop <name>` native | cancel via signal | `/workflow cancel [id]` native (this lane); Esc cancels children | parity | |
| 125 | | Fan-out inside a workflow | `parallel()`, agent budget 128 | `parallel()/pipeline()`, no budget vocabulary | `parallel()/pipeline()`, 16 live / 1000 total, token budget | parity | |
| 126 | | Interrupt semantics | Ctrl+C pauses the goal | cancellation pauses the goal | Esc keeps goal active, cancels the timer, `/goal` now says how to continue | deliberately different (2026-07-24 dogfood decision) | |
| 127 | | Docs accuracy | — | — | fixed: `/workflow run`, `[workflow]` honored, `/goal` verbs | fixed | |
| 128 | |
| 129 | ## What this lane changed |
| 130 | |
| 131 | - `/workflow status|runs [run_id]`, `/workflow cancel [run_id]`, |
| 132 | `/workflow settings`, `/workflow help` are host answers |
| 133 | (`crates/tui/src/commands/groups/core/workflow.rs`, |
| 134 | `crates/tui/src/tools/workflow.rs::{host_workflow_runs, |
| 135 | host_cancel_workflow}`); `/workflow run <path>` launches a checked-in file |
| 136 | as-is; `/config workflow` / `/config goal` explain the effective tables. |
| 137 | - The workflow tool reads the session `[workflow]` table for approval and |
| 138 | admission decisions (`workflow_config_for`). `require_approval_for_writes` |
| 139 | gates the start card only: YOLO / session auto-approve still bypasses it, |
| 140 | and writes inside a running VM step stay on the VM runtime contract. |
| 141 | - `/goal help|?|status`, bare `/goal` prints usage on an empty session, plain |
| 142 | status wording (`Goal active: … · elapsed … · continuations N · not running |
| 143 | now — send a message or /goal resume to continue`). |
| 144 | - `create_goal` guidance now lets the model infer long-running intent from a |
| 145 | direct request (DSH policy) and promises a one-line receipt instead of a |
| 146 | confirmation question; the runtime shows `Goal set: "…" · /goal shows |
| 147 | progress · /goal pause or /goal clear stops it` when the model (or a |
| 148 | restored session) introduces a goal. |
| 149 | |
| 150 | ## Follow-ups (not done here) |
| 151 | |
| 152 | - Journal-replay resume for workflows (`/workflow resume <run_id>`): the |
| 153 | per-event journal already records every task; the missing piece is a |
| 154 | request-hash cache in the driver so completed leaves return their recorded |
| 155 | results on re-run (Grok Build `xai-workflow/journal.rs` is the reference). |
| 156 | - A saved-workflow registry (`.codewhale/workflows/*.workflow.js` with |
| 157 | `meta.name`, project + user scope, trust-checked) so `/workflow run <name>` |
| 158 | and `/workflow list` work by name; the CLI already resolves `workflows/`. |
| 159 | - Grok Build-style stall handling beyond no-progress pause (strategist |
| 160 | restructure, next-step generator) — evaluate after the prefix-cache lane, |
| 161 | since both add prompt sections. |
| 162 | - Small-context local models: the emergency compaction loop (`estimate ~3272 |
| 163 | tokens, budget ~1024` on an 8K Ollama route) and the phase strip showing |
| 164 | "Context automatically compacting…" for the whole turn were observed but |
| 165 | are outside this lane's scope (`g0*` captures). |
| 166 |