Skip to content

Phase 2: the model: TestSpace, rules, feasibility - #53

Merged
adolgert merged 30 commits into
feature/one-ohfrom
feature/phase2-model
Oct 3, 2026
Merged

adolgert merged 30 commits into
feature/one-ohfrom
feature/phase2-model

Conversation

@adolgert

Copy link
Copy Markdown
Owner

Phase 2 of design/20260926_implementation_plan.md, stacked on #52 (retarget to release/1.0 after it merges). Review note with transcript, numbers, pending tests, and open decisions: design/phase2_review.md.

  • TestSpace, Invalid, Partition, value identity, negative-row rule selection (src/space.jl).
  • Constraint, forbid/require in pattern, named, and whole-case forms, @forbid/@require, tabulation into RuleTables with a lazy fallback (src/constraints.jl, src/rule_table.jl).
  • Index-space feasibility: backtracking with forward checking over connected components, witness caches, an exact node budget that returns unknown and never memoizes an exhausted search, deletion search for implied exclusions, ResourceLimitError (src/feasibility.jl).
  • Public isallowed, explain, and an unexported classify (src/explain.jl).
  • The != rule that 0.4 silently over-forbade now forbids exactly two pairs; the solver example gives 3 direct and 2 implied exclusions by name.
  • classify and the valid-row sets agree with the independent checker on every fixture and on random problems; 12 Phase 2 pending tests flipped on.

Full suite: 332,527 pass, 31 broken/skipped (all deliberate, Phases 3–6), 0 failures. Aqua green. Model tests also pass on Julia 1.10.

🤖 Generated with Claude Code

adolgert and others added 5 commits September 26, 2026 21:10
…lity

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…abulation

The model layer of the 1.0 contract: a TestSpace validates names and
domains by value identity, holds Constraints built from patterns, named
predicates, whole-case predicates, or @forbid/@require, and tabulates
each rule into a RuleTable over ordinary values, lazily above
tabulation_limit. Negative-row rule selection is active_tables.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tial

Backtracking with forward checking over connected components, per-component
witness caches, a node budget that returns unknown and never memoizes an
exhausted search, deletion search for implied exclusions with a separate
explanation budget, and ResourceLimitError.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
src/explain.jl builds the ordinary or negative-row search for an
assignment, maps rule numbers back to constraint positions, and prints
one sentence per outcome. The checker adapter test_space moves into the
shared Checker test module, the 12 Phase 2 pending lines become real
tests, and test_explain.jl cross-checks classify against the checker on
every fixture and 100 random problems. to_indices is renamed
case_indices to avoid shadowing Base.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…emantics

Legacy generation rejects Invalid and Partition values until Phase 6, and
two-domain full_factorial no longer hits a MethodError. The macro walker
scopes ->, let, generators, comprehensions, and do blocks with Julia's
rules and rejects other binding forms with a pointer to the function
form. The contract states that the node budget does not count rule
checks, results report nodes and checks, and a lazy rule's memo is
documented as space-owned tabulation with memo_size to measure it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@adolgert

Copy link
Copy Markdown
Owner Author

Review round 1 applied (see the "Review round 1" section of design/phase2_review.md): wrapper guard on legacy generation (plus a two-domain full_factorial MethodError found on the way); macro walker rewritten with Julia scoping for ->, let, generators, comprehensions, and do, other binding forms rejected with guidance; contract §3.3 now states what a node bounds and results carry nodes/evaluations; §12.19 and §3.5 distinguish the space-owned lazy memo from per-call search caches, with memo_size and a Phase 3 memory measurement.

Full suite: 334,312 pass, 31 broken/skipped (unchanged pending lines), 0 failures.

🤖 Generated with Claude Code

adolgert and others added 4 commits September 27, 2026 09:38
request.jl is the second index-space boundary: a Request validates
strength, stronger groups, and must-include rows against the space,
exposes dead() and witness() to the engines, classifies every target with
attribution, and validate_design certifies a result. GND now takes a
fixed default seed and candidates, with M deprecated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…llow

generate(::IPOG, request) classifies every target, covers exactly the
required ones, and certifies the result. The three IPOG sites use dead()
instead of disallow, and ipog_multi_way keeps rows full width so a value
set for one stronger group is visible to the next, which fixes invalid
rows with overlapping groups. The positional interface routes through
Request; disallow, Counter, generate_tuples, and the nothing sentinel are
gone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…layer

GND builds each case from candidates checked with dead(), and when no
candidate covers anything it builds the next case from the first
uncovered target, so it always terminates. Excursions take an explicit
base, drop and report dead rows, and reject a forbidden base by rule.
Full factorial refuses a product above the limit before enumerating and
retains only accepted rows through an in-place odometer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Both engines pass 500 pairwise and 500 three-way random problems, each
design certified by the independent checker, and every Phase 3 fixture
test is live. A limited search raises ResourceLimitError during
classification or placement and never returns an incomplete design.
benchmark/run.jl records the baseline against 0.4 in
design/benchmark_results_phase3.md. Docs examples that passed disallow
are plain code blocks until Phase 7.

Closes #51.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
adolgert and others added 17 commits September 27, 2026 13:56
per-request lazy memo, index-space validation, CI benchmark job

Excursions take one distance (zero allowed) and reject stronger groups.
Excluded records which limit stopped an explanation and an infeasible
must-include row's error carries its rules. A lazy rule's memo now lives
in the operation's Feasibility, so a TestSpace retains nothing from
generation. validate_design checks index rows directly, making full
factorial on bench12 about 10x faster. CI gains a benchmark job.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
covering, all_values, all_pairs, all_triples, excursions, and
full_factorial accept a TestSpace, a NamedTuple, pairs, or positional
vectors and return TestCases{T}, a read-only vector of typed rows that
records the space, strategy, engine and seed, must-include count, covered
and excluded targets with attribution. show prints only recorded
bookkeeping. all_tuples, n_way, seeds, wayness, the *_excursion names,
and GND(M=) warn through depwarn; Excursion and Counter are gone.
Excursion notes are values, not positions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
exclusion wording, budget docs, strength-0 semantics for Phase 5

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
field types from values, min(2, n) report default, duplicate wording

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
coverage measures any supplied rows against a space, independent of
generator bookkeeping: covered targets need no search, missing ones are
classified with attribution, unknown ones are listed without a
percentage, ordinary and negative parts are kept separate, and rejected
rows contribute nothing. Unconstrained requests no longer materialize
their target list for the certification recount.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
report verifies a result independently of its bookkeeping: a guarantee
line, the excluded list with attribution, bonus coverage at strength + 1,
a prefix curve computed in one pass, and the seed, never printing a
percentage while a target is unresolved. design_sizes runs each strategy
and tabulates cases, share of the valid product, and pairs and triples
covered, recording a resource-limit status instead of a count.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The excursion guarantee exempts must-include rows; report shows its own
freshly verified exclusions and labels recorded proofs as a fallback;
coverage(cases; strength) keeps stored stronger groups unless replaced;
plain() gives a Report, Coverage, or DesignSizes representation with no
executable state, tested by round trip; measurement docstring examples
are doctests with real output. The release is 0.5.0: the maintainer
wants a 0.x version to use before calling anything 1.0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…matrix

Negative targets are classified through the negative-row search and
covered by a sub-request over the other parameters with the same engine,
with separate bookkeeping and a ! marker on negative rows. Must-include,
full factorial, and excursions accept wrappers under their row policies.
realize draws each Partition once under the caller's rng. diagnose ranks
combinations present only in failing cases and groups indistinguishable
ones; followups finds isolating cases or proves there are none.
github_matrix writes a validated GitHub Actions include matrix with
JSON.jl.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
figures, JSON field-name validation

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The docs environment pinned Documenter 0.25, which needs JSON 0.21, while
the package now requires JSON 1, so CI could not resolve it. Documenter 1
makes missing docstrings and unresolved references errors by default;
they stay warnings until Phase 7 completes the manual.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
README and home page lead with the promise, the decision table, and one
example with its printed output. The manual is a tutorial in five levels,
nine how-to guides by job, explanation pages on values and oracles,
interaction coverage and its evidence, constraints, and the engines, a
reference organized by purpose with every exported docstring opening on
the situation it serves, a 0.4 to 0.5 migration table, developer pages,
and a one-pager for AI agents. Doctests run in the docs build and in the
test suite; the build fails on any warning.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
wording, two-check lockfile pattern, badge and contract wording

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Phase 7: documentation and first contact
@adolgert adolgert closed this Oct 3, 2026
Phase 6: Invalid, Partition, diagnose, github_matrix
Phase 4: the public interface and the result type
@adolgert adolgert reopened this Oct 3, 2026
Phase 3: engines that keep the promise
@adolgert
adolgert merged commit 4df1ad3 into feature/one-oh Oct 3, 2026
14 checks passed
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.

1 participant