Skip to content

feat(t27b): tri t27b reduce -- ddmin fixture reducer, decisions in reduce.t27 (Closes #6445) - #6865

Closed
gHashTag wants to merge 1 commit into
masterfrom
sieve/t27b-reduce-6445
Closed

gHashTag wants to merge 1 commit into
masterfrom
sieve/t27b-reduce-6445

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 6, 2026

Copy link
Copy Markdown
Owner

Closes #6445
Refs #6488 (sieve C3), #6434, #6063

What

tri t27b reduce — the fixture reducer. It shrinks a spec to a minimal
regression fixture with delta debugging (ddmin after Zeller) over top-level
declarations, so every t27b blocker family can carry a 20-line reproduction
instead of a 384-line spec.

Two modes:

  • --family X — keep shrinking while t27c (the reference) passes the
    candidate and t27b's FIRST unsupported construct is still family X;
  • --disagree — keep shrinking while t27c passes and t27b FAILs, MISMATCHes
    or CRASHes (a shared block is not a disagreement).

Where the decisions live

All of them in specs/tri/t27b/reduce.t27, compiled to
gen/c/tri/t27b/reduce.c (L2) and called through ctypes — the same pattern as
specs/tri/t27b/dogfood.t27 / t27b_dogfood.py (#6457):

  • the interestingness table (interesting, startable);
  • the ddmin state machine (running, removal, next_cur, next_gran,
    next_pos, start_gran, chunk_mask, count_bits, span);
  • the budgets (MAX_UNITS = 64, MAX_CANDIDATES = 512, budget_done);
  • the recorded result of a real reduction (constants + test, below).

scripts/tri_loop/t27b.py (owner-approved exception, unmodified policy) keeps
only I/O: unit splitting, running t27c/t27b, a content-hash oracle cache, and
writing the fixture. The cache key carries the oracle binaries' hashes.

The reference predicate (a trap this PR closed)

The first run produced a 21-line fixture that t27c typecheck accepted — but
which referenced undeclared identifiers (GAT_POS), so t27c test-report
said BLOCKED does not compile while still exiting 0 (#6788 made test-report
print BLOCKED instead of a vacuous all-pass). The oracle now requires:
typecheck exit 0 AND test-report exit 0 with no BLOCKED and no FAIL count.
Typecheck alone is not a reference pass.

The recorded run (test recorded_gfternary_reduction)

specs/numeric/gfternary.t27 reduced with --family "type (alias)":
45 units / 384 lines → 5 units / 30 lines in 428 candidates (84 of the 512 budget left),
inside every budget; the fixture's first t27b blocker is still type (alias).
The test asserts the measured numbers, so the done-when cannot drift.

Verified locally: spec 5/5 tests, t27c gen-c regenerated and deterministic,
tri t27b reduce byte-identical on a rerun, negative controls honest
(not-interesting original → exit 3; --disagree on a blocked spec → exit 3;
--budget N stops and says so; >64 units → exit 2), and the five
scripts/ci/test_the_t27b_*.py / test_a_t27b_*.py suites pass.

🤖 Generated with Claude Code

…duce.t27 (Closes #6445, Refs #6488)

specs/tri/t27b/reduce.t27 is the one home of the reducer: the interestingness
table (--family X / --disagree, reference-passes guard), the ddmin state
machine over top-level units (Zeller), the budgets (64 units, 512 candidates),
and the recorded reduction. gen/c/tri/t27b/reduce.c is its t27c gen-c output
(L2). scripts/tri_loop/t27b.py (owner-approved exception) adds the I/O shell:
unit splitting, the t27c/t27b oracles with a binary-hash-keyed cache, and the
fixture writer.

The reference predicate: typecheck 0 AND test-report 0 with no BLOCKED and no
FAIL -- the first run shipped a 21-line fixture reading undeclared consts,
which typecheck accepted and the #6788 test-report calls BLOCKED; typecheck
alone is not a reference pass.

Recorded run: gfternary.t27 --family "type (alias)" 45 units/384 lines ->
5 units/30 lines in 428 candidates (84 of budget left); fixture compiles
(0 tests, 0 FAIL), first t27b blocker still type (alias) at line 29.
Negative controls: uninteresting original exits 3, --disagree on a blocked
spec exits 3, --budget stops and says so, >64 units exits 2. Spec 5/5 tests,
0 vacuous; driver byte-identical on rerun; the five scripts/ci t27b suites pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 6, 2026
@gHashTag
gHashTag force-pushed the sieve/t27b-reduce-6445 branch from df22c52 to c39f5a4 Compare October 6, 2026 15:05
@gHashTag

gHashTag commented Oct 6, 2026

Copy link
Copy Markdown
Owner Author

Closing as a duplicate of #6830, which landed while this implementation was in flight (the cold reduction run alone took ~45 min; #6830 merged 13:26Z, this PR opened ~14:00Z).

The landed version is the better keeper: it reduces at three levels (declarations, statements, expressions) where this one stops at declarations, and its reference guard compiles candidates through t27c's Zig backend, which rejects undeclared identifiers outright — the exact trap this PR's oracle hardened against by parsing test-report output for BLOCKED (bare t27c typecheck accepts undeclared identifiers, and #6788 made test-report print BLOCKED while still exiting 0). Two implementations would give one command two homes; keeping theirs.

For the record, this run reached the same endpoint on the same target: specs/numeric/gfternary.t27 --family "type (alias)" shrank 45 units / 384 lines to 5 units / 30 lines in 428 candidates — the family fires on the alias use in a signature, not on the bare alias.

@gHashTag gHashTag closed this Oct 6, 2026
@gHashTag
gHashTag deleted the sieve/t27b-reduce-6445 branch October 6, 2026 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

t27b: automatic reducer for blocked and disagreeing specs (tri t27b reduce)

1 participant