8000 fix(rules): stratify a rule above a not/or rule it calls (#628) by adityamukho · Pull Request #631 · project-minigraf/minigraf · GitHub
[go: up one dir, main page]

Skip to content

fix(rules): stratify a rule above a not/or rule it calls (#628) - #631

Merged
adityamukho merged 2 commits into
v3from
fix/628-mixed-rule-stratum
Oct 19, 2026
Merged

adityamukho merged 2 commits into
v3from
fix/628-mixed-rule-stratum

Conversation

@adityamukho
@adityamukho adityamukho commented 8000 Oct 19, 2026
Copy link
Copy Markdown
Collaborator

For #628.

Problem

StratifiedEvaluator::evaluate runs a stratum's positive-only rules to a fixpoint, then each rule with not / not-join / or / or-join once. stratify() gave a positive dependency the callee's stratum, so a rule calling such a rule ran before any of the callee's rows existed and returned too few rows, often none. When the caller had its own not/or, all_preds order decided, so asking for the callee first in the query changed the answer.

Fix

A positive edge to a predicate with a mixed rule now needs dep_stratum + 1, like a negative edge, unless the callee reaches the caller. In that case (recursion through a mixed rule) both stay in one stratum, so no rule set accepted before is now rejected with INT-054. has_mixed_clause is shared with the evaluator's partition.

Not covered: recursion through a mixed rule

A mixed rule still runs once per stratum, so recursion through one, directly (reach calling itself with a not in the body) or mutually (p calls mixed q, which calls p), gives incomplete results today. A 5-node chain returns 7 of 10 reachability rows. This PR doesn't change that, and it isn't a regression. It needs a fixpoint loop over the stratum with deduplicated mixed-rule output, which is a separate issue.

Tests

  • tests/not_join_test.rs: four A rule calling a rule with not / not-join returns too few rows #628 tests (a rule calling a not-join rule with a free and a literal argument and through a forwarding rule; a not callee; a mixed caller with the callee asked first or not; a rule calling an or rule). All four fail on v3.
  • Stratification unit tests: a caller and a forwarding rule sit above the mixed callee; recursion through a mixed rule still stratifies.
  • cargo test: 1588 passed, 0 failed, 10 ignored. cargo clippy --all-features and the wasm32 browser clippy are clean.
  • Codex review: no new INT-054 rejections and no ordering gaps for mixed callers, or-branch invocations or several rules per predicate. Its one finding is the recursion case above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PtCdzbJMSS1V8qEPaJ4jXz

StratifiedEvaluator runs a stratum's positive-only rules to a fixpoint,
then each rule with not / not-join / or / or-join once. stratify() gave a
positive dependency the callee's stratum, so a rule calling a mixed rule
ran before any of the callee's rows existed and returned too few rows,
often none; a mixed caller ran before or after its callee depending on
all_preds order.

A positive edge to a predicate with a mixed rule now needs dep_stratum + 1,
like a negative one, unless the callee reaches the caller: recursion
through a mixed rule stays in one stratum and is not rejected as
unstratifiable. has_mixed_clause is shared with the evaluator's partition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtCdzbJMSS1V8qEPaJ4jXz
@codecov
codecov Bot commented Oct 19, 2026
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Covers reaches() revisiting a predicate; the stratification coverage
gate is 100%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtCdzbJMSS1V8qEPaJ4jXz
@adityamukho
adityamukho merged commit 224c290 into v3 Oct 19, 2026
25 checks passed
@adityamukho
adityamukho deleted the fix/628-mixed-rule-stratum branch October 19, 2026 16:32
adityamukho added a commit that referenced this pull request Oct 19, 2026
Backport of #631. StratifiedEvaluator runs a stratum's positive-only
rules to a fixpoint, then each rule with not / not-join / or / or-join
once. stratify() gave a positive dependency the callee's stratum, so a
rule calling a mixed rule ran before the callee's rows existed and
returned too few rows, often none.

A positive edge to a predicate with a mixed rule now needs
dep_stratum + 1, unless the callee reaches the caller: recursion through
a mixed rule stays in one stratum (#633) and is not rejected.


Claude-Session: https://claude.ai/code/session_01PtCdzbJMSS1V8qEPaJ4jXz

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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

0