Skip to content

mcpx hooks (#2541 follow-up): bound descendant processes on timeout, cap retained output, count bus-level drops, real interpreter readiness — plus CI-only internal/hooks failure #2573

Closed

Description

@dezren39

Follow-up to #1872 / PR #2541 (merged 2026-10-30, merge commit 1aef00e). The PR merged with 4 Codex review findings undispositioned (review 2026-10-30T03:27:58Z by chatgpt-codex-connector[bot]) and a red basic: test run. Filing per the Codex-findings gate so none of them evaporate.

Codex findings to fix (all in the merged hooks implementation)

  1. P1 — pkgs/mcpx/internal/hooks/runner.go:187 Bound descendant processes and output-pipe waits. CommandContext kills only the direct child; descendants can hold stdout/stderr pipes open and keep cmd.Run() waiting for EOF indefinitely — so the hard timeout does not actually bound a hook that spawns children, contradicting mcpx: config-declared hooks over the event bus, running any command, JS/TS or Python module #1872'''s acceptance "a hanging hook cannot hang the daemon" for that case. Fix direction: process-group kill and/or bounded pipe draining.
  2. P2 — runner.go:86 Account for event losses before per-hook fanout. The shared bus subscription can overflow before events reach per-hook queues; Subscription.Dropped is never read, so Stats.Dropped under-reports and the gap contract (Bump build/buck/preludes/buck2-prelude from 3a02ea3 to 4371899 #6) is not honoured for bus-level drops.
  3. P2 — runner.go:185 Cap retained hook output. Both output streams accumulate unbounded in daemon memory, including successful runs whose output is discarded (a yes hook can allocate heavily inside the 2s default timeout). Cap and truncate.
  4. P2 — pkgs/mcpx/internal/cli/hook.go:93 Check interpreter availability before marking a module ready. A declared Python module with neither python3 nor uv on PATH still reports ready in mcpx hook ls / doctor, then fails on every matching event. Readiness must check the interpreter, not just the file.

CI-only internal/hooks failure

PR #2541'''s basic: test (run 40997046260, head eb4cabc) failed internal/hooks in 0.159s (the internal/defaults/internal/settings failures in the same run are the pre-existing doc-drift reds tracked in #2552). Reproduction attempt 2026-10-30 (queue task 3097, Lane D): go test ./internal/hooks/ -count=1 on the laptop at the exact merged commit eb4cabc passes 11/11 tests. The workflow log prints only package-level output (per-test JSON is filtered out), so the failing test is not identifiable from CI logs. Investigate: likely environment- or timing-sensitive (candidates: TestTimeoutCutsHangingHookAndPublishProceeds under runner load, or an executor-availability assumption). Consider surfacing per-test failures in the mcpx workflow log so this class is diagnosable.

Acceptance

  • All 4 findings fixed with tests (descendant-spawning hanging hook is cut at timeout; bus drops counted; output capped; hook ls/doctor report unready when the interpreter is missing).
  • go test ./internal/hooks/... green in CI on the fixing PR.
  • Findings dispositioned on PR mcpx: config-declared hooks over the event bus (#1872) #2541 threads pointing here.

Acceptance criteria

  • Timeout handling kills the hook's whole process group (or equivalently bounds pipe draining): a hook whose descendants hold stdout/stderr open cannot keep cmd.Run() waiting past the timeout
  • Bus-level subscription drops are accounted: Subscription.Dropped is read and reflected in Stats.Dropped
  • Retained hook output is capped per run with truncation, for both streams, including successful runs
  • mcpx hook ls / doctor readiness for a declared Python module checks interpreter availability (python3 or uv on PATH), not just the file
  • The CI-only internal/hooks failure from PR mcpx: config-declared hooks over the event bus (#1872) #2541's run 40997046260 is identified (named test + mechanism) or per-test failure output is surfaced in the mcpx workflow so it becomes identifiable
  • Existing hooks tests pass; new regression tests pin the descendant-timeout and output-cap behaviour

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    priority/normalOrdinary priority (the default)
    effort/mMedium: expected under 1 day of work
    app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)
    source/queue-workerFiled or worked by the queue/worker pilot
    queue/queuedHas a queued task in the Supabase agent queue
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Oct 30, 2026
  2. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    Intake review

    Still live: follow-up to merged PR #2541 (#1872) — the four Codex findings are on code that is now on main, verified undispositioned at filing; a fix task is already queued (task 3823, enqueued by the lane that filed this). The CI-only internal/hooks failure is a fifth, separate thread in the same issue: it passes 11/11 on the laptop at the exact merged commit eb4cabc, so it is environment/timing-sensitive until proven otherwise.

    Related: #1872 (origin), PR #2541 (merged 1aef00e), #2552 (the pre-existing defaults/settings doc-drift reds in the same CI run — explicitly NOT part of this issue).

    Notes / risks: finding 1 (descendant processes) is the P1: it negates the timeout guarantee #1872's acceptance promised. Findings 2–4 are P2 but each is small and localised in internal/hooks/runner.go / internal/cli/hook.go. The CI-only failure should not block the four findings; if it cannot be reproduced, surfacing per-test JSON in the workflow is an acceptable resolution for that thread.

    Suggested approach: one PR for findings 1–4 with regression tests (process-group kill pattern already used elsewhere in the fleet), and a separate small look at the CI failure's timing sensitivity.

  3. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 30, 2026
  4. 16 remaining items

  5. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  6. chatgpt-codex-connector commented on Oct 30, 2026

    @chatgpt-codex-connector
  7. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Oct 31, 2026
  8. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  9. added a commit that references this issue on Oct 31, 2026
  10. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

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

Metadata

Metadata

Assignees

Labels

app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)effort/mMedium: expected under 1 day of workkind/bugSomething isn't working (prefixed form of the classic bug label)meta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/queue-workerFiled or worked by the queue/worker pilot

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions