- ?format=json on the v1 activity / outputs / decisions / stale-tasks export endpointsCloses the explicitly-named rev-120 next-sprint candidate. Until rev 121 the rev-120 v1 export endpoints were CSV-only โ MCP hosts wanting to pipe the procurement-evidence audit trail through their own analytics had to parse CSV. Rev 121 adds an optional `?format=json` query param to every rev-120 v1 export endpoint (activity, outputs, decisions, stale-tasks). CSV stays the default for backwards compatibility. The JSON variant returns typed `{ rows, total, capped }` payloads (with `since` / `until` for activity, `thresholdDays` for stale-tasks). Each pair of endpoints shares one row-fetcher helper (`getWorkspaceActivityRows`, `getWorkspaceArtifactsRows`, `getWorkspaceDecisionsRows`, plus the existing `getStaleTasks`) so the CSV takeaway artefact and the JSON-pipeline read can never drift. JSON projects `tags` as arrays (not the CSV `|`-joined string) and `publicShareUrl` as relative paths.
- ?format=json on /api/v1/workspace/sources-export and /api/v1/workspace/cost-exportCloses the v1 export JSON symmetry across the full six-axis procurement-evidence cluster (activity / outputs / decisions / stale-tasks / sources / cost). Sources JSON projects `includeKeywords` and `excludeKeywords` as arrays (not the CSV `|`-joined string) plus the rev-16 health diagnostic columns + rev-12 7-day signal-rate inline. Cost JSON returns a structured object grouped by axis (`{ daily, byTask, bySource, byAssignee, timezone, generatedAt }`) so MCP hosts and FinOps pipelines can render the cost summary without parsing the four-section CSV. New `getWorkspaceSourcesRows()` + `getWorkspaceCostSummary()` helpers query through the same per-axis getters the CSV uses so the two output formats can never drift. The procurement-evidence v1 cluster is now both CSV-takeaway-ready (procurement reviewers) AND JSON-pipeline-ready (MCP hosts) on every axis โ closes the protocol-bound side of the takeaway story.
- โ Caught up affordance on the rev-76 WhatsNewBadgeUntil rev 121 the only way to clear the rev-76 'N updates since you were last here' badge + the rev-76 per-row 'new' pills + the rev-120 per-bucket 'N new' pills was to wait for the rev-76 60-second `markWorkspaceVisited` throttle to tick on the next render โ operators landing on the dashboard, scanning the deltas, then wanting to dismiss them now had no one-click escape. Rev 121 adds an explicit `โ Caught up` button inside the rev-76 badge that POSTs to a new viewer+ `/api/workspace/mark-caught-up` endpoint, bypassing the throttle so every 'new' surface anchored to the operator's `lastVisitedAt` (badge / bucket pill / row pill / Only-new chip) collapses on the next render. Per-user-per-workspace โ an admin marking themselves caught up doesn't affect another admin's pills. Pairs naturally with the rev-120 per-bucket 'N new' pills as the explicit close-the-loop affordance.
- /docs page documents the new JSON format + cumulative trust-signal polish on the v1 self-describing indexEvery rev-120 v1 export entry on the self-describing index at `GET /api/v1` and the public docs page now names the `?format=csv|json` parameter inline so MCP-host code generators reading the index discover the JSON variant without having to read the changelog. Cumulative micro-polish โ every rev 22+ has carried at least one. Rev 121's polish is on the typed-contract surface itself: the index reads as authoritative with-or-without code generation, so the upcoming MCP server's wrapping work has nothing left to design on the procurement-evidence axis at any of the six axes (activity / outputs / decisions / stale-tasks / sources / cost) at either output shape (CSV / JSON).