Skip to content

regression: tracingChannel().traceCallback loses every events.push (test_gap_diagchannel_3082_3084_3085_3086, unnoticed since 2026-07-30) #7521

Description

@proggeramlug

Symptom

test-files/test_gap_diagchannel_3082_3084_3085_3086.ts is a non-snapshot gap
failure on main
— it is in neither test-parity/gap_snapshot.json nor
test-parity/known_failures.json, so nothing records it as accepted.

The #3086 block (tracingChannel(...).traceCallback) produces an empty
events array
:

$ node --experimental-strip-types test-files/test_gap_diagchannel_3082_3084_3085_3086.ts   # 23 lines, exit 0
$ perry test-files/test_gap_diagchannel_3082_3084_3085_3086.ts -o /tmp/dc && /tmp/dc       # exit 0, one blank line where 6 should be

Diff (node < vs perry >), lines 17-22:

< start:{"ctx":true}
< fn args:A,function,B,C
< asyncStart:"cb-value"
< callback:null:cb-value
< asyncEnd:"cb-value"
< end:{"ctx":true,"result":"cb-value"}
---
>

Everything before it matches byte-for-byte, including 3086 ret: target-ret
so traceCallback did invoke target and did return its value. What is
lost is every events.push(...): the four subscriber handlers AND the
events.push("fn args:…") inside target itself. events.join("\n") then
prints one empty line.

That target ran but its own events.push did not land in the array the
console.log reads is the interesting part — it points at the array binding
captured by the traced function, not at the subscriber plumbing.

This is a regression, not a host quirk

I originally filed this (in #7518) as a suspected host-local flake because it
reproduced on clean main. That reasoning was wrong: reproducing on clean main
is evidence of an unnoticed regression, not of a host quirk. Measured on one
host with --profile perry-dev builds of
-p perry -p perry-runtime -p perry-stdlib -p perry-runtime-static -p perry-stdlib-static,
own build at every point:

commit date verdict
17c0ff952 2026-07-30 PASS
c6ed8175d 2026-07-30 PASS
33acba4c1 (main) 2026-08-06 FAIL

So the break is somewhere in c6ed8175d..main. Bisecting that window is the
first step.

Why it went unnoticed

parity (which runs the gap suite) is gated to tag pushes only — see CLAUDE.md,
"Workflow Requirements" — so a gap regression lands on main with no red check
and the tag-time run is far from the commit that caused it. Same mechanism as
#7518.

Repro

perry test-files/test_gap_diagchannel_3082_3084_3085_3086.ts -o /tmp/dc && /tmp/dc
diff <(node --experimental-strip-types test-files/test_gap_diagchannel_3082_3084_3085_3086.ts) <(/tmp/dc)

Node 26.5.1 (the .node-version pin).

Acceptance

test_gap_diagchannel_3082_3084_3085_3086 byte-identical to node with exit 0,
plus the bisected commit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions