Skip to content

0.47.0 — Approve a commit whose message lives in a file

Choose a tag to compare

@mikebronner mikebronner released this 17 Sep 23:07
· 21 commits to main since this release
ca055bd

⚡ After you update

Restart any session that should be governed. A running session holds the plugin it loaded at start, so an open conversation keeps the old hooks until it restarts.

If you want Watson to stop carrying an effort default, edit your own config. Setup never overwrites ~/.claude-workbench/dev-team-config.json, which is deliberate — your edits survive every update. The consequence here is that an existing install keeps whatever watson.effort it already had, and the next setup run stamps that value straight back into the frontmatter. Remove the key yourself, then re-run /workbench-dev-team:setup.

✨ Approve a commit whose message lives in a file

The approval gate refused git commit -F <path>, which is the shape it should have preferred. The gate makes the command run twice, so a message written inline lands in your transcript twice in full.

The subject check looked for the subject in the command text, and a -F command carries only a path. It now reads the first line of the file git will read, in every spelling git accepts — -F <path>, --file=<path>, --file <path>, and short clusters like -aF. Variables in the path resolve from the command's own assignments and from the environment, never by running a shell on it: the recorded command is caller-controlled text, so expanding it through a shell would be the injection this gate exists to prevent.

The file is display. The command is still the decision. Every check that decides whether an approval may be granted finishes before the first byte of a message file is read. A file can refuse an approval or name a commit. It can never widen one, change which command an approval covers, or stand in for an approval that was never granted.

It fails closed. A path that will not resolve, a file that will not open, an empty message, and -F - each refuse and name their own case. A command that promised no subject at all, such as --amend --no-edit, falls back to the request id as before.

🔥 No shipped effort default for Watson

Watson carried effort: xhigh in the shipped config from 2026-06-12, and in its frontmatter from 2026-09-11, when the setup stamper first made the interactive dispatch path read frontmatter. Nobody read either line for months.

Correcting the number would have fixed one value and left the next wrong one just as invisible, so the key goes instead. A value that is never shipped cannot drift.

The config key and the frontmatter line had to go together. The stamper rewrites frontmatter from the config on every setup run, and setup runs at install, so removing the line alone would have been cosmetic.

The consequence, stated rather than buried: Dispatch stops passing --effort for Watson too. Per-agent effort control for Watson is gone on both paths, not only the interactive one. Watson inherits the session's effort instead.

Holmes and Lestrade keep high. The same drift argument applies to them identically, but between them they ran three dispatches in fourteen days, so changing them buys nothing against a review- or triage-quality risk. The asymmetry is deliberate and each document now says so.

📐 An advisory working-context budget on every agent

All three agent definitions now carry a target of roughly 250k tokens of working context for a single task.

Nothing enforces that figure, and nothing in the harness can. maxBudgetUsd is passed on the scheduled dispatch path and reaches no other, and the Agent tool that spawns an agent from a live conversation exposes no budget parameter at all. The wording says so outright, because a limit presented as enforced when it is not gets trusted and then silently exceeded.

The five-slot brief template stays free of figures. The two numbers measure opposite sides of a handoff: a brief-length ceiling would bound the prose a sender writes, while this bounds the context a receiver accumulates. A shorter brief does not buy a cheaper run, which is why the brief-length figure was removed in the first place and stays removed.