Skip to content

autoplan phase hook refuses nearly every real Claude Code transcript (claude-public-transcript.ts ownership walk). #2977

Closed

Description

@rikimasorati

readOwnedClaudePublicTranscript requires one parentless user root in the project cwd and a strictly backward parent chain. Real Claude Code transcripts break both: (1) the first record is usually a parentless SessionStart hook_success attachment; (2) a resumed or compacted session starts with a compact_boundary whose logicalParentUuid points FORWARD into copied-in context, which the walk reads as a cycle; (3) the harness flushes children before parents (measured 3,886 forward parentUuid links beside hook attachments, 312 elsewhere over 400 transcripts). Measured: the unpatched reader accepts 1 of 400 local transcripts, so phase-publication-hook denies every phase entry with 'Native parent evidence has not reached the journal yet', and the only exit a user sees is a new session. Proposed fix (running locally, gstack suites 575/575): keep the strict walk, fall back on refusal to membership by declared parent chain reaching the file's first node (any direction; a boundary's forward logical parent continues from its predecessor; a missing parent only before the first message), expose a refusal reason code, raise MAX_BYTES (3/400 transcripts exceed 128 MiB), and poll min(45 s, max(3 s, 2x first read)). Separately (harness, not gstack): the phase-entry tool_use record is sometimes not in the transcript until the PreToolUse hook returns (13/18 trials).

Activity

  1. Corenthin-Buffard commented on Sep 28, 2026

    @Corenthin-Buffard

    Additional data on the harness-side part of this issue ("the phase-entry tool_use record is sometimes not in the transcript until the PreToolUse hook returns"). This happens even when the transcript is owned and readable, so it can still block after the ownership-walk fix.

    Environment: gstack 1.91.2.0, Claude Code 2.1.283, Linux (Ubuntu 26.04), idle 24-core VPS. readOwnedClaudePublicTranscript returns status: "ready" for the live session (about 5 ms), so the ownership walk is not the cause here.

    Observations: a background watcher tailed the session .jsonl and logged when the guarded Read tool_use line reached disk.

    Trial Hook deadline Guarded Read sent tool_use line on disk Result
    1-2 2 s alone after the hook returned denied ("has not reached the journal yet")
    3 2 s in parallel with a Bash call about 1.3 s, during the hook reached publication checks
    4 2 s alone 2.2 s, written together with the denial result denied
    5 10 s alone never during the hook (waited the full 10.07 s) denied
    6 10 s in parallel with a trivial echo Bash call flushed when the Bash result was written allowed

    Conclusion: raising the poll deadline does not help. In these trials, Claude Code wrote the pending tool_use to the transcript only when another tool result forced a write, not during the hook. A lone guarded Read waits for a record that is written only after the hook exits. So the adaptive min(45 s, ...) poll proposed above would probably still deny a lone phase-entry Read, just more slowly.

    Workaround: send each guarded phase-entry Read/Agent call in the same assistant message as a trivial Bash call (echo flush). The Bash result makes the harness write the transcript, which includes the pending tool_use.

    Possible fixes on the gstack side:

    • Do not rely on the in-flight tool_use being on disk. For example, authorize from tool_use_id + tool_input in the hook payload plus the already-flushed history.
    • Or document/instruct the parallel-flush pairing in autoplan/SKILL.md.
    • Or file a Claude Code harness bug: flush the pending assistant tool_use record before running PreToolUse hooks.
  2. capy-ai commented on Oct 2, 2026

    @capy-ai
    Contributor

    Fixed in v1.91.13.0 (#3013, merged as f30b7b7): the reader accepts SessionStart-rooted journals and a forked session that starts at a compact boundary (captured from claude 2.1.284), and failures now carry typed reason codes. The forward logicalParentUuid shape did not reproduce on 2.1.284; it is followed normally if it appears, and a loop is reported as a cycle. Run /gstack-upgrade, then start a new Claude Code session. Thanks for the report. Reopen if you still see it after upgrading.

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