Skip to content

lib/hook-utils.test.sh: 'a Windows backslash path' begin case is flaky on Linux CI #4357

Description

@kyle-sexton

Problem

On PR #4352, CI run 35858998103, job test-linux (2), step "Run plugin contract tests", one case in lib/hook-utils.test.sh failed:

FAIL: begin: a Windows backslash path → FILE_DIR '' (want '.'), FILE_BASE '' (want 'x.md')
PASS=506 FAIL=1

When I reran the failed job on the same commit (f43d49e), it passed, so the case is nondeterministic. PR #4352 does not touch lib/hook-utils.sh or its test. The suite passes locally on Windows Git Bash with 510/0.

Both fields came back empty. That means the driver never printed its REACHED=1 block for this row: hook::begin exited before the printf, or the row's output was lost. The case is the table-driven "post-read half" loop at lib/hook-utils.test.sh around line 3899, which uses the BG_STUB_FILE reader stub.

Done when

  • The cause of the empty output on Linux is identified.
  • The case, or hook::begin, is made deterministic.
  • The fix is verified by repeated runs of the suite on Linux.

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Sep 23, 2026
  2. kyle-sexton commented on Sep 23, 2026

    @kyle-sexton
    ContributorAuthor

    This was generated by AI during triage.

    Additional occurrence, from #4360 (being closed as a duplicate of this issue): on PR #4210, CI run 35865887568, job test-linux (2) (https://github.com/melodic-software/claude-code-plugins/actions/runs/35865887568/job/107197366977), two begin cases failed in the same suite:

    FAIL: begin: a nested path → FILE_DIR '' (want '/a'), FILE_BASE '' (want 'b.md')
    FAIL: begin: a Windows backslash path → FILE_DIR '' (want '.'), FILE_BASE '' (want 'x.md')
    PASS=505 FAIL=2
    

    Same shard and the same empty FILE_DIR/FILE_BASE signature, so the defect is not limited to the Windows backslash row: the nested path row of the same post-read loop failed too. Re-running only the failed job on the same commit passed, and an earlier head with byte-identical content passed every job.

  3. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Sep 23, 2026
  4. added theissue type on Sep 23, 2026
  5. kyle-sexton commented on Sep 23, 2026

    @kyle-sexton
    ContributorAuthor

    This was generated by AI during triage.

    Agent Brief

    Type: Bug
    Summary: Make the hook::begin table-driven cases in the hook-utils test suite pass deterministically on Linux CI.

    Current behavior:
    On test-linux (2) the post-read begin cases intermittently report empty FILE_DIR and FILE_BASE (the "a Windows backslash path" row on runs 35858998103 and 35865887568, the "a nested path" row on 35865887568). Re-running the same commit passes. Empty values for both fields mean the driver never printed its REACHED=1 block for the row: either hook::begin exited before the print or the row output was lost. The rows use the BG_STUB_FILE reader stub. Root cause has not been reproduced.

    Desired behavior:
    Every begin row yields its expected FILE_DIR/FILE_BASE on every run, on Linux, including under CI-like parallel load.

    Key interfaces:

    • hook::begin (shared hook-utils library): its stdin read and path split.
    • The test suite driver for the begin post-read loop and its BG_STUB_FILE stub.

    Acceptance criteria:

    • Reproduce first: a loop of the suite on Linux (under parallel load like the CI matrix shard) that shows the empty-output failure, with the observed failure rate recorded in the PR.
    • The root cause is named in the PR body, backed by the reproduction.
    • After the fix, the same loop runs the same number of iterations or more with zero failures, and the full hook-utils suite passes.
    • If the fix is in hook::begin, no other suite that sources the shared library regresses.

    Out of scope:

    • Rewriting unrelated cases in the suite.
    • CI retry or rerun logic that masks the flake instead of fixing it.
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

    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions