Skip to content

feat(schema): add optional resolved_count so hit_rate 0 can be read - #59

Merged
tkowalczyk merged 1 commit into
mainfrom
feat/resolved-count
Jul 30, 2026
Merged

feat(schema): add optional resolved_count so hit_rate 0 can be read#59
tkowalczyk merged 1 commit into
mainfrom
feat/resolved-count

Conversation

@tkowalczyk

Copy link
Copy Markdown
Contributor

Consumer half of auditmos/ogsfrompoly#236.

hit_rate is in_favor / resolved over alerts emitted in the period, so hit_rate: 0 is ambiguous:

hit_rate resolved_count meaning
bad week 0 240 240 settled, none in favour
nothing settled 0 0 rate is vacuous

Macro-only statements are almost always the second — those markets resolve months after the alert. Without a denominator the sanity lint must treat both as suspect, which is why 2026-07-28-weekly.md could not be published at truthful values and was unpublished instead.

Optional field → not a version bump (per docs/statement-schema.md). schema_version stays 1; all ten published statements keep validating. Absent means unknown, never zero, so the 0/0-collapse guard still fires for the back catalogue, including the ogsfrompoly-lp#30 case it exists for.

Adds two mirror checks: hit_rate > 0 with resolved_count === 0, and resolved_count > alert_count (join fan-out). Hit-rate checks extracted to findHitRateInconsistencies, mirroring the existing findPnlInconsistencies split — inlining tripped noExcessiveCognitiveComplexity.

408 tests pass, lint clean, 0 type errors. Producer half is auditmos/ogsfrompoly@686de7f.

`hit_rate` is `in_favor / resolved` over alerts EMITTED in the period, so a market
alerted on Monday that settles in December counts toward `alert_count` now and
toward `hit_rate` months later. On its own `hit_rate: 0` is therefore ambiguous
between two very different weeks:

  hit_rate 0, resolved 240  → 240 outcomes settled and none went our way
  hit_rate 0, resolved   0  → nothing has settled; the rate is vacuous

Macro-only statements are almost always the second — those markets resolve months
after the alert. Without a denominator the sanity lint had to treat both as
suspect, which made a truthful statement for an unresolved window unpublishable:
`2026-07-28-weekly.md` could not clear CI without either asserting a 0% success
rate that never happened, or falsifying its PnL back to 0 to match. It was
unpublished instead.

`resolved_count` is OPTIONAL, which per docs/statement-schema.md is explicitly not
a version bump — `schema_version` stays 1 and all ten existing statements keep
validating. Absent means UNKNOWN, never zero: the 0/0-collapse guard still fires
when the field is missing, so this does not retire that check for the back
catalogue, including the ogsfrompoly-lp#30 case it was written for.

Two mirror checks come with it, since a denominator is only useful if it is also
constrained:
  - hit_rate > 0 with resolved_count === 0 — a rate over no resolved outcomes
  - resolved_count > alert_count — the resolution join fanned out

The hit-rate checks move into `findHitRateInconsistencies`, mirroring the existing
`findPnlInconsistencies` split; inlining the new branches tripped
noExcessiveCognitiveComplexity, and the helper is the shape this file already uses.

Producer side (emitting the field) lands in auditmos/ogsfrompoly. Ordered
consumer-first so the value is understood before it is sent.

Refs auditmos/ogsfrompoly#236, auditmos/ogsfrompoly#234
@tkowalczyk
tkowalczyk merged commit a50bfb5 into main Jul 30, 2026
1 check passed
@tkowalczyk
tkowalczyk deleted the feat/resolved-count branch July 30, 2026 07:52
github-actions Bot pushed a commit that referenced this pull request Jul 30, 2026
# [1.18.0](v1.17.1...v1.18.0) (2026-07-30)

### Features

* **schema:** add optional resolved_count so hit_rate 0 can be read ([#59](#59)) ([a50bfb5](a50bfb5)), closes [ogsfrompoly-lp#30](https://github.com/ogsfrompoly-lp/issues/30) [auditmos/ogsfrompoly#236](https://github.com/auditmos/ogsfrompoly/issues/236) [auditmos/ogsfrompoly#234](https://github.com/auditmos/ogsfrompoly/issues/234)
tkowalczyk added a commit that referenced this pull request Jul 30, 2026
…minator (#60)

`resolved_count` landed in #59, so an unresolved window is expressible: adding
`resolved_count: 0` clears `findHitRateInconsistencies`, which is what held this
file at `draft: true`. The numbers are unchanged from #58 — regenerated from the
warehouse at auditmos/ogsfrompoly@554f537 over the identical window — and its
summary's "0 of 263 resolved" is the count itself, so the field states what the
prose already did.

Publishing it would otherwise have put `Hit rate 0%` back on the live page beside
this stat's own caption, "0.50 ≈ a coin flip; above 0.50 is signal" — the exact
misreading auditmos/ogsfrompoly#236 exists to stop, on the most-skimmed surface.
So the stat now reads `pending` when the denominator is known-empty, with wording
that replaces the standing caption rather than appending a caveat to it.

`formatHitRate` / `describeHitRate` key off the denominator, never the rate, so a
genuine 0-in-favour-of-240 week still reads as a real 0%. Absent stays unknown,
never zero: every statement published before the field existed renders exactly as
before, verified across all twelve. A known non-zero denominator is now named too
("Measured over the 240 of 263 alerts that have resolved") — publishing a rate
without one is what let the 0.00 pass unnoticed for a week.

Refs auditmos/ogsfrompoly#236

Co-authored-by: Tomasz Kowalczyk <tkow@Mac-Studio-Tomasz.local>
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