Skip to content

Wire recommendations.v1 into the UI render surface and exports - #158

Merged
slittycode merged 2 commits into
mainfrom
claude/hopeful-galileo-o5nnxp
Jun 11, 2026
Merged

Wire recommendations.v1 into the UI render surface and exports#158
slittycode merged 2 commits into
mainfrom
claude/hopeful-galileo-o5nnxp

Conversation

@slittycode

Copy link
Copy Markdown
Owner

Summary

The backend projects Phase 2 device cards into the frozen, schema-validated, citation-gated recommendations.v1 envelope (ADR 0003) and attaches it to every producer_summary interpretation — but the UI never read it. RecommendationsContract existed in types/interpretation.ts as a definition only; the cards rendered from the raw arrays. This PR makes the envelope load-bearing on the user-facing surface.

What changed

New reader service — apps/ui/src/services/recommendationsContract.ts
Indexes the envelope so each raw device card can be paired with its validated contract entry. Pairing is by (device, parameter, normalized value): device+parameter alone is ambiguous when Phase 2 repeats a pair with different values, and a wrong pairing would surface a confidently-wrong working range — the exact failure mode the warn-only catalogue gate exists to prevent. The value parser is a deliberate TS mirror of the backend's parse_value (same cross-boundary duplication pattern as audio_mime.py / audioFile.ts), with a test case table pinned to the backend's documented examples so drift surfaces in CI.

Mix Chain + Patch cards (analysisResultsViewModel.ts, AnalysisResults.tsx)
Card view models now carry contractEntries. Cards backed by an entry render a "✓ Validated" chip in the header and, when expanded, a recommendations.v1 block with the normalized value and the contract's published working range (net-new information — the raw value string already renders in the parameter grid). Cards without a match are exactly the uncited cards the projection refused to admit, so the badge is the citation gate (PURPOSE.md invariant #2) made visible. Synthetic frontend-derived cards (limiter fallback, stereo width, MIDI Clip Guide) never match by construction.

Markdown export (exportUtils.ts)
New "Validated Recommendations (recommendations.v1)" table: device, parameter, normalized value, working range, cited measurements. The JSON export already carried the envelope verbatim inside phase2; no change needed there.

Not changed: the applied-recommendations tracker keeps its positional card ids — rekeying to contract entries would orphan existing localStorage progress, and the contract deliberately excludes uncited cards that still render (and still need tracking).

Verification

  • npm run lint (tsc) — clean
  • npm test — 782 passed, 4 skipped (includes new recommendationsContract.test.ts: parser mirror table, value-aware disambiguation, citation-gate absence; plus view-model and export coverage)
  • npm run build — green
  • Playwright smoke not runnable in this sandbox (cdn.playwright.dev blocked by the environment network allowlist) — relying on CI for the smoke gate

https://claude.ai/code/session_01Q8cG71HowqrHxa7dXJ5f3a


Generated by Claude Code

claude and others added 2 commits June 11, 2026 23:07
The backend has been projecting Phase 2 device cards into the frozen,
schema-validated, citation-gated recommendations.v1 envelope (ADR 0003)
and attaching it to every producer_summary interpretation — but no UI
code read it. The cards rendered from the raw arrays only, leaving the
validated projection decorative.

This makes the envelope load-bearing on three surfaces:

- New reader service (src/services/recommendationsContract.ts): indexes
  the envelope so each raw device card can be paired with its validated
  contract entry. Pairing is by (device, parameter, normalized value) —
  device+parameter alone is ambiguous when Phase 2 repeats a pair with
  different values, and a wrong pairing would surface a confidently-wrong
  working range. The value parser is a deliberate TS mirror of the
  backend's parse_value (same cross-boundary duplication pattern as
  audio_mime.py / audioFile.ts).

- Mix Chain + Patch cards: cards backed by a contract entry carry a
  "Validated" chip in the header and, expanded, a recommendations.v1
  block showing the normalized value and the published working range.
  Cards without a match are exactly the uncited cards the projection
  refused — the citation gate made visible. Synthetic frontend-derived
  cards (limiter fallback, stereo width, MIDI Clip Guide) never match
  by construction.

- Markdown export: a "Validated Recommendations (recommendations.v1)"
  table with device, parameter, normalized value, working range, and
  cited measurements. (The JSON export already carried the envelope
  verbatim inside phase2.)

Verified: tsc clean, full Vitest suite 782 passed, production build
green. Playwright smoke not runnable in this environment
(cdn.playwright.dev blocked by network allowlist).

https://claude.ai/code/session_01Q8cG71HowqrHxa7dXJ5f3a
@slittycode
slittycode force-pushed the claude/hopeful-galileo-o5nnxp branch from 03e62b6 to 60d7f43 Compare June 11, 2026 22:19
@slittycode
slittycode merged commit dd235a6 into main Jun 11, 2026
5 checks passed
@slittycode
slittycode deleted the claude/hopeful-galileo-o5nnxp branch June 11, 2026 22:31
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.

2 participants