Date: 2026-07-10. Status: PLAN (written during a network outage on a
rolled-back container; baseline numbers are from the tableau landing
report of the same day, branch worktree-tableau-refute commit
4d04cc8, pushed to origin — re-verify against
docs/test-results/latest.json once the landing merges).
Owner goal (2026-07-10 /goal): level up implementation + npm FP JS
API + hub docs for OWL2 DL/tableau to complete coverage.
Update 2026-07-14 (obsolescence sweep): five tableau waves landed
since the baseline below — datatype facet satisfiability, role box
(subPropertyOf/FunctionalProperty/transitive), contrapositive
unfolding of definitions + exact-cardinality-0 NNF, SHIQ ≤-rule
witness merging, and named-individual identification + stored FP
max-1 bounds. Current measured scores: type-inconsistency (DL) 110
pass, 18 fail (out of 128 scored); type-consistency (DL) 334 pass, 18
fail (out of 352). Soundness gate held throughout: exactly one
unexpected-inconsistency (WebOnt-miscellaneous-202, pre-existing,
tcon only). See docs/claude-rules/current-state.md and
w3c-completeness-ledger.md for the current snapshot; the wave
letters actually landed (datatype facets / role box / contrapositive /
≤-rule / named-merge) diverge from the A–E plan below — treat the plan
as the historical starting point, not the executed sequence.
All DL-regime numbers from the rebuilt binaries of the tableau landing:
unexpected-inconsistency
(WebOnt-miscellaneous-202, pre-existing, #236 territory).Tableau.Refute.fst (~1050 lines, verified, zero admits/assume vals)
implements: NNF, lazy TBox unfolding, index-ordered disjunction
branching under a threaded linear budget, depth-capped existential
witnesses, and clash rules for complement/boolean, min/max cardinality
(incl. qualified), differentFrom-backed counting, self-disjoint
properties, Bottom/Top property assertions, AllDifferent, rdf:nil
structure, and hasSelf+disjointness.
O-rule (x : {a} implies
x = a) and its interaction with counting. Plan: represent nominal
membership as a merge constraint; reuse the existing
differentFrom-aware counting for the clash side. No full equality
saturation — merge classes lazily, as the RL closure already
maintains a sameAs partition we can consult.XSD.Datatypes.fst already carries lexical + value-space checks
for the base types; the missing piece is a facet-satisfiability
checker over value-space intervals (rational endpoints, open/closed)
FACTOIDAL_OWL_REFUTE_FUEL selectively? No — first profile which
tests exhaust budget and whether ordering heuristics (clash-first
branch ordering, unit propagation before split) shrink the search.
Only then consider budget raises, measured.dl-502,
once filed here as a budget-out, was re-diagnosed as
encoding-not-loaded (multiply-defined owl:oneOf never materialised;
Tableau.fst:303 first-oneOf-only + no OWL.Closure oneOf
rule) — it needs a loader/closure change (F1) + nominal
identify-branching (F2), not fuel tuning. See
w3c-completeness-ledger.md § "dl-502 nominal-DPLL wave".Each wave: fail-set diff (names, not counts), floors (SPARQL 631/0, RDF 1031/0, RIF 46/1/3, ShEx-neg 100/0), and the one pre-existing WebOnt-202 soundness exception must stay exactly one.
Expose reasoning to the bundle per the engines pattern (typed fn.*):
fn.owlIsConsistent(ontologyTtl, opts?) -> {consistent: boolean|null, reason?: string}
(null = budget-out, reason names the cap — never a silent false).fn.owlEntails(premiseTtl, conclusionTtl, opts?) -> {entailed: boolean|null, via: "closure"|"refutation"}.fn.owlClassify(ontologyTtl) — subsumption pairs from the closure
(already computable via RL rules; label it RL-closure-based, not DL-complete,
until refutation-backed classification exists).null.Post 30 ("OWL reasoning by model construction: the tableau") gains
live cells: a textarea ontology cell -> fn.owlIsConsistent verdict
cell -> a rendered clash-trace summary (the refuter's reason string),
plus canned examples per clash family (the corpus's spirit, original
data). Live cells call fn.* only; bundle rebuild with npm-entry forced;
tests/hub/post30* extended. Anti-pattern #28 applies.
Waves land sequentially onto claude/main (no long-lived stack), each via the dedicated-landing pattern if its base drifts. The npm/hub tracks branch after Wave A and land independently. All scores labelled per anti-pattern #25; dashboard rows via the normal generate-report path.