Skip to content

0.7.0 — the human's answer is in the chain

Latest

Choose a tag to compare

@github-actions github-actions released this 15 Sep 15:25

Record schema 8. One theme: make the log answer questions the data already held.

The human's decision is in the chain. obstat approve and obstat deny now append a durable approval record as the database row changes — the approval id, the request record it answers, the state, who decided. Until now the chained record of a refusal was written by the agent's next retry, so an agent that never came back left the human's answer in the one store here anyone can UPDATE. That §8 item is gone.

obstat log --dangling lists every allowed call with no outcome record and says what its run says about why: the run ended, so the outcome write was lost; the run has no end marker, so the process died or is still serving; or the record predates schema 7. 0.6.0 put the run markers in the file. Nothing read them until now.

obstat pending warns the approver holding a rubber stamp. A request whose tool named nothing in record_args gets a line saying so — a digest and a resource id are all the approver then has.

A denial keeps its record id through the MCP SDK. A new test calling through the SDK found that since SDK 2.2 any exception that is not its own ToolError is treated as a crash: the traceback is logged and the client is told only Error executing tool <name>. Under the current SDK, obstat's denials were reaching agents with no record id at all. Denied now inherits from the SDK's class when the SDK is importable, and from Exception otherwise. No dependency added; except Denied is unchanged. The built wheel was run through the full suite on every MCP 2.x release, 2.0.0 through 2.2.0.

Also: py.typed ships, so type checkers see the annotations; the §9 table lists the fork-child run test; a subject resolver that raises is recorded (0.6.1) and the spec's §3.1 table has it as step 1c.

65 tests.