Skip to content

session-flow: measure the next tool after each block-hook-bypass denial, then choose accept or briefing #8986

Closed

Description

@kyle-sexton

Problem

The owner decided on 2026-10-12 (recorded on #5668, 2026-10-13): measure which tool follows each block-hook-bypass denial first, then choose between accept and briefing. #5668 adds the next_tool field to the friction collector. Running it over local transcripts on two machines and making the choice is not lane work.

Criteria moved from #5668

  • Run /session-flow:audit-friction on both machines, using only denials after 2026-10-04 (fix(guardrails): print each refusal once per call and advise only forms the guards allow #6303 changed the message), with main and subagent rates kept separate. The owner then picks accept or briefing.
  • The owner's choice is recorded on this issue.
  • For option 2 or 3: the per-1,000 denial rate and the similar-retry rate are re-measured after the change, main context and subagents separately.

Blocked by: #5668

Activity

  1. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    on Oct 22, 2026
  2. github-actions commented on Oct 22, 2026

    @github-actions
    Contributor

    Proposed work class: none

    Thanks for the report. Automated triage handed this issue to a maintainer.

    Automated triage. A maintainer reviews it.

  3. removed
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 25, 2026
  4. kyle-sexton commented on Oct 25, 2026

    @kyle-sexton
    MemberAuthor

    Released for re-triage under the owner's 2026-10-24 rule: an issue stops for a person only for an intent or vision question, a security call, a host or attended run, or spend outside prepaid credit. The hold label came off and intake triage runs again now; it re-applies a hold, with a numbered question, when one of those applies.

    To hold this issue again, add needs-human (or status: needs-decision) and say why in a comment.

  5. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 25, 2026
  6. kyle-sexton commented on Oct 25, 2026

    @kyle-sexton
    MemberAuthor

    Hold restored: the 2026-10-25 release took needs-human off, but this issue does need a person under the owner's stop rule. Reason (attended): "Run /session-flow:audit-friction on both machines ... The owner then picks accept or briefing."

  7. added
    host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.
    and removed
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 27, 2026
  8. kyle-sexton commented on Oct 28, 2026

    @kyle-sexton
    MemberAuthor

    Host run. I ran /session-flow:audit-friction --since 2026-10-04 through headless claude -p on both machines, melo-desk-001 (WSL) and melo-lap-001-wsl. Each run's step 1 (collect, then friction.py mine) wrote friction.json, and I tallied the block-hook-bypass denials and their next_tool fields from that file directly.

    What ran:

    • Version. Claude Code 2.1.312 on both lanes, subscription login, session-flow 1.7.0, which includes the next_tool field from feat(session-flow): record the next tool after each hook-block denial #9174.
    • Collect. collect.py collect --since 2026-10-04 --retention-days 180 --excerpt-chars 240 --excerpt-words 60 ran on each lane. My first headless turns backgrounded collect and ended before it finished, so I warmed the store with this command and then reran the skill.
    • Skill run. claude -p --permission-mode auto "/session-flow:audit-friction --since 2026-10-04 --verify probes", unattended with dry-run probes. Its step 1 wrote friction.json on each lane.
    • Later steps. The runs went on to the classify, cause-map and plan steps. The harness audits on both lanes found no permission edit warranted. The numbers below rest only on step 1's friction.json, not on any agent's summary.
    • Tally. A short read-only script summed every friction.json row whose key carries a block-hook-bypass denial message, by side, and grouped the rows' next_tool tallies.
      • Matched text: bypasses Write/Edit hook, or the & $var positional form.
      • From the same session store it also took the last session end with such a denial, and the shell-call count.
    • Coverage. Every denial counted below has a next_tool tally (tallied equals counted). The window keeps sessions that ended on or after 2026-10-04, so a session that began earlier can add a few earlier denials.

    Results: block-hook-bypass denials, and the tool called next in the same transcript:

    Machine Side Denials Next: Write/Edit Next: Bash Next: Read Other or none
    desk (WSL), 1,716 sessions main 125 71 (56.8%) 27 (21.6%), 7 failed 21 (16.8%) 6
    desk (WSL) subagent 1,444 856 (59.3%) 292 (20.2%), 28 failed 271 (18.8%) 25
    laptop (WSL), 554 sessions main 48 26 (54.2%) 13 (27.1%), 4 failed 7 (14.6%) 2
    laptop (WSL) subagent 556 282 (50.7%) 158 (28.4%), 17 failed 110 (19.8%) 6

    Against the criteria:

    1. "Run on both machines, post-2026-10-04 denials only, main and subagent kept separate": done. The table above has the result.
      • About 51-59% of denials are followed directly by Write or Edit, and another 15-20% by a Read, usually the file about to be edited.
      • 20-28% are followed by another Bash call. That is the upper bound on a shell retry: the field records the next tool, not how similar its command was.
      • The pattern is the same in main and subagent contexts on both machines.
      • No per-1,000 rate per side. The session store counts shell calls for main and subagents together (tools.by_name), so it cannot give a separate denominator for each side. I have not estimated one.
    2. "The owner picks accept or briefing": open. The finding below bears on it.
    3. Re-measure after option 2 or 3: not applicable until a choice is made.

    Finding: the guard has been retired since this issue was filed. #7627 (merged 2026-10-16) retired block-hook-bypass. On origin/main the guard script is gone and no hooks.json row runs it. The last session holding one of these denials ended 2026-10-17 on the desk and 2026-10-16 on the laptop, and neither machine has one after that.

    Recommendation: close this issue as overtaken by the retirement. The owner's choice is effectively option 1, accept. Briefing work would have nothing left to re-measure, because the denial no longer fires. Basis: plugins/guardrails/hooks/ on origin/main has no block-hook-bypass.sh, plus the latest-denial dates above.

    Decision recorded. Question: "Close #8986 as completed, superseded by merged #7627? The accept-or-briefing choice no longer has a guard to apply to." Owner answer (2026-10-28): "Yeah, go with recommendations."

    Resume step: if block-hook-bypass returns, reopen and rerun /session-flow:audit-friction from the next denial date.

    Target labels: add none; remove host-run.

  9. removed
    host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.
    on Oct 28, 2026
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

    priority: mediumReal value, no hard deadline; normal backlog flow.status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.

    Type

    Fields

    No fields configured for Task.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions