Skip to main content

What the ResearchReport does not publish yet

The /chat result renders one record table — opportunities. It renders no supplier table and no market-history table, and it exports no renderer for either. This document is why, and what would have to land for each one. The rule behind it: a table over an array that is always empty is a promise the contract cannot keep. It reads as a feature with no data rather than as a feature that does not exist, and it teaches the reader that empty is normal.

The gap, exactly

apps/api/src/cognitive/market-research/research-report.contract.ts publishes:
There is no suppliers and no historicalRecords. The client’s ResearchReportView declares suppliers: SupplierResult[] and history: MarketHistoryResult[], and adapters.ts reads them from raw['suppliers'] / raw['history'] — a forward-compatible read, not a hard-coded empty. The day the server publishes either key it arrives typed and parsed. Until then both are [] on every run. This is the same pair listed as suppliers-in-report and history-rows-in-report in BACKEND_GAPS (intelligence/phases.ts).

Minimum structure each renderer needs

Neither renderer can be written against prose. A supplier row inferred from the answer text would be a structure the run never produced, attributed to a source that never published it — which is the failure the whole evidence model exists to prevent.

suppliers[] — for a supplier table

historicalRecords[] — for a market-history table

amount, currency and amountScope must travel together or not at all. The grouping helper that already exists (research/domains.tsx, groupAwards) refuses to subtotal a group where any amount is missing, and it needs the scope to know which rows may be added at all.

When tabs may return

/chat has no tabs. They may return only when the report carries at least two typed, populated domain collections in the same run — at which point a tab is a way to move between things that exist. A static tab per domain, present whether or not that domain has rows, is a domain selector wearing a different name: it makes the reader choose a domain before seeing anything, which is the manual-console paradigm this surface was built to replace.