ADR-0007: record step 2 as implemented, and the one part that was not - #22
Merged
Conversation
Steps 1 to 4 are done and every consumer reads bars from marketdata. cotdata
0.4.0 ships with no bar API, no Norgate and no yfinance.
The part worth being precise about is what did NOT happen: databento is still in
cotdata. That is a deviation from this ADR rather than an exception it carved
out, and the previous framing of it (in the shipping PRs) had that backwards.
The ADR says plainly that vendors are providers and never packages, and step 2's
own inventory names providers/databento.py as the largest single file that moves.
It stayed because porting it is its own piece of work -- a two-stage paid-API
producer with a raw bronze store, an ingest manifest and a reconcile path, with
no counterpart in marketdata's Norgate-shaped provider -- and because deleting it
would have destroyed an ADR-0006-validated alternative to make a package
description true. So it is outstanding work, and the status says so.
What that costs is now written down: cotdata's public API is COT-only and its
STORE is not, because keeping databento keeps write_prices/read_prices,
prices_dir() and the prices manifest half with it.
Also recorded:
* No shim was built and none was needed. The Consequences section planned one
plus a deprecation window; ordering made it unnecessary (every consumer was
repointed before the delete) and would have made it harmful (a shim reading
cotdata's own store returns a stale number instead of an AttributeError).
Step 4's shim half is void; its store-root half stays open.
* Two predictions corrected. Step 2 moved ~700 lines, not ~1,700, because
databento stayed -- cotdata is still ~18% price code. And it was not "a file
move": the Norgate provider had to be rewritten against the tier-aware store,
since one frame per symbol cannot hold backadj and unadj at once.
* propadj is resolved and hardened: marketdata raises when only one stored tier
is present rather than returning empty.
* A process finding for the next extract in this style. Step 2 ported the
provider WITHOUT its tests and the gap was invisible for two weeks, because
the test files existed on both sides -- diffing test NAMES gave zero overlap
across the 30 about to be deleted, hiding seven behaviours that would have
had no test anywhere. The same shape appeared twice more: finals_ready() was
ported with no caller, and two parity harnesses read the store by path. A
call-site census is not a coverage census.
* Two open questions that were stale: livebook now HAS the specs guard step 3
asked for, and livebook/bin/daily.sh guards COTDATA_STORE but not
MARKETDATA_STORE, which is where its bars and specs now come from.
407 tests pass. docs/adr/ is excluded from the prose guard, so this text is out
of its scope either way.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ADR-0007 step 2 shipped 2026-08-09. Steps 1–4 are done, every consumer reads
marketdata.get_bars, andcotdata0.4.0 ships with no bar API, no Norgate and no yfinance.Doc only — 407 tests pass, and
docs/adr/is excluded from the prose guard.The part worth being precise about
databento is still in
cotdata, and that is a deviation from this ADR — not an exception it carved out. The shipping PRs framed it as the latter; that was backwards, and this corrects it against the ADR's own text:and step 2's inventory names
providers/databento.py(1015 lines) as the largest single file that moves.Why it stayed — for no architectural reason. It was neither ported nor deleted:
marketdata, whose futures provider is Norgate-shaped.So it was left as the lesser of two bad options, and the status now says it is outstanding work.
What it costs, written down:
cotdata's public API is COT-only; its store is not. Keeping databento keepsstore.write_prices/read_prices,config.prices_dir()and thepricesmanifest half with it. Two packages can still write futures bars — the coupling the contract-specs amendment argued against under "one vendor integration, one home". Nothing is broken today: the dash is on synced Norgate per ADR-0006's Outcome, so the split store is latent, not live.No shim was built, and none was needed
Consequences planned "a re-export shim and a deprecation window rather than a clean cut", with step 4 to remove it. The cut was clean. Ordering made the shim unnecessary — every consumer was repointed and verified before the delete — and would have made it harmful: a shim left reading
cotdata's own store returns a stale number instead of anAttributeError, and that store is no longer filled by the nightly job. Step 4's shim half is void; its store-root half stays open.Two predictions corrected
cotdatais still roughly 18% price code — the mismatch is reduced, not eliminated.cot.pyimporting onlystore) made the split clean, but the Norgate provider had to be rewritten against the tier-aware store: one frame per symbol cannot holdbackadjandunadjat once.A process finding for the next extract in this style
Step 2 ported the Norgate provider without its tests, invisible for two weeks because the test files existed on both sides. Diffing the test names across the 30
cotdatawas about to delete gave zero overlap — which reads like a renaming and hid seven behaviours that would have had no test anywhere once the deletion landed.The same shape appeared twice more in the same step:
finals_ready()was ported and wired to no CLI flag, so deletingcotdata's--require-finalwould have silently ungated the nightly capture; and two databento parity harnesses read the Norgate store by path, so no call-site grep found them.A call-site census is not a coverage census. Count what the tests assert and what reaches each entry point, not what files exist.
Open questions, refreshed
propadjis resolved and hardened (marketdataraises when only one stored tier is present rather than returning empty). Two were stale and are corrected:livebooknow has the specs guard step 3 asked for —livebook.specs.broker_specscallscontract_specs(required=True)and provesExchangeresolves before the broker connects.livebook/bin/daily.shguardsCOTDATA_STOREbut notMARKETDATA_STORE, which is where its bars and specs now come from. It fails closed rather than silently, so the consequence is a traceback mid-run instead of a clear refusal at the top — worth making symmetric, inlivebook.Generated by Claude Code