Why this helps
Assurance action pages already carry pcs_claim_id on nodes (AssuranceNode in portal/lib/assuranceTypes.ts), and the portal has /pcs/claims/[claimId]. The action UI never surfaces those IDs as links, so readers cannot jump from an action chain to the portable PCS evidence layer. Small UX polish that makes the assurance/PCS boundary obvious for first-time explorers.
Scope
On /assurance/actions/[actionId], when a node (or chronology entry) has a non-null pcs_claim_id, render a link to /pcs/claims/<id>. Keep existing non-claim copy. Prefer reading only from portal/.generated/assurance-export.json (no new fetch paths).
Suggested starting points
portal/components/assurance/AssuranceActionPage.tsx (NodeList, chronology, authority list)
portal/lib/assuranceTypes.ts (pcs_claim_id on AssuranceNode)
portal/app/assurance/actions/[actionId]/page.tsx
portal/app/pcs/claims/[claimId]/ (target route)
pipeline/src/sm_pipeline/assurance/export/__init__.py (confirm export already includes pcs_claim_id when present)
- Optional smoke:
portal/scripts/verify-assurance-export.mjs
Acceptance criteria
Non-goals
- Importing or validating nested PCS bundles (separate issue)
- New assurance export schema fields beyond what export already emits
- Redesigning the full
/assurance IA or adding a metrics dashboard
How to test
uv run --project pipeline sm export-assurance-portal-data
pnpm --dir portal lint
pnpm --dir portal build
pnpm --dir portal exec node scripts/verify-assurance-export.mjs
just portal
# Open /assurance/actions/<id> for an action whose export nodes include pcs_claim_id
# (may require a fixture/corpus chain that sets pcs_claim_id; if pilots use mode=none,
# add a minimal test fixture or use an existing PCS-linked node in a local export)
If you need a fixture with pcs_claim_id populated and none exists yet, keep the fixture change minimal and document it in the PR.
Why this helps
Assurance action pages already carry
pcs_claim_idon nodes (AssuranceNodeinportal/lib/assuranceTypes.ts), and the portal has/pcs/claims/[claimId]. The action UI never surfaces those IDs as links, so readers cannot jump from an action chain to the portable PCS evidence layer. Small UX polish that makes the assurance/PCS boundary obvious for first-time explorers.Scope
On
/assurance/actions/[actionId], when a node (or chronology entry) has a non-nullpcs_claim_id, render a link to/pcs/claims/<id>. Keep existing non-claim copy. Prefer reading only fromportal/.generated/assurance-export.json(no new fetch paths).Suggested starting points
portal/components/assurance/AssuranceActionPage.tsx(NodeList, chronology, authority list)portal/lib/assuranceTypes.ts(pcs_claim_idonAssuranceNode)portal/app/assurance/actions/[actionId]/page.tsxportal/app/pcs/claims/[claimId]/(target route)pipeline/src/sm_pipeline/assurance/export/__init__.py(confirm export already includespcs_claim_idwhen present)portal/scripts/verify-assurance-export.mjsAcceptance criteria
pcs_claim_idshow a navigable link to/pcs/claims/<pcs_claim_id>pcs_claim_idbehave as today (no broken empty links)Non-goals
/assuranceIA or adding a metrics dashboardHow to test
If you need a fixture with
pcs_claim_idpopulated and none exists yet, keep the fixture change minimal and document it in the PR.