stephen-taipei/better-workflows-core
v6.0.0-alpha.2
Evidence binding, action gate and provider reconciliation for AI coding agents.
Changelog
Unreleased
Added
- What the hooks stopped is now in the ledger. When the Claude Code hook refuses a tool call or asks the person about one, it records a
tool.gatedentry with the decision, the reason, the command or file, and the session. Before, only Stop refusals and side effects that went ahead were recorded, so a review had to search the conversation logs for refusals.bw loglists the new entries. - A guide to building on Core.
docs/sdk.md(anddocs/sdk.zh-TW.md) explains the model, the CLI exit codes, the JavaScript API and the rules a host adapter must keep. Its example,examples/sdk/guarded-run.mjs, decides, records, runs and reports one command through the public API, and the test suite runs it. - Experimental Codex adapter.
bw hook codexconnects Codex hooks to the shared evidence, action and ledger checks. Liveapply_patch, plugin discovery andStopresponse behavior remain unverified on a live Codex host. - Versioned ledger entries. New entries use ledger version 1. Entries without
vremain readable and are verified using their original hash; a presentvthat is not a positive integer breaks the chain. Core keeps newer entries raw, exposes the maximum asstate.newerLedger, blocks side effects, opaque commands and completion until Core is upgraded, warns at the top ofbw status, and prints the maximum version frombw verify. When host hooks encounter a newer ledger version, they leave existing pending calls pending and do not append ledger records for those calls.
Changed
- Read-only Bash calls with no pending work on Claude Code and Codex no longer add ledger markers. Core writes
tool.consumedonly when a call has a pending result file or a corresponding pending action. Probe results and manual reconciliation now compare and append under the ledger lock, so stale probe results cannot replace newer history. - Codex upgrade handling is explicit. Pending-file names are host-specific; rerun checks that were in progress when upgrading.
PostToolUsecannot end older action records without a session field, so those actions remain open for reconciliation. Codexaskis denied withCodex hooks cannot ask; change the policy and retry.
6.0.0-alpha.2
Fixed
- The agent could fake a passing check with
bw run.bw run --kind test -- truerecorded a passingtestfor the current files, and the Claude Code hook let the agent run it. The hook now refusesbw runfrom the agent, however it is invoked (bw,npx bw,node …/bw.mjs,npx @better-workflows/core); a person can still use it. - Two sessions could both be let through for the same side effect. The hook decided from the ledger and recorded the action as two separate steps, so a second session could pass between them. The final decision and the record now happen under the ledger lock, and the second session is refused while the first one's result is open.
- A ledger lock older than 30 seconds was deleted. The lock now names its owner and is taken back only when that process, on the same machine, is gone. A lock whose owner is still running is never removed for being old; after waiting 10 seconds the writer reports which process holds it.
6.0.0-alpha.1
First release of Better Workflows Core, the V6 line. V5 is frozen on the frozen/v5 branch and shares no code with it.
The policy format (version: 1) may still change before beta.
What it does
- Evidence. A test, lint, typecheck or build result counts only for the exact working tree it ran on, only if it passed, and only if no file changed while it ran. A run whose exit code belongs to another command (
npm test | tail,npm test || true) never counts. - Completion.
completion.requirelists the evidence that must be fresh before work counts as complete. Exact kinds can name the directory they must run in (cwd) and the directories their result covers (scope);evidence.ignorekeeps check output out of the tree. - Action gate. Pushes, PR merges and creates, releases, package publishes,
gh apiand HTTP writes, and custom kinds needallowfrom.better-workflows/policy.json; the default isask. Commands Core cannot read areopaqueand asked about. The same side effect at the same commit is refused after it succeeded. - Reconciliation. Anything but exit code 0 leaves an action
unknown, and further side effects are refused until a read-only provider check (git ls-remote,gh pr view,gh release view,npm view) or a person settles it. - Ledger. Append-only and hash-chained in
.git/better-workflows/, with the last entry's seq and hash inledger.head, sobw verifyalso notices entries cut from the end. - Claude Code plugin. Six hooks:
SessionStart,PreToolUse,PostToolUse,PostToolUseFailure,Stop(sends the agent back once when required evidence is stale) andSubagentStop(settles refusals made during a subagent, never sends it back). - CLI.
bw init,run,check-completion,check-command,reconcile,status,verify,log. - Demo.
examples/stale-green/demo.mjsruns the stale-green and unknown-push stories in a few seconds without Claude.
Limits
- Claude Code is the only host. Other agents are not constrained by the policy.
- Core sees only the commands Claude Code shows its hooks; a side effect inside a script is invisible unless the policy names the script.
- Shell parsing is deliberately limited. A form Core cannot read is treated as not counting, or as needing a person.
- Rewriting
ledger.jsonlandledger.headtogether is not detected.