Skip to content

Phase 167: /batch-export — one zip for a screened list - #211

Merged
StephenAbbott merged 2 commits into
mainfrom
feat/phase-167-batch-export
Sep 3, 2026
Merged

Phase 167: /batch-export — one zip for a screened list#211
StephenAbbott merged 2 commits into
mainfrom
feat/phase-167-batch-export

Conversation

@StephenAbbott

Copy link
Copy Markdown
Owner

Third and last piece of batch / portfolio screening (Notion ticket, Phase C).

  • GET /batch-export?leis=: runs the Phase 164 loop to completion (free inside the replay window) and returns opencheck-batch-<date>.zipbundle.json (every row's BODS statements, de-duplicated by statementId), rows.csv (same 16 columns as the page's CSV, failed rows marked not checked), manifest.json, LICENSES.md over the union of sources (strictest member wins — pinned by a test). X-OpenCheck-Batch-Failed header. Heavy tier, bot gate, robots disallow.
  • opencheck/batch.py: iter_batch hands the LookupResponse back beside each row; collect_batch + BatchResult + rows_csv. run_batch and the MCP tool are unchanged.
  • /batch page: Download BODS bundle (zip) beside the CSV button, fetch-based so a 429 is worded. /api page + docs/mcp-server.md updated.
  • 6 backend tests.

🤖 Generated with Claude Code

https://claude.ai/code/session_016TF8feptbqf5yz3KoeDFQq

StephenAbbott and others added 2 commits September 3, 2026 16:54
The third piece of batch screening: the combined export. GET /batch-export
runs the same loop as /batch-stream to completion (free inside the
15-minute replay window, which is the case when the table has just been
shown) and returns opencheck-batch-<stamp>.zip with bundle.json (every
row's BODS statements, de-duplicated by statementId — two subsidiaries of
one group share the parent's entity statement and it appears once),
rows.csv (the same columns as the page's CSV button, failed rows included
with their reason), manifest.json (totals, the failed list, contributing
sources, the licence verdict) and LICENSES.md computed over the union of
sources, so one CC-BY-NC source in one row makes the whole bundle
non-commercial and the notes say so.

- opencheck/batch.py: iter_batch yields the LookupResponse beside each
  row (run_batch drops it, unchanged for its callers); collect_batch runs
  to completion in paste order and merges; BatchResult; rows_csv with
  CSV_COLUMNS mirroring frontend/src/lib/batch.ts.
- routers/batch.py: build_batch_zip reuses export._build_licenses_md and
  licensing.assess; the route is on the heavy tier, behind the same bot
  gate (message names /batch-export), robots-disallowed, and sets
  X-OpenCheck-Batch-Failed so a script can notice a partial batch without
  opening the archive.
- Frontend: fetchBatchExport (server's own words on 4xx, filename from
  Content-Disposition) and a "Download BODS bundle (zip)" button on
  /batch; /api page + docs/mcp-server.md updated.
- 6 tests: merge + dedupe + a failed row contributes nothing, rows.csv
  shape, union licence = strictest member, the route's zip + header, the
  gate/422/robots, the tier.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TF8feptbqf5yz3KoeDFQq
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TF8feptbqf5yz3KoeDFQq
@StephenAbbott
StephenAbbott merged commit 7ad7bc6 into main Sep 3, 2026
10 checks 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