docs: caveat 4 needs a year span crossing FY2002, not just a recipe query

Task 4's implementer found that SB195 does not surface for a
recipe query spanning only 2011-2012. .build_series_break_refs() matches
break_year BETWEEN min(years) AND max(years), and SB195's break_year is 2002.

That is correct behaviour rather than a gap: a series lying entirely after the
book -> market change sits on one consistent basis, so disclosing a break it
never crosses would be noise. .build_corpus_break_refs() applies the same rule
deliberately.

The spec's caveat table overclaimed by omitting the span condition. Corrected.
This commit is contained in:
2026-08-03 10:39:09 -04:00
parent 90d2e6019e
commit b8189aeb7f
+9 -1
View File
@@ -187,7 +187,15 @@ Verified against `series_breaks.csv`, not assumed:
| 1 | Gross holdings, **not GAAP fund balance**; no liabilities netted | No — a constant, new field `not_gaap = TRUE` |
| 2 | `W` is FY2012–2021 only | No — new `coverage_window`, **computed** from the corpus |
| 3 | `X`/`Z` holdings end FY2016 | **Not yet.** No `series_breaks` row exists at 2016/2017 for `Z77`/`Z78`/`X30`. Reader surfaces it via `coverage_window`; flows through `series_break_refs` once the upstream entry lands (see Out of scope) |
| 4 | `X40`/`X41` book → market at FY2002 | **Yes**, via `SB195`/`SB196` on `fin_code` `X40`/`X41` — but only on a `recipe` query, which is the only path that observes those codes. Asserted in the tests rather than assumed |
| 4 | `X40`/`X41` book → market at FY2002 | **Yes**, via `SB195`/`SB196` on `fin_code` `X40`/`X41`, under **two** conditions: a `recipe` query (the only path that observes those codes) **and** a year span that crosses FY2002. Asserted in the tests rather than assumed |
On caveat 4's second condition: `.build_series_break_refs()` matches
`break_year BETWEEN min(years) AND max(years)`, so a request spanning only
2011–2012 does **not** surface `SB195`. That is correct, not a gap — such a
series sits entirely after the change, on one consistent basis, and flagging a
break it never crosses would be noise. The same rule is applied deliberately in
`.build_corpus_break_refs()`. An earlier draft of this row omitted the span
condition and overclaimed.
`coverage_window` is derived per observed subtype family from the corpus, never
hardcoded, so it stays correct as the corpus grows.