feat: merge records a conditional fact instead of applying it - #54
Open
ShocOne wants to merge 1 commit into
Open
feat: merge records a conditional fact instead of applying it#54ShocOne wants to merge 1 commit into
ShocOne wants to merge 1 commit into
Conversation
Phase 7.4, step one. The guard that closes the class of bug this phase exists for. Behaviour is unconditional by construction: one Writable, one ReturnedOnRead, one RejectedValues per attribute. Writing a fact that holds only under a precondition into any of those turns it into a claim about every case. That is exactly how the pilot came to suppress matchType's read-back for every tag on the strength of an observation about static ones, and how endpoint-agent came to sit in objectType's rejected set. So a fact with a precondition goes into the description with its condition stated first, and nothing generates from it. Both halves are load-bearing: applying it is the bug, and dropping it silently would lose evidence somebody paid a live run for. The guard sits immediately after the suspected-facts guard, for the same reason and in the same shape -- both are "this fact is not strong enough a claim to put in the schema", differing only in why. Result gains Conditional alongside Ignored rather than reusing it. Ignored would be the wrong word: these facts are strong enough to act on and were withheld because the schema cannot express the condition, not because the evidence was weak, and somebody deciding whether to trust a schema needs to tell those apart. The condition reads first in the prose, because the claim is wrong without it: "matchType is not returned on read" is false, and "when objectType is endpoint-agent, matchType is not returned on read" is true. Four tests, driven through Apply rather than the internal helper. The control matters as much as the subject: the same fact without a condition still reaches Behaviour, so the suite cannot pass because merge quietly stopped applying returnedOnRead altogether. Both branches of one gate are recorded, because an attribute whose description carries only one reads as though that branch were the whole truth -- which is where this started. And a second merge changes nothing, which merge -check depends on. Mutation tested: disabling the guard fails two tests, the second with "neither branch may win: false" -- one branch silently winning, which is the original bug reproduced exactly. Step two, Behaviour holding conditional variants so emission can act on them, waits for the re-record: there is nothing conditional in the committed facts yet to shape it against, and designing the storage before seeing the data is how the unconditional model got written in the first place. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Phase 7.4, step one — the guard that closes the class of bug this phase exists for.
The problem, precisely
Behaviouris unconditional by construction: oneWritable, oneReturnedOnRead, oneRejectedValuesper attribute. Writing a fact that holds only under a precondition into any of those turns it into a claim about every case.That is exactly how the pilot came to suppress
matchType's read-back for every tag on the strength of an observation about static ones, and howendpoint-agentcame to sit inobjectType's rejected set.The fix
A fact with a precondition goes into the description with its condition stated, and nothing generates from it.
Both halves are load-bearing. Applying it is the bug. Dropping it silently would lose evidence somebody paid a live run for.
The guard sits immediately after the suspected-facts guard, in the same shape and for the same reason — both say "this fact is not a strong enough claim to put in the schema", differing only in why.
ResultgainsConditionalalongsideIgnoredrather than reusing it.Ignoredwould be the wrong word: these facts are strong enough to act on and were withheld because the schema cannot express the condition, not because the evidence was weak. Somebody deciding whether to trust a schema needs to tell those apart.The condition reads first in the prose, because the claim is wrong without it:
Four tests, and the control matters as much as the subject
Driven through
Applyrather than the internal helper.Corroboratedconditional fact — deliberately strong, so the test cannot pass because it was too weak — does not reachBehaviour, and does reach the description with its condition.Behaviour. Without this, the suite would pass if merge had quietly stopped applyingreturnedOnReadaltogether — a different bug wearing the same green tick.merge -checkdepends on.Mutation tested: disabling the guard fails two of them, the second with
neither branch may win: false— one branch silently winning, the original bug reproduced exactly.Step two is deliberately not here
Behaviourholding conditional variants, so emission can act on them, waits for the re-record. There is nothing conditional in the committed facts yet to shape the storage against — and designing the storage before seeing the data is how the unconditional model came to be written in the first place.Verification
go test ./...probe -mode verifymerge -checkverifygofumpt -l ./golangci-lint🤖 Generated with Claude Code