Bid amendment arrives
Bid responses are amended frequently. B5875 (NYC DOE) hit Amendment 13 in the SY2026 cycle alone. Each amendment can change line specs, quantities, or terms — and the response has to reflect those changes within a tight clock.
This workflow runs the diff so Mike doesn't have to. The amendment doc parses, the lines diff against the prior version, changed lines get re-costed, the affected spec sheets regenerate, and the hub UI cache busts so the bid response page renders the new state.
Risk level 3 (medium). The cascade table list is bid_lines, bids, spec_versions, ns_pending_pushes.
Trigger conditions
- Email arrives at the bids@ mailbox with an amendment attachment.
- A portal webhook fires from a customer's bid system (NYC DOE, NJDOA, etc).
- Mike manually uploads an amendment from /intake.html when an email gets routed wrong.
- A reconciliation cron detects an amendment number gap (e.g. last seen 11, current 13).
The amendment_sequential precondition warns if the new amendment number is not exactly prior + 1. This catches the "did we miss amendment 12?" case that bit us during the SY2025 cycle.
The 3 beats
-
01
Update bid_lines for changed entries
Changed lines UPDATE in place, new lines INSERT, removed lines set
deleted_at=now. The bid_lines table is the source of truth for the bid response render. -
02
Regenerate affected spec sheets
For any spec referenced by changed lines, a POST to
/api/spec/regeneraterebuilds the PDF and stores it in R2. -
03
Invalidate hub UI cache
Keys
hub:nycdoe:bid_{bid_id}andhub:bids:summaryare deleted. Next hub render pulls fresh state from D1.
What's different after the workflow runs
bid_linesreflects the amendment's adds, updates, and soft-deletes.- Affected spec sheets are regenerated and the new R2 keys point from the hub.
- The bid hub page (e.g. /nycdoe-hub) shows the amendment within 60 seconds.
- An amendment delta summary artifact is produced for Mike's pre-submission review.
- reflexion_log carries a
bid_amendmenttagged row with the bid_id.
What can go wrong and how to recover
Precondition warns but doesn't block. Mike checks the bids@ inbox for the missing amendment. If genuinely skipped by the issuer, override the warn and continue.
Browser Rendering exceeds 30s on a large spec. Old PDF stays in R2; manual POST /api/spec/regenerate?item_code=<code> retries.
Precondition blocks at bid.status NOT IN (open, pending_submission). Amendment to a closed bid is meaningless; the email-routing layer logs it for awareness.
KV propagation occasionally takes 60s+. If a customer-facing render still shows the old state after 2 minutes, manual POST /admin/hub/invalidate?key=<k> retries.
Adjacent workflows + diagrams
Code paths + invariants
| Concern | Where |
|---|---|
| Workflow contract | workflow_definitions WHERE workflow_type='bid_amendment_arrives' |
| Amendment doc parser | src/document_converter.ts (PDF/DOCX → MD) |
| Diff engine | src/chat_tools/impls.ts → bid_lines diff |
| Hub cache keys | hub:nycdoe:bid_<bid_id>, hub:bids:summary |
| Reflexion tag | bid_amendment, bid_id:<id> |
| Risk level | 3 |
| Expected duration | ~30 min |
| Trigger | event · sources=email_intake, manual_upload, portal_webhook |