D-MCAL-4: domain evidence routes the phase DAG without MUL ground - #1068
Conversation
Discharges F-MUL-1 (consent veto) and F-MUL-2 (evidence contradiction). Two methods on an existing enum, no type minted: KanbanColumn::advance() -> forward successor (first non-Prune) KanbanColumn::veto() -> Prune iff a legal successor (Libet free-won't) `advance_on_gate` now delegates to both, so exactly one copy of the DAG routing rule survives and callers that genuinely hold a MUL assessment — `gate_decision_i4`, the supervisor's cycle driver — are unaffected. The gap being closed: before this, the only route into the phase DAG was `advance_on_gate(&GateDecision)`, whose `Block` and `Hold` variants require a `TrustTexture` AND a `FlowState`. A domain that measures neither had to invent both, and the two measured external producers did: ada-rs's consent veto, and medcare-first-thought's evidence contradiction at four sites. Since the routing never read those coordinates — pinned in D-MCAL-3 by `f_mul_4_routing_ignores_the_calibration_payload` — naming the transition directly loses nothing and fabricates nothing. D-MCAL-5's prohibition is respected. These are transitions named as transitions, not a new verdict vocabulary, so no fourth gate enum joins the three that already exist. "Stay put" needs no symbol: it is `None`. Anti-vacuity is satisfied mechanically rather than by assertion. The falsifier file, compiled unchanged against `main`, fails with `no method named veto` and `no method named advance` — the red state in its strongest available form: on main there is no route into the DAG that does not construct MUL ground. +9 tests in tests/d_mcal_4_domain_evidence.rs. Each case models the external producer's real shape (ada-rs's ConsentLevel; MedCare's NARS expectation plus supporting/contradicting cardinality) and asserts three things: the route is correct, no `GateDecision` is constructed anywhere in the domain path, and the route is IDENTICAL to the fabricating path it replaces — the last being F-MUL-5's premise, that removing the fabrication costs no behaviour. Each domain axis exercises advance / stay / veto so no single arm can pass by accident, non-finite expectations refuse to route rather than falling through a NaN comparison, and the two primitives are checked to stay inside the DAG and to not collapse onto each other where both edges are legal. 1221 lib + 56 integration tests green; clippy --all-targets and fmt clean. Board hygiene in the same commit: LATEST_STATE inventory delta, STATUS_BOARD row, INTEGRATION_PLANS prepend, supersession index regenerated last. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKHLL6NTnRr1XGvKFA1j2L
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_732e0a5e-2fa1-4abf-8563-d2660d67fed7) |
…n-evidence # Conflicts: # .claude/board/SUPERSESSION-INDEX.md
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b0ad5d681b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| //! Measured on `main` before this change | ||
| //! (`.claude/plans/mul-consumer-census-v1.md` §3), the only route into the | ||
| //! kanban phase DAG was `advance_on_gate(&GateDecision)`, whose `Block` and | ||
| //! `Hold` variants require a `TrustTexture` **and** a `FlowState`. Two external | ||
| //! producers reached it with neither axis in their data flow and invented both: |
There was a problem hiding this comment.
Remove the false red-state proof
Compiling this test against main only proves that the new convenience method names were absent; it does not prove that routing without MUL ground was impossible. KanbanColumn::next_phases() was already public in the parent revision and already exposed Prune for Planning and Evaluation (and in-tree callers such as scheduler.rs route through that API), so a domain could express the same veto without constructing GateDecision. Consequently, this test and the accompanying board updates incorrectly claim that F-MUL-1/F-MUL-2 were red and are now discharged; the falsifier must test a behavior unavailable through the prior public API, or the red-state/discharge claims must be revised.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Confirmed against source, and you're right. Fixed in b362bb9 + follow-up.
next_phases() is public on main and returns Prune for Planning and Evaluation, so the veto was always expressible by hand:
phase.next_phases().iter().copied().find(|c| *c == KanbanColumn::Prune)The compile failure proved only that two convenience method names were absent. Presenting that as the strongest form of evidence is exactly the vacuous-falsifier trap this repo's CLAUDE.md warns about, so the claim is withdrawn rather than softened — recorded in the test file's header and corrected in place on LATEST_STATE.md and INTEGRATION_PLANS.md.
What survives, scoped to what's actually true: the honest route existed but was unnamed, so the obvious path into the phase DAG (advance_on_gate(&GateDecision)) demanded two calibration coordinates — and both measured producers took it and invented them. Naming the transition makes the honest route the reachable one. That is an ergonomics-and-naming fix with a measured behavioural consequence, not a new capability, and the falsifiers now say so.
Added veto_agrees_with_the_pre_existing_next_phases_route, which pins exactly the equivalence you identified for both veto() and advance(), so the wrappers can never drift from the raw DAG walk and the honest scope stays visible in code rather than only in a commit message.
One related fix carried in the same commit, from your other finding on #1067 (already merged): the consumer table named crate::action::ActionInstance with methods commit/emit. The type is ActionInvocation and the methods are commit/commit_via. Corrected.
Your third finding — that .claude/plans/mul-consumer-census-v1.md did not exist — was verified stale: true of the reviewed commit, resolved by the merge that brought #1065's census onto this branch. No action taken there.
Generated by Claude Code
…n-evidence # Conflicts: # .claude/board/LATEST_STATE.md # .claude/board/STATUS_BOARD.md
Discharges the second half of F-MUL-6 — the half a grep cannot reach. A classification tells you a symbol is mentioned; only a compiler tells you a change is source-compatible. ada-rs was COMPILED against the combined arc head (#1065 merged, plus #1066, #1067, #1068, #1069) using a temporary `paths` override, reverted afterwards. The override was VERIFIED to bind rather than assumed: a probe calling `KanbanColumn::veto()` — a method that exists only on the head under test — compiled without E0599. Without that check the entire gate could have run against `main` and reported a meaningless pass. Result: ada-rs does not compile, with exactly three errors, and all three are the pre-existing #1045 `reason:` break that predates every deliverable in this arc. Zero errors are attributable to the arc: - `PlannerContract::gate_check` removal -> ada-rs never implemented it - `MulProvider::gate_check` deprecation -> a warning by construction - `KanbanColumn::{advance, veto}` -> purely additive - D-MCAL-3 and D-MCAL-5 -> docs and tests only So the arc is source-compatible with its one live external implementor, and the single red consumer is red for a reason the arc exists to explain rather than one it caused. The stopgap stays unpushed. The three errors are trivially silenced by supplying a texture and a flow at each site, and that fix is refused: inventing two calibration coordinates ada-rs never measured would reproduce exactly the defect the census found in MedCare-rs. The honest fix is D-MCAL-4's route, which now exists on this head — a consent veto is domain evidence, so it calls `veto()` and constructs no `GateDecision` at all. Two of the adapter's three arms are genuine MUL and keep working through `assess()`; only the consent arm moves. MedCare-rs is covered at symbol level plus the in-tree pins rather than by a compile, and that asymmetry is recorded as a LIMITATION in the report rather than reported as a pass. The report's final section states what the gate does not certify at all, including the fifteen other dependent repos whose non-involvement rests on a grep — which, by this deliverable's own argument, is not a build. Board hygiene in the same commit: STATUS_BOARD row, INTEGRATION_PLANS prepend, supersession index regenerated last. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKHLL6NTnRr1XGvKFA1j2L
a37c4a3 to
b362bb9
Compare
Two codex findings, both verified against source before acting.
1. The red-state proof was a naming artifact. WITHDRAWN.
The earlier text claimed F-MUL-1/F-MUL-2 were shown red "mechanically",
because the falsifier file failed to compile against `main` with
`no method named veto`. That proves only that two convenience method NAMES
were absent. `KanbanColumn::next_phases()` is public on `main` and already
returns `Prune` for `Planning` and `Evaluation`, so a domain could always
have routed a veto by hand:
phase.next_phases().iter().copied().find(|c| *c == KanbanColumn::Prune)
Presenting that as the strongest form of evidence is exactly the
vacuous-falsifier trap CLAUDE.md warns about. The correction is recorded in
the test file's header and on both board files rather than quietly deleted.
What remains true, and is what this deliverable actually delivers: the
honest route existed but was unnamed, so the OBVIOUS path into the phase
DAG — `advance_on_gate(&GateDecision)` — demanded two calibration
coordinates, and both measured producers took it and invented them. Naming
the transition makes the honest route the reachable one. That is an
ergonomics-and-naming fix with a measured behavioural consequence, not a
new capability, and the falsifiers are now scoped to that claim.
New test `veto_agrees_with_the_pre_existing_next_phases_route` pins the
equivalence codex identified, so the wrappers can never drift from the raw
DAG walk they wrap and the honest scope stays visible in code.
2. `crate::action::ActionInstance` does not exist.
The consumer table added in #1067 (now on main) named a type that is not
there and methods that are not its: the type is `ActionInvocation` and its
methods are `commit` and `commit_via`, not `commit` and `emit`. The
intra-doc link was unresolved and the table pointed readers at an API that
does not exist. Fixed here because #1067 has already merged.
A third finding — that the census file the doc links did not exist — was
verified stale: it was true of the reviewed commit and resolved by the merge
that brought #1065's census onto this branch.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKHLL6NTnRr1XGvKFA1j2L
b362bb9 to
1719107
Compare
… capability proof Brings the codex-driven corrections on #1068 and #1069 into the combined head the build gate measures, so the gate reports on the corrected arc. Also adds a note to the gate's method section drawing a distinction the arc got wrong once and should not get wrong again. "`KanbanColumn::veto` is absent from `main`" is valid evidence for WHICH SOURCE cargo bound — that is a question about symbol availability, and symbol availability is what it answers. It is NOT valid evidence that routing without MUL ground was previously IMPOSSIBLE, because `next_phases()` was already public and already exposed `Prune`, so the capability existed unnamed. D-MCAL-4's original red-state claim made that second, invalid inference; this gate's probe makes only the first. Recording both readings of the same fact means the next session does not have to re-derive why one use is sound and the other was not. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKHLL6NTnRr1XGvKFA1j2L
…n-evidence # Conflicts: # .claude/board/STATUS_BOARD.md
Two review findings from #1070 that belong with this deliverable's code rather than with the build-gate report that surfaced them, so they land here regardless of merge order. 1. `MulProvider::gate_check` was a REQUIRED trait item, so the migration this deliverable documents did not compile. Deprecation does not make a method optional: an implementor that deleted its `gate_check` got E0046, and one that kept it still had to return a `GateDecision` and fix its `Hold` constructors. `veto()` alone was never a compiling route. It is now a PROVIDED method whose default applies the canonical `(TrustTexture, FlowState) -> GateDecision` rule to the two coordinates already on the `MulAssessment` the implementor computed — measured values, not invented ones, which is the whole difference between this default and what the external producers were doing by hand. The rule is extracted to `GateDecision::from_axes` so it has one definition shared with the i4 evaluator instead of a second copy. `the_documented_migration_compiles_and_behaves` now implements the exact migration shape — assess + compass only, no `gate_check`, consent routed through `veto()` — so if `gate_check` ever becomes required again this file stops compiling. `the_inherited_gate_check_default_reads_measured_axes_not_invented_ones` pins the default to the assessment's own coordinates. 2. `KanbanColumn::veto`'s public rustdoc still carried the red-state claim this PR already withdrew in its test file and on the boards. The rustdoc is the copy users read, and it still said this was the only ground-free route into the phase DAG. It now describes the method as what it is — an ergonomic named wrapper over the already-public `next_phases()` walk, whose value is making the honest route the obvious one — and names the equivalence test inline. 1227 lib + 12 integration tests green; clippy --all-targets and fmt clean. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKHLL6NTnRr1XGvKFA1j2L
… board claim The merge itself is the D-MCAL-6 branch catching up to #1068. Two board fixes ride with it because the conflict put me in the file and leaving them would be the same defect twice. 1. D-MCAL-2/3/4/5 still read "In PR" after all four merged. Flipped to Shipped with their PR numbers. 2. The D-MCAL-4 row still carried the WITHDRAWN red-state claim — "F-MUL-1/F-MUL-2 red-on-main (no compile) then green". That claim was retracted in the test file, in LATEST_STATE, in INTEGRATION_PLANS and in the veto rustdoc, and was still standing here. `next_phases()` already exposed `Prune`, so the capability existed unnamed; what D-MCAL-4 delivers is an ergonomics-and-naming fix with a measured behavioural consequence, not a new capability. The row now says so and marks the old wording withdrawn rather than deleting it. This is the third place the same retraction had to be chased. A claim withdrawn in four places and live in a fifth is still a live claim, and the board is the surface future sessions read first. D-MCAL-2's row also records that the deprecation alone left `gate_check` required, and that #1068 gave it a default — otherwise the row reads as though the migration worked from #1066 onward, which it did not. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKHLL6NTnRr1XGvKFA1j2L
Discharges F-MUL-1 (consent veto) and F-MUL-2 (evidence contradiction). This is the deliverable the whole arc was pointing at.
The change: two methods, no type
advance_on_gatenow delegates to both, so exactly one copy of the DAG routing rule survives and callers that genuinely hold a MUL assessment —gate_decision_i4, the supervisor's cycle driver — are unaffected.The gap being closed
Before this, the only route into the phase DAG was
advance_on_gate(&GateDecision), whoseBlockandHoldvariants require aTrustTextureand aFlowState. A domain that measures neither had to invent both — and the two measured external producers did exactly that:contract_impls.rs:72— consent veto →Block { texture, flow }, neither axis in its data flow.Since the routing never read those coordinates — pinned in #1067 by
f_mul_4_routing_ignores_the_calibration_payload— naming the transition directly loses nothing and fabricates nothing.D-MCAL-5's prohibition is respected
No fourth gate enum joins the three that already exist. These are transitions named as transitions, not a new verdict vocabulary. "Stay put" needs no symbol — it is
None.Anti-vacuity, satisfied mechanically
The plan's §5 requires F-MUL-1/2 shown red first against
main. Not asserted — demonstrated. The falsifier file, compiled unchanged againstmain:That is the red state in its strongest available form: on
mainthere is no route into the DAG that does not construct MUL ground. Green after.The 9 falsifiers
Each case models the external producer's real shape — ada-rs's
ConsentLevel, MedCare's NARS expectation plus supporting/contradicting cardinality — and asserts three things:GateDecisionis constructed anywhere in the domain path;The third is the load-bearing one: it is F-MUL-5's premise, that removing the fabrication costs no behaviour.
Guards against passing by accident:
NaN,±∞) refuse to route rather than falling through a comparison that is false forNaN;advance()andveto()are checked to stay inside the DAG, and to not collapse onto each other at columns where both edges are legal (otherwise one is decoration).Verification
What this does NOT do
It does not touch ada-rs or MedCare-rs. Those migrations are theirs, and per the plan's §6 invariant the ada-rs stopgap stays unpushed. D-MCAL-6 builds the consumers against this head — a classification is not a build.
Board hygiene (same commit)
LATEST_STATE.mdinventory delta ·STATUS_BOARD.mdrow ·INTEGRATION_PLANS.mdprepend · supersession index regenerated last.Generated by Claude Code