Skip to content

chore(ts): pick fixture cases from one list, and target lang's by name - #164

Merged
kixelated merged 15 commits into
mainfrom
quest/m2/ts-harness-names
Oct 28, 2026
Merged

kixelated merged 15 commits into
mainfrom
quest/m2/ts-harness-names

Conversation

@kixelated

@kixelated kixelated commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Fixture harnesses dispatch by hand-numbered match op % N, and lang's caller.ts and differential.ts's wide sweep target cases by those numbers. Every concurrent ts PR collided on the numbers and on N, and one collision routed durations' targeted cases to another module.

Approach

  • Each harness picks its case from one list, cases[op % cases.len()], so the count follows the list and a case appended at the end moves no other.
    • lang: harness::cases() lists (name, fn) pairs. A new root, harness::op(name), returns a case's first byte, and caller.ts targets every case by name.
    • codec: harness::cases() lists its fns. Nothing targets them, so they carry no names.
    • task: harness.rs's steps() and tests/task.ts's steps list named steps in the same order. Its scripts are written by step name (script(["open", 0], ["sum", 0], ...)), and unwind.ts draws ops from steps.length, not 13.
  • The wide sweep was lang-only code in the generic differential.ts. It moves to caller.ts as ints(), using names, which drops differential.ts's wide argument and fixtures.rs's extra parameter.
  • differential.ts appends a harness's cases in a loop: spreading lang's named cases, which now include the sweep, into push overflows the stack.

Coverage is unchanged. Every list keeps the old order, so each first byte picks the same case. The sorted, deduplicated (input, native outcome) set's sha256 matches main's at 5e6e7db for lang (481488 cases), codec (34464), and task (34720), and unwinding draws ops from the same 15 steps. Merging main brought in #124's wrappers, edits, edited step, and wide sweep changes, #159's utf8::decodes case, #166's helpers step (its scripts are now written by name), and #165's floats::floats case, all appended to the lists. #165's within tolerance now finds the floats case by name and the case count, not % 59 !== 58.

The list is built per call, in a function: the translator can't read fn pointers out of a const ("has no value tree"). This doesn't cost speed: lang's differential run took 22s against main's 44s locally, over repeated runs. Codec's time is unchanged.

Choices made without asking:

  • Names are the called path (ints::u8_op, durations::durations), unique by construction. ints::neg and ints::cast are small helpers in harness.rs that wrap what the old match arms did inline.
  • The old order is kept, with new cases appended at the end, so the random run and the full-width op 0..8 loop reach exactly what they did. Sorting by name would make concurrent appends merge without a textual conflict, but it would reshuffle which cases that loop reaches. Two appends still conflict on adjacent lines, and the fix is to keep both; nothing gets renumbered.

Impact

None: test fixtures and test runners only. lang's ts.toml gains the root harness::op, so its snapshot gains cases and op.

Alternatives

  • A macro that generates both a NAMES const and an index-guarded dispatch: no runtime list, but more code than a plain vec!.
  • Translator support for fn pointers in const allocations, which would let the list be a const. That is a translator feature with no consumer outside this harness, so it isn't worth the work here.

Follow-ups

  • None required. If a stock crate ever needs fn-pointer tables in a const, the translator rejects them loudly ("no value tree"). That would be a quest of its own.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

@kixelated kixelated changed the title Fixture cases by name test(ts): pick fixture cases from one list, and target lang's by name Oct 28, 2026
@kixelated kixelated changed the title test(ts): pick fixture cases from one list, and target lang's by name chore(ts): pick fixture cases from one list, and target lang's by name Oct 28, 2026
@kixelated
kixelated marked this pull request as ready for review October 28, 2026 08:22
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-28T12:07:31.992657Z eab0399 New commits
🔒 Security Review ✅ Completed 2026-10-28T12:10:08.864033Z eab0399 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed commit: 53afa68

No actionable bugs found. I checked the old dispatch order against the new lang/codec lists, the extracted neg/cast behavior, task step and named-script parity, and the relocated wide-integer sweep and runner wiring. The existing case mappings and boundary inputs appear preserved.

Direction: deriving dispatch counts from the lists and resolving targeted lang cases by name removes the fragile duplicated numbering. Keeping the sweep with its fixture is simpler than a fixture-specific flag in the generic runner; the plain function tables are proportionate, without adding translator machinery. Task's Rust/TypeScript step lists still deliberately require matching order.

Verification limits: GitHub-only static review of the diff, generated snapshots, and relevant surrounding code; I did not execute type checks, differential tests, or unwind tests, or independently reproduce the reported coverage hashes.

kixelated and others added 4 commits October 28, 2026 01:48
…ames

# Conflicts:
#	ts/fixtures/lang/expected/harness.ts
#	ts/fixtures/lang/src/harness.rs
#	ts/fixtures/task/src/harness.rs
#	ts/tests/differential.ts
#	ts/tests/task.ts
#	ts/tests/unwind.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated and others added 5 commits October 28, 2026 04:40
# Conflicts:
#	ts/fixtures/lang/caller.ts
#	ts/fixtures/lang/expected/harness.ts
#	ts/fixtures/lang/src/harness.rs
# Conflicts:
#	ts/fixtures/task/src/harness.rs
#	ts/tests/fixtures.rs
#	ts/tests/task.ts
#	ts/tests/unwind.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary: main merged three times, conflicts resolved by hand, and each concurrent case or step appended to the named lists:

Checks: just ts test and just check pass locally. The sorted (input, native outcome) set's sha256 is identical to main at 5e6e7db for every differential fixture: lang 481488, task 34720, codec 34464, plus share and bind. Codex reviewed head eab0399 with no findings, and CI passed.

(Written by Claude Opus 5.5)

@kixelated
kixelated merged commit 2a76782 into main Oct 28, 2026
1 check passed
@kixelated
kixelated deleted the quest/m2/ts-harness-names branch October 28, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant