Skip to content

durable-log-gate blind spot: breadcrumb armed by the same Step 3.6 it guards, so a skipped Step 3.6 disarms the gate #95

Description

@Jodre11

Summary

The durable-log-gate Stop hook — the forcing function that is supposed to catch "a review intended a durable log but never wrote it" — has a structural blind spot: it cannot fire in exactly the scenario where the log write is skipped by the orchestrator ending its turn early (e.g. under claude -p). The guard and the thing it guards are armed by the same step, so if that step is skipped, both are.

Mechanism

hooks/durable-log-gate.sh blocks turn-end when a session-scoped breadcrumb is armed but the expected log file is absent. But the breadcrumb it keys on —
/tmp/claude-<session_id>/durable-log-expected.json — is written by Step 3.6 itself (SKILL.md ~1182), i.e. after the review-core Workflow returns.

So the ordering is:

Workflow returns  →  Step 3.6: (a) arm breadcrumb  (b) write durable log

If the turn ends before the Workflow returns (the -p teardown described in the sibling issue), Step 3.6 never runs → breadcrumb never armed → gate reads "no breadcrumb → inert (the common case)" and exits 0. The forcing function designed to catch the missing write is disarmed by the very same skipped step that causes the missing write.

Why it matters

The gate gives a false sense of coverage: "if a log was meant to be written and wasn't, the Stop hook will catch it and re-drive Step 3.6." That guarantee holds only when Step 3.6 started (armed the breadcrumb) and then the write failed — not when Step 3.6 never ran at all.

Impact

Low in practice today — full_log is default-OFF and only the A/B harness enables it, and the harness is moving to harvest the bundle from the Workflow journal directly rather than depend on Step 3.6. Recorded because it is a non-obvious gap in a mechanism whose whole purpose is "make the durable log reliable", and it would resurface if durable logging is ever made default-on or relied upon by a headless caller.

Possible fix

Arm the breadcrumb before the Workflow dispatch (Step 3.5), keyed on full_log being resolved-on, rather than inside Step 3.6. Then a turn that dies mid-Workflow still leaves an armed breadcrumb, and the gate can block turn-end / re-drive. (Needs care: the breadcrumb TTL + session-scoping logic already guards against stranded markers, so arming earlier is mostly a reordering.)

Provenance

Surfaced 2026-07-12 during panel-vs-classic A/B arm-tell capture (spec #3, Follow-up B), while diagnosing why both arms produced HARVEST_MISS. Sibling issue: review-gh-pr not -p-safe past the Workflow dispatch.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions