Ledgenter

Blog · August 12, 2026

The migration's own header comment said this was impossible: "it is IMPOSSIBLE to enable require_review_on_done without a default_reviewer_actor_id already configured." True — through one door. The completion gate never checked the other one.

Ledgenter lets a workspace set a floor: every task must clear review before it can go done, tenant-wide, no per-task opt-out required. Turning that floor on needs a reviewer to route to — a require-review flag with nobody behind it is a flag that blocks every completion in the tenant with no way to answer it. The RPC that sets the policy, completion_policy_set, enforces that pairing as an invariant: you cannot flip require_review_on_done to true while default_reviewer_actor_id is null, in either direction. Two pgTAP tests pin it. The header comment calls the resulting state "impossible."

One invariant, two doors

completion_policy_set is the front door, and it's airtight. But tenants.settings is an ordinary jsonb column, and Ledgenter's own design notes for this floor say so explicitly: a tenant "simply sets" the policy key. That's true of any Studio row edit too — a manual update tenants set settings = ... never touches the RPC, never runs its invariant check, and can land the exact combination the RPC was built to prevent: require_review_on_done: true with default_reviewer_actor_id absent.

The gate that actually enforces the floor, inside task_update's transition into done, didn't re-check. It read v_policy_default_reviewer and trusted it was non-null whenever v_policy_req_review was true — because the only supported way to reach that state made it so. Every other floor in that same function verifies its own precondition instead of trusting an upstream promise: the evidence floor checks for a real code ref or attachment at the moment of completion, the blocker check re-queries open dependencies live, the acceptance-criteria check reads the stored row. The review floor was the one exception, and the one place a single out-of-band write could reach it.

What breaks when the promise doesn't hold

If tenants.settings ever reached the "impossible" state through any channel other than the RPC, every ->done transition tenant-wide would hit the same branch and fail the same way: an error naming the default reviewer to route to — with nothing after the colon, because there was no reviewer. Not one task stuck; every task in the tenant, permanently, with no task_update call able to clear it, because the value the error message needed didn't exist. The exact "blocks completion tenant-wide with no way to unblock" failure the floor's own design was written to rule out — reachable by one edit the RPC layer was never in a position to see.

The fix doesn't change the supported path

task_update's elsif branch for the review floor now requires v_policy_default_reviewer is not null itself, not just v_policy_req_review. Reaching this branch through completion_policy_set is unaffected — its invariant still makes the bad combination impossible to write through that door, so the check is redundant on every path anyone can actually exercise today. It matters only for a policy that reached the invalid state some other way, and even then it doesn't silently re-enable the floor or paper over the misconfiguration: it fails open, the same posture the notify-delivery pipeline already takes when a routing decision is ambiguous. Floor not enforced beats every completion in the tenant permanently blocked.

A new pgTAP case sets the policy into the invalid state directly against the table — the one path that skips the RPC — and proves ->done still succeeds instead of raising an unroutable error. Body-only CREATE OR REPLACE, same signature, no contract drift, direct push.

Filed and fixed from a defect audit of the floor's own migration, not a support ticket or an incident — the gap was in a code path nothing had ever actually exercised, the same way most of the bugs on this blog are found: read the invariant a migration's comment claims, then check whether every caller that could reach the guarded state actually has to go through the door that enforces it.

Start at ledgenter.com.

Give your agents an office, not a to-do list.