Skip to content

fix(driver): an unloaded mode downgrades instead of hanging the dispatch - #51

Merged
Joshua-Gilbert merged 1 commit into
mainfrom
fix/bob-2.0.3-mode-preflight
Aug 14, 2026
Merged

fix(driver): an unloaded mode downgrades instead of hanging the dispatch#51
Joshua-Gilbert merged 1 commit into
mainfrom
fix/bob-2.0.3-mode-preflight

Conversation

@Joshua-Gilbert

Copy link
Copy Markdown
Collaborator

Problem

review/refactor/devsecops are not Bob built-ins — 2.0.3 ships agent/plan/ask. They come from the workspace's .bob/custom_modes.yaml that init-project-board.mjs installs, so any project without that file resolves none of them.

Bob reports an unresolvable slug by doing nothing. startTaskhandleInputMessage posts "Invalid mode used." to the webview and returns — after openTask has already created the task row. The driver therefore correlated a row that never ran: updated_at never passed created_at, hasRun() stayed false, the completion watch never settled, and the dispatch burned its full wall clock to report a bare timeout with no error text.

The symptom reads as a slow Bob, not a misconfigured workspace, so it can cost a whole dispatch timeout before anyone suspects the mode. As of today only 2 of the 12 checkouts under C:\vsPounceProject carry the modes file.

Change

Resolve the slug against what the workspace can actually load — 2.0.3's built-ins plus the slugs declared in the workspace and global custom_modes.yaml — before calling startTask. On a miss: print which file to add and dispatch in a fallback mode. Non-blocking by design; a missing mode never fails the dispatch.

bob2: mode 'review' is not loaded in this workspace — running as 'ask'.
Add it to C:\proj\.bob\custom_modes.yaml (e.g. `node tools/init-project-board.mjs <project>`).

The fallback is keyed on the safety profile rather than always landing on agent: a read-only slug goes to ask, the only built-in with no edit group. Sending an unresolvable review to agent would hand a read-only review write access to the code it was asked to inspect — a silent capability upgrade at exactly the moment the config is already wrong. The tradeoff is that ask has no execute either, so a degraded review can't run git diff: weaker, but weak in the safe direction, and the warning says how to restore the real mode.

Slugs are scraped rather than parsed — only the slug matters and the repo carries no YAML dependency, matching the same call in init-project-board.mjs. Over-reporting is the safe direction: a slug wrongly accepted just restores today's hang, while one wrongly missed would downgrade a working mode.

Also corrects a comment stating Bob throws Mode with id "<x>" not found on an unknown slug. That is resolveMode(), which startTask never calls.

Bob 2.0.3 compatibility

Verified against the 2.0.3 bundle and a live store; no driver changes needed for the upgrade itself:

  • startTask({content, mode, workspaceFolder, mask}) unchanged, still focuses bobChatView
  • schema unchanged — newest migration is still 2.0.2's 010_pending_approvals, so tasks/messages/task_pending_approvals still match the store reader
  • active → running → active lifecycle unchanged, still no completed
  • settings.json auto-approve keys unchanged and preserved across the upgrade
  • costs gained contextTokens, which parseCosts ignores

Latent, not firing: approval.forbiddenApprovalGroups is checked ahead of allowed_permissions in shouldAutoApprove and is driven by the DisabledAutoApprovalGroups GPO policy, whose definition default is edit,execute. No such policy is set on this machine, but if one is ever applied it would silently disable headless edit and execute.

Tests

9 new (736 total, all passing): slug scraping from the workspace file, a bare workspace, a null workspace and unparseable YAML, built-ins resolving untouched, custom modes resolving as themselves, the safety-preserving fallback mapping, and driver-level coverage that an unloaded mode warns, downgrades, and still completes while a loadable one dispatches silently.

review/refactor/devsecops are not Bob built-ins — 2.0.3 ships agent/plan/ask — they come
from the workspace's .bob/custom_modes.yaml that init-project-board.mjs installs. In a
project without that file the slug does not resolve, and Bob reports that by doing
nothing: startTask -> handleInputMessage posts "Invalid mode used." to the webview and
returns, after openTask has already created the task row. The driver correlated a row
that never ran, so updated_at never passed created_at, the completion watch never
settled, and the dispatch burned its full wall clock to report a bare timeout.

Resolve the slug against the workspace's modes before dispatching: on a miss, name the
file to add and run the turn in a fallback mode rather than stalling. The fallback keeps
the mode's safety profile — a read-only slug lands on ask, the only built-in with no edit
group, not on write-capable agent, so a review that lost its custom mode still cannot
rewrite the code it was sent to inspect.

The comment claiming Bob throws `Mode with id "<x>" not found` on an unknown slug
described resolveMode(), which startTask never calls; corrected alongside.

Verified against the 2.0.3 bundle and a live store: startTask, the tasks/messages/
task_pending_approvals schema (newest migration is still 010_pending_approvals), the
active->running->active lifecycle, and the settings.json auto-approve keys are all
unchanged. costs gained a contextTokens field the existing parser ignores.
@Joshua-Gilbert
Joshua-Gilbert merged commit 54f65ac into main Aug 14, 2026
3 checks passed
@Joshua-Gilbert
Joshua-Gilbert deleted the fix/bob-2.0.3-mode-preflight branch August 14, 2026 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant