A rule may say or, once - #484
Merged
Merged
Conversation
WaylandYang
force-pushed
the
feat/a-rule-is-an-edge
branch
from
September 8, 2026 03:15
4e1b4b8 to
c244bc3
Compare
WaylandYang
force-pushed
the
feat/a-rule-may-say-or
branch
from
September 8, 2026 03:15
67c9f14 to
2aace5e
Compare
WaylandYang
force-pushed
the
feat/a-rule-is-an-edge
branch
from
September 8, 2026 03:53
c244bc3 to
154ec34
Compare
WaylandYang
force-pushed
the
feat/a-rule-may-say-or
branch
from
September 8, 2026 03:53
2aace5e to
2829f86
Compare
WaylandYang
force-pushed
the
feat/a-rule-is-an-edge
branch
from
September 8, 2026 04:10
154ec34 to
38d1115
Compare
WaylandYang
force-pushed
the
feat/a-rule-may-say-or
branch
from
September 8, 2026 04:10
2829f86 to
2613d6a
Compare
WaylandYang
force-pushed
the
feat/a-rule-may-say-or
branch
from
September 8, 2026 04:41
2613d6a to
5127dd4
Compare
WaylandYang
force-pushed
the
feat/a-rule-is-an-edge
branch
from
September 8, 2026 04:41
38d1115 to
4671d37
Compare
WaylandYang
added a commit
that referenced
this pull request
Sep 8, 2026
Three records were written as 0026-0028 on three branches on the same day. By the order the pull requests were opened, the adjudication stack (#473-#475) keeps 0026-0028, the rules stack (#484, #485) becomes 0029 and 0030, and the event record (#487) becomes 0031. Signed-off-by: WaylandYang <wayland0916@gmail.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
WaylandYang
force-pushed
the
feat/a-rule-may-say-or
branch
from
September 8, 2026 05:03
5127dd4 to
ea36c26
Compare
WaylandYang
force-pushed
the
feat/a-rule-is-an-edge
branch
2 times, most recently
from
September 8, 2026 05:08
6c67fdb to
ac19eca
Compare
WaylandYang
force-pushed
the
feat/a-rule-may-say-or
branch
2 times, most recently
from
September 8, 2026 05:12
8b9509a to
3219159
Compare
WaylandYang
force-pushed
the
feat/a-rule-is-an-edge
branch
2 times, most recently
from
September 8, 2026 05:18
4f2b54d to
769f376
Compare
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: WaylandYang <wayland0916@gmail.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
WaylandYang
force-pushed
the
feat/a-rule-may-say-or
branch
from
September 8, 2026 05:21
3219159 to
e78ec78
Compare
This was referenced Sep 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #476. Stacked on #483. Decision record:
docs/decisions/0026-a-rule-may-say-or-once.md.A criterion is rarely one pattern. A gas-bearing well is one whose total hydrocarbon is above 8 and whose interpretation reads as a gas anomaly — or one whose composite interpretation already says gas-bearing. Until now that was two rules, two names, the same conclusion, and nothing in the base saying they were one criterion: delete one and the other keeps firing.
The shape
A condition carries a group. Conditions in a group are joined with
and; groups are joined withor.(A and B) or (C), one level, no nesting.That is not a concession to keep the editor simple — it is the shape the evaluator already has. A hit does not report "true", it reports which facts made it true and the interval on which they all hold; getting there means walking the cartesian product of the per-condition matches and intersecting their intervals, which is a conjunction. Running that once per group keeps every property it has. An arbitrary and/or/not tree would have to answer "what are the premises of a disjunction", and neither answer is good: the fired branch's premises are what groups already give without the tree, and all of them would attach a conclusion to readings that had nothing to do with it.
What changed
0039addsgroup_seq; existing conditions default to group 0, so every rule keeps its exact meaning. The unique key becomes(rule_id, group_seq, seq). (Numbered 39, not 38 — another branch owns 38 in the shared dev database.)(rule, entity)pair once. Two groups true on the same interval are one conclusion, keeping the premises of the first group in group order so the proof is stable across runs.not_injoins the ops. It reads a value that is there and asks whether it falls outside a set, so it has a premise and an interval like any other condition. "This entity has no such attribute at all" is deliberately not here — it has no premise, so nothing could ever retire it, and the base is open-world: a missing reading means nobody wrote it down.groupon a condition, defaulting to 0 — a caller that sends a flat list still sends one conjunction.andat the head of the row, blocks divided by a rule and the wordor, one button per block to add a row and one at the bottom to add a block. Deleting a block's last row takes the block with it, so no block is ever empty except the first one before anything is written — an empty conjunction is true of everything and there is no state in which one can be saved. Blocks are not boxed; the connectives already say how far a block reaches.A and B or C.Tests
Four evaluator tests (either group fires and carries only its own premises; two groups on one interval are one hit; a capped group does not stop the other;
not_inneeds a reading to be true) and one database test that a rule with two groups names only the premises of the group that fired. Verified end to end against a running stack: a three-block rule written in the dialog stores0,0,1,2and reads back with bothors in the sentence.Chaining — a rule reading what another rule concluded — is #477 and is not this.
🤖 Generated with Claude Code