Skip to content

fix(facts): accept real EDGAR company-facts shapes during ingest#209

Merged
sroussey merged 3 commits into
mainfrom
fix/company-facts-ingest-constraints
Jul 23, 2026
Merged

fix(facts): accept real EDGAR company-facts shapes during ingest#209
sroussey merged 3 commits into
mainfrom
fix/company-facts-ingest-constraints

Conversation

@sroussey

Copy link
Copy Markdown
Contributor

A full bootstrap flooded with STORE_ERRORs that lost whole CIKs' facts because the company-facts constraints were tighter than real EDGAR data:

  • fp: EDGAR emits CY / H1 / H2 (calendar-year, half-year) beyond FY/Q1-Q4, and an empty string "" for period-agnostic facts. Widen the FP enum and add normalizeFp() to map "" / unknown codes to null at parse time (the storage boundary already coalesces null to the "" PK sentinel), so one odd fact can't fail a CIK's entire batch.
  • val_unit: composite units run to ~20 chars; bump 12 -> 32.
  • grouping: ifrs-full is 9 chars; bump 8/10 -> 20. (Existing Postgres company_facts columns widened separately via ALTER.)

Also fix update facts --retry-failed, which crashed with "Query criteria must not be empty" — the all-CIK read used query({}, ...); switch to getAll({ orderBy }). This path is only reached by update facts, not bootstrap, so it stayed hidden until a retry run.

Adds regression tests for the widened fp/val_unit/grouping schemas, normalizeFp, and the getAll retry-lane read.

Claude-Session: https://claude.ai/code/session_019ZKz3adGzMpEdy9jJ3HNXu

sroussey and others added 2 commits July 22, 2026 15:42
A full bootstrap flooded with STORE_ERRORs that lost whole CIKs' facts
because the company-facts constraints were tighter than real EDGAR data:

- fp: EDGAR emits CY / H1 / H2 (calendar-year, half-year) beyond FY/Q1-Q4,
  and an empty string "" for period-agnostic facts. Widen the FP enum and
  add normalizeFp() to map "" / unknown codes to null at parse time (the
  storage boundary already coalesces null to the "" PK sentinel), so one
  odd fact can't fail a CIK's entire batch.
- val_unit: composite units run to ~20 chars; bump 12 -> 32.
- grouping: ifrs-full is 9 chars; bump 8/10 -> 20.
  (Existing Postgres company_facts columns widened separately via ALTER.)

Also fix `update facts --retry-failed`, which crashed with "Query criteria
must not be empty" — the all-CIK read used query({}, ...); switch to
getAll({ orderBy }). This path is only reached by `update facts`, not
`bootstrap`, so it stayed hidden until a retry run.

Adds regression tests for the widened fp/val_unit/grouping schemas,
normalizeFp, and the getAll retry-lane read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZKz3adGzMpEdy9jJ3HNXu
- xbrl_fact.context_ref overflowed varchar(128) on real filings (iXBRL
  context ids are long, esp. dimensional contexts). Widen schema to 512.
- Add widenNarrowColumns() migration, run at the end of setupAllDatabases:
  CREATE TABLE IF NOT EXISTS never alters an existing table, so a Postgres
  DB set up before the company-facts (val_unit/grouping) and XBRL
  (context_ref) widenings kept the narrow columns and silently re-hit the
  original overflow. The migration brings existing columns up to the schema
  width. Postgres-only (SQLite TEXT is unbounded); guarded to skip columns
  already wide enough, so it is a cheap idempotent no-op on a clean DB.
- Add context_ref width regression test (parity with the facts tests).

Addresses the review's MAJOR finding: the maxLength bump alone left the
fix incomplete on the very backend (Postgres) that exhibited the bug.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZKz3adGzMpEdy9jJ3HNXu
@sroussey
sroussey force-pushed the fix/company-facts-ingest-constraints branch from dc6091d to 11bc2c8 Compare July 22, 2026 22:43
The test registers SEC_DRY_RUN=true in the global service registry to
exercise the dry-run retry lane, but resetDependencyInjectionsForTesting()
only re-registers repos — it never clears SEC_DRY_RUN. Under `bun test`
all files share one process, so the leaked flag poisoned later files: on
bun 1.3.14's file ordering it ran before SecFetchFileOutputCache.test.ts,
whose saveOutput early-returns under dry-run, failing all 5 of its
save-path assertions. Reset the flag to false in afterEach (matching
dryRunRouting/runCommand). Verified: full suite 1938 pass / 0 fail on
bun 1.3.14 in a Linux container (previously 5 fail).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZKz3adGzMpEdy9jJ3HNXu
@sroussey
sroussey merged commit 071c2f7 into main Jul 23, 2026
1 check passed
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