Skip to content

feat(serve): load taxonomy packages and page long networks - #69

Merged
jfrench9 merged 3 commits into
mainfrom
feature/taxonomy-package-load
Sep 16, 2026
Merged

jfrench9 merged 3 commits into
mainfrom
feature/taxonomy-package-load

Conversation

@jfrench9

Copy link
Copy Markdown
Member

Summary

load_filing refused a taxonomy published on its own (a zip of schemas and linkbases with no report), even though every tool reads its DTS once Arelle is pointed at the right schema. A package with no report now loads from an entry point, by path or by URL. Once loaded, a taxonomy's networks outran the 400-row cap with no way to reach the rest, so statement and information_block now page.

Taxonomy support is a load format, not a new lane: no new tools, one optional parameter on load_filing, and reports load exactly as before.

Changes

serve/session.py (loading)

  • A zip or directory with no inline document or instance loads from an entry point: the first one META-INF/taxonomyPackage.xml lists, resolved into the package through its catalog's rewriteURI; or, with no manifest, the one schema nothing else in the package imports. With no manifest and several root schemas, the load asks for one.
  • FilingSession.load takes entry_point to load another, matched by path in the package, file name, stem or manifest name. An ambiguous or unknown name is refused with the candidates listed. entry_point on a source that is not a package is refused.
  • An elements-only entry point (no linkbases, so no networks for the model to reach) is refused as such, naming the entry points that have networks, instead of "not XBRL".
  • A .zip URL is downloaded and loaded as a local package. This is also the path a report zip given by URL now takes, the same one lei: / filings.xbrl.org loads already use.
  • _find_load_target returns None instead of raising when a package holds no report.

serve/tools.py (surface)

  • The load receipt and describe_filing carry a taxonomy block: the entry point loaded and the others on offer. The next steps for a taxonomy point at resolve_element, disclosures, statement and information_block.
  • statement and information_block take offset. A truncated response returns next_offset; the pages join into the unpaged rows with depths intact. A later page carries ancestors (the headers above its first row). information_block returns axes, calculation and text with the first page only. An offset past the end is refused with the row count.

serve/server.py + serve/README.md

  • MCP: entry_point on load_filing, offset on statement and information_block. The tool text grows by one sentence each, since it ships in every client's prompt; the detail lives in serve/README.md.

Output Impact

BROADER COVERAGE: taxonomy packages that previously failed to load now load (FASB US GAAP / SRT, and manifest-less packages such as GASB's 2026 taxonomy exposure draft). Holon, TAVI and model output are unchanged; serialize/ is untouched.

MCP surface changes are additive: new optional parameters and a taxonomy key present only on taxonomy loads. The CLI is unchanged; xbrlkit serve / view take a taxonomy zip as a source but have no --entry-point flag. The robosystems information-block operation calls information_block with keyword arguments, so the new offset parameter does not affect it.

Testing

just test-all (via the commit hook): ruff, format, basedpyright clean; 544 passed, 2 skipped.

New tests (hermetic, Arelle mocked at _parse): root-schema detection that ignores linkbase back-references, several roots asking for one, manifest order with a catalog-rewritten URL and a relative href, entry-point matching and its errors, the receipt block, the elements-only refusal, a zip by URL, entry_point refused off-package, and paging that joins back into the unpaged rows for both tools.

Real loads through the branch code (no report, so no accession numbers):

Source Entry point chosen Concepts Networks (pre / cal / def)
gasb-exposure-2026.zip (no manifest) gasb-exposure-2026.xsd 855 147 / 0 / 735
us-gaap-2025.zip entire/us-gaap-entryPoint-all-2025.xsd, 10 others listed 20,699 118 / 65 / 2,414
us-gaap-2025.zip, entry_point="us-gaap-entryPoint-std-2025" entire/us-gaap-entryPoint-std-2025.xsd 18,232 111 / 65 / 2,372
https://xbrl.fasb.org/us-gaap/2026/us-gaap-2026.zip entire/us-gaap-entryPoint-all-2026.xsd 20,617 117 / 65 / 2,353
https://xbrl.fasb.org/srt/2026/srt-2026.zip entire/srt-entryPoint-all-2026.xsd 3,578 22 / 2 / 203

US GAAP 2025 network counts were checked against the raw linkbases the entry point reaches: 111 FASB presentation roles (+7 from the SEC taxonomies it imports), 65 calculation roles, 397 FASB definition roles (+11 SEC). The classified balance sheet pages to 691 rows over two calls; Liabilities, StockholdersEquity and LiabilitiesAndStockholdersEquity, previously unreachable past the cap, sit at rows 535, 594 and 690. The Leases (Topic 842) block pages to 771 rows over two calls.

Known and left alone: resolve_element ranking has no fact counts to lean on in a taxonomy ("revenue" on US GAAP does not rank us-gaap:Revenues first), and GASB's statements are not classified as statements. Both wait for real demand.

`load_filing` refused a taxonomy published on its own — a zip or
directory of schemas and linkbases with no report — with "No inline
document or XBRL instance found", even though every tool works on its
DTS once Arelle is pointed at the right schema.

- A package with no report now loads from an entry point: the first one
  `META-INF/taxonomyPackage.xml` lists, resolved into the package through
  its catalog (FASB's US GAAP and SRT packages open with
  `entire/…-entryPoint-all`), or, with no manifest (GASB's exposure
  drafts), the one schema nothing else in the package imports. Several
  root schemas and no manifest asks for one.
- `load_filing` takes `entry_point` to load another, by its path in the
  package, file name or name.
- The receipt and `describe_filing` carry a `taxonomy` block naming the
  entry point loaded and the others on offer, and the next steps point
  at resolve_element, disclosures, statement and information_block.
- An elements-only entry point has no networks for the tools to read;
  it is refused as such rather than as "not XBRL".
- A `.zip` URL is downloaded and loaded as a local package, so a
  published taxonomy loads by its URL
  (`https://xbrl.fasb.org/us-gaap/2026/us-gaap-2026.zip`).
A taxonomy's own networks outrun the 400-row cap: US GAAP's classified
balance sheet walks to 691 rows, and `statement` stopped in current
liabilities with no way to reach Liabilities, StockholdersEquity or
LiabilitiesAndStockholdersEquity.

- `statement` and `information_block` take `offset`. A truncated
  response returns `next_offset`; passing it back returns the next page,
  and the pages join into the unpaged rows with their depths intact.
- A later page carries `ancestors`, the headers above its first row, so
  a page that opens deep in the tree says what it sits under.
- `information_block` returns the section's axes, calculation and text
  with the first page only; later pages carry rows and their columns.
- An offset past the end is refused with the row count.
Tool descriptions ship in every client's prompt, so every xbrlkit user
pays for them. The taxonomy loading detail stays in serve/README.md.
@jfrench9
jfrench9 merged commit 8c518a2 into main Sep 16, 2026
4 checks passed
@jfrench9
jfrench9 deleted the feature/taxonomy-package-load branch September 16, 2026 20:56
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