Repository navigation
PARTIAL values are lower bounds in Pulse and Debt without the subset proof Clutter now requires, and the derivation rewrites their cause #39
Description
Found by the review of 2026-09-30, while repairing PV-REV-PR-031-003 in #31.
What happens
The research review of #31 (run 408, PV-REV-PR-031-003, CLU-PARTIAL-TRUST-01..08) found that clutter.bands.v1 read any fresh value-bearing PARTIAL count as an observed subset on its status alone. #31 now repairs that for Clutter: the derivation declares a count over an incomplete inventory an OBSERVED_SUBSET_COUNT in its coverage, and Clutter admits a PARTIAL count as a floor only with that proof.
Two more Vitals make the same inference and were outside that review's scope:
- Pulse (
pulse.bands.v1,_partial_lower_boundinsrc/devostasis/vitals/pulse.py): a required input that isPARTIAL, fresh and value-bearing is a lower bound for the bounded inference ofPV-PULSE-REQUIRED-LOWER-BOUND-001, which the accepted contract grants only "because a newest-first enumeration was capped". - Debt (
src/devostasis/vitals/debt.py): aPARTIALdebt.items.open_countgreater than zero isDEGRADED / PRESENT / CONSERVATIVE_LOWER_BOUND.
Neither looks at what the value is. Reproduced on the head of #31, where the proof now exists but is not asked for:
pulse [no coverage at all]: STEADY DEGRADED CONSERVATIVE_LOWER_BOUND ['REQUIRED_INPUT_PARTIAL:git.default_branch.commits.count_28d:PAGINATION_CAPPED', ...]
debt [no coverage at all]: PRESENT DEGRADED CONSERVATIVE_LOWER_BOUND ['PARTIAL_REGISTER:debt.items.open_count']
pulse [value_semantics=ESTIMATE]: STEADY DEGRADED CONSERVATIVE_LOWER_BOUND [...]
debt [value_semantics=ESTIMATE]: PRESENT DEGRADED CONSERVATIVE_LOWER_BOUND ['PARTIAL_REGISTER:debt.items.open_count']
A PARTIAL value that says outright it is an estimate is still a floor.
Two related provenance defects of normalize._derived, found by the same review:
- the reason of a
PARTIALaggregate is replaced bySOURCE_COVERAGE_INCOMPLETEwhatever the source said (PAGINATION_CAPPED,REQUEST_BUDGET_EXHAUSTED, a cause that is not a cap), so Pulse diagnosesREQUIRED_INPUT_PARTIAL:…:SOURCE_COVERAGE_INCOMPLETEand cannot tell the capped enumeration its contract covers from anything else; - a value-less
PARTIALinventory becomes anUNAVAILABLEaggregate, which means "the source does not exist": Clutter then reads the branch component as explicitly unavailable (COMPONENT_UNAVAILABLE:branches:REQUEST_BUDGET_EXHAUSTED) instead of unresolved.
Why it is not repaired in the release
On the live path nothing changes: every count observe derives from an incomplete inventory now carries the proof, so a live PARTIAL input to Pulse or Debt is always a proven subset. The difference is only for saved or hand-written observation sets. But pulse.bands.v1 has been released since 0.1.2, and whether a hardening that changes no live output moves the rule id (one RULE_VERSION_BOUNDARY per project in the fleet) is a question for the research side. Debt also has its own accepted repair pending (PV-DEBT-PARTIAL-001, #33) on the same branch of debt.py. The review PR does fix Debt's missing freshness check (a stale partial register was a PRESENT lower bound, which vitals.md never allowed).
Proposal
- Apply the Clutter check (
observations.subset_count_problem) to everyPARTIALvalue Pulse and Debt read as a lower bound, with the fail-closed outcome each Vital already has for an unusable input (Pulse:UNKNOWNfor a required input; Debt:UNKNOWN). - Carry the source's reason onto a
PARTIALaggregate, and never turn a value-lessPARTIALsource intoUNAVAILABLE(a value-lessPARTIAL, orERROR). - Do the Debt part together with the
PV-DEBT-PARTIAL-001adoption of Accepted research repairs of the Vitals not yet adopted: Direction closed-target and incomplete, Debt partial, Horizon partial, Integrity totality, T9 #33, so Debt's rule version moves once; give Horizon's accepted partial repair (PV-HORIZON-PARTIAL-001, Accepted research repairs of the Vitals not yet adopted: Direction closed-target and incomplete, Debt partial, Horizon partial, Integrity totality, T9 #33) the same proof from the start. - For the research side: does a fail-closed check that changes no live output need a Pulse rule version? If not, record the judgement in
PROVENANCE.md.
🤖 Generated with Claude Code
Activity
drevendev commentedon Sep 30, 2026
#53 (0.2.0) does the Debt part as proposed: a
PARTIALdebt.items.open_countis a lower bound only withvalue_semantics = OBSERVED_SUBSET_COUNT, under the rule versionPV-DEBT-PARTIAL-001moves anyway (debt.bands.v2), and Horizon's partial repair (horizon.bands.v2) requires the same proof from the start. Debt now also reports the source inventory's own reason (derived.partial_enumeration.source_reason_code, e.g.PAGINATION_CAPPED) without changing the derivation.Still open here: the Pulse part, which waits for the research answer this issue asks for, and the two
normalize._derivedprovenance defects (aPARTIALaggregate's reason replaced bySOURCE_COVERAGE_INCOMPLETE; a value-lessPARTIALinventory derived asUNAVAILABLE), which change live Pulse and Clutter diagnostics and belong with that answer.🤖 Generated with Claude Code
drevendev commentedon Oct 14, 2026
Manual implementation handoff: proof must survive the source-to-count boundary
RUN-433 /
PV-MANUAL-REPOSITORY-HANDOFF-20261014-001. Freshly inspected cumulative head09d497f16520b6dc20f5dd42077ff76774e1f5e1(normalize.py,vitals/pulse.py) and the existing Debt/Horizon update in this thread.The Debt/Horizon evaluator checks are not the whole repair. In
_derived(), a value-bearing PARTIAL list getsvalue_semantics=OBSERVED_SUBSET_COUNTwhenever the caller setssubset_count=True; the source coverage is copied but is not used to establish that its records are an authoritative monotone subset. An estimate/unproven acquisition can therefore acquire a stronger proof marker during derivation. This is the upstream concern independently recorded byPV-REV-PR-053-001, not a request to weaken Debt/Horizon's checks.The remaining boundaries are visible in the current source:
_partial_lower_bound()still checks only PARTIAL, FRESH andhas_value, not subset semantics._derived()overwrites a PARTIAL source's cause withSOURCE_COVERAGE_INCOMPLETEunless explicitly overridden.Implementation sequence: establish machine-explicit source provenance before issuing a subset marker; make Pulse consume the proof; retain the original acquisition cause and distinguish missing data from nonexistence. Negative tests should carry an ESTIMATE or absent proof through source -> derivation -> evaluator, not merely call the Vital with an already valid marker. Include valid capped subsets, malformed coverage, valueless PARTIAL, optional-channel gaps and frozen historical replay.
Compatibility proposal (not a newly accepted rule): changing classification of previously admitted saved observations needs an explicit version boundary even if the ordinary collector output is unchanged. Coordinate Debt with its existing v2 candidate; do not silently redefine released Pulse v1.
Two cautions prevent over-repair: independent lower bounds
commits>=1andactive_days>=20are not contradictory by themselves;active_days<=commitsapplies to exact paired counts from the same inventory, not arbitrarily paired floors. Also the current rolling 28-day window can touch 29 UTC dates; do not introduce a hard 28-date ceiling.Verification: fresh source inspection and prior accepted review cross-check; no full integration suite or newly accepted semantic contract is claimed.
Publication receipt:
DV-MANUAL-20261014-I39-d56e20bb.