Skip to content

feat(reports): close the report granularity vocabulary - #6

Merged
lessevv merged 1 commit into
mainfrom
feat/close-report-granularity
Jul 29, 2026
Merged

feat(reports): close the report granularity vocabulary#6
lessevv merged 1 commit into
mainfrom
feat/close-report-granularity

Conversation

@lessevv

@lessevv lessevv commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Spec: GOV-R13

Summary

Adds C7-R21, closing the report granularity vocabulary to monthly and
weekly, requiring one named type rather than free strings, and stating that
the type must not be shared with the series cadence (C2) or the digest cadence
(C8).

Why

Granularity is monthly or weekly and nothing else, but C7 never said so. The
set exists only as a 'monthly' | 'weekly' docblock repeated across five
classes, and the value is stored inside a saved report's definition JSON
payload — so unlike the series cadence there is no column a CHECK constraint
could reach. The requirement is worded for that: it asks for rejection of an
out-of-set value rather than for a column constraint.

This is the third vocabulary that says weekly. C2-R20 and C8-R22 already
close the other two and already require them to be distinct from each other;
granularity was left out of that pass. Sharing a type between any two of them
would be wrong in a way that still type-checks — a report is not on a cadence,
and widening its buckets has nothing to do with how often a series recurs or
how often a digest is sent.

Note on quarterly

Quarterly is deliberately not in the vocabulary. TimeBucketGenerator
reaches it on its own when a range would exceed MAX_BUCKET_POINTS, but the
user never selects it and a saved report never stores it — it is a widening
outcome, not a choice.

This needed saying in prose, because the existing "Time buckets widen rather
than truncate" paragraph names quarterly and, read alone, suggests it is
selectable. Someone implementing R21 from the requirement table plus that
paragraph could reasonably have put a third case in the enum.

Verification

  • python3 scripts/integrity.py — clean
  • Requirements are append-only; R21 is new, nothing renumbered or reworded
  • Both cross-links resolve (c2-recurring.md, c8-notifications.md), added
    to Related as well as inline

Follow-up

The code change lands separately and cites C7-R21: a ReportGranularity enum
replacing the string on ReportDefinition, TimeBucketGenerator,
TimeBucketSpendQuery, NetWorthSeriesQuery and ReportBuilder.

Report granularity is monthly or weekly and nothing else, but C7 never
said so. The set exists only as a `'monthly' | 'weekly'` docblock
repeated across five classes, and the value is stored inside a saved
report's definition payload where no column constraint can reach it.

This is the third vocabulary in the codebase that says `weekly`. The
series cadence of C2-R20 and the digest cadence of C8-R22 are already
closed and already required to be distinct from each other; granularity
was left out of that pass. Sharing a type between any two of them would
be wrong in a way that type-checks: a report is not on a cadence, and
widening its buckets has nothing to do with how often a series recurs
or how often a digest is sent.

C7-R21 closes the set, requires one named type rather than free
strings, requires a stored value outside the set to be rejected rather
than defaulted, and states that the type MUST NOT be shared with either
cadence.

Quarterly is deliberately not in the vocabulary. The generator reaches
it on its own when a range would exceed the point cap, but the user
never picks it and a saved report never holds it — it is a widening
outcome, not a choice. The prose says this explicitly, because the
existing widening paragraph names quarterly and would otherwise read as
if it were selectable.

Spec: GOV-R13
Signed-off-by: Wessel Verheij <info@nightworks.io>
@sonarqubecloud

Copy link
Copy Markdown

@lessevv
lessevv enabled auto-merge (squash) July 29, 2026 12:24
@lessevv
lessevv merged commit bfb51d4 into main Jul 29, 2026
13 checks passed
@lessevv
lessevv deleted the feat/close-report-granularity branch July 29, 2026 12:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant