Skip to Content

← All archived runs

Run: workspace-journey-lensing

run.md

Run: workspace-journey-lensing

  • branch: claude/workspace-journey-lensing-pipeline-l8zdvk
  • pr: #711

01_define/output/spec.md

Spec: Workspace journey lensing + lever reconciliation

  • slug: workspace-journey-lensing
  • personas: All (admin, CSM, SDM, expert, vendor, customer — the lead workspace is shared)
  • touches: packages/services/src/db/workflows/workflows.json, apps/web/components/workspace/journey-strip.tsx, apps/web/components/workspace/workspace-view.tsx
  • complexity: standard

Problem

The lead workspace is the best-ported surface between the demo and web apps — sections, order, intros and lever weights already align. Two gaps remain. First, demo's journey strip shows per-persona status nomenclature (a customer sees "Project Submitted", an SDM "New Project", an expert "Project Available"), while web's strip shows the generic displayName from the status service for everyone. This matters for the Q2 2026 O1 objective (human-in-the-loop vendor engagement, under the "Refine the Bridge" initiative): each persona should read the shared journey through its own lens rather than internal jargon. Second, the demo-vs-web lever catalogues differ, and the "forward advance is automatic" model and the demo-only vs web-only lever set have never been formally reconciled to one agreed catalogue — leaving the parity effort without a settled source of truth.

The infrastructure for per-persona labels already exists in web and is unused for the lead journey: workflows.json statuses support an optional per-persona labels map, and the status service's resolveStatusLabel(name, persona) / resolveStatusView(name, persona) already resolve it, falling back to displayName when absent. Today the lead spine statuses carry no labels, and JourneyStrip is not passed a persona — so the lens is never applied.

Proposed change

Port demo's per-persona STATUS_LABELS into web so each persona sees its own status wording on the journey strip, reusing web's existing per-persona label mechanism (no new resolution machinery):

  • Add a per-persona labels map (admin, csm, sdm, expert, vendor, customer) to each of the eight lead spine statuses in workflows.json (pending, backlog, quotation_process, awaiting_confirmation, work_in_progress, delivered, survey_sent, completed), using demo's STATUS_LABELS wording. qualified_out keeps its displayName fallback (demo has no per-persona wording for it either).
  • Pass the current persona into JourneyStrip from WorkspaceView, and render each spine and drop-off chip's label via the status service's persona-aware resolution instead of the raw displayName. The strip stays read-only over live data — not clickable-to-preview.

Reconcile the lever catalogue as a documented decision (no lever code changes this run):

  • Confirm the "forward spine is automatic" model as canonical: every forward stage advance happens implicitly through a satellite action (BRD sign-off, bid accept, quote accept, final invoice approve/pay, CSAT submit); qualify out is the only direct spine lever. Record this as intended in spec.md so it is not re-litigated.
  • Settle web's lever catalogue as canonical. Web's levers are grounded in real server actions and workflow gates; demo-only levers with no real workflow gate (brd.approve, lead.reject, expert.reassign, outreach.send) are design-fiction and are intentionally not ported. Web-only levers (match.override, match.add, proposal.archive, lead.clearRework, split assign-CSM/assign-SDM, lead.editOverview) stay. This decision is the reconciled catalogue.

Acceptance criteria

  • Each of the eight lead spine statuses in workflows.json carries a per-persona labels map (admin, csm, sdm, expert, vendor, customer) matching demo's STATUS_LABELS wording.
  • JourneyStrip receives the current persona from WorkspaceView and renders every spine and drop-off chip label through the status service's persona-aware resolution (per-persona label, falling back to displayName when a status has none).
  • A customer viewing a lead at pending sees "Project Submitted"; an SDM sees "New Project"; an expert sees "Project Available" (i.e. the lens is observably applied per persona).
  • qualified_out (and any status without a per-persona label) still renders its displayName.
  • The journey strip remains read-only (no click-to-preview added).
  • The spec records the two settled decisions: forward-spine-advance is automatic (qualify-out the only spine lever), and web's lever catalogue is canonical with the named demo-only levers intentionally not ported.

Out of scope

  • Making the journey strip clickable-to-preview in web (decided: keep read-only).
  • Any change to the lever catalogue code — adding demo-only levers, or removing web-only levers (decided: web catalogue is canonical; reconciliation is a documented decision, not a code change).
  • The workspace section set / order / intros (already at parity).
  • Per-persona wording for sub-workflow statuses (proposal/quote/milestone/invoice) — only the lead spine (+ its drop-off) is lensed this run.

Open questions

  • none

02_build/output/notes.md

Build notes: workspace-journey-lensing

  • commits: feat: workspace-journey-lensing — per-persona journey strip labels

What changed

  • packages/services/src/db/workflows/workflows.json: added a per-persona labels map (admin, csm, sdm, expert, vendor, customer) to each of the eight lead spine statuses (pending, backlog, quotation_process, awaiting_confirmation, work_in_progress, delivered, survey_sent, completed), using demo's STATUS_LABELS wording verbatim. qualified_out is left without labels — it falls back to displayName, matching demo (which has no per-persona wording for it).
  • apps/web/components/workspace/journey-strip.tsx: the strip now takes a persona prop and renders every spine and drop-off chip label via resolveStatusLabel(status.name, persona) (the workflow engine's persona-aware resolver, which falls back to displayName when a status has no per-persona label) instead of the raw displayName. Still read-only — no click-to-preview added.
  • apps/web/components/workspace/workspace-view.tsx: passes the current persona into JourneyStrip.

Reuse over new machinery

No new resolution code: web already supports per-persona labels end-to-end (workflows.json schema allows labels; resolveStatusLabel/resolveStatusView already resolve them). The lead spine simply had no labels populated and the strip wasn't passed a persona. This build fills that gap — a data addition plus one prop.

Acceptance criteria status

  • Each of the eight lead spine statuses in workflows.json carries a per-persona labels map (admin, csm, sdm, expert, vendor, customer) matching demo's STATUS_LABELS wording — verified all six keys present on all eight statuses.
  • JourneyStrip receives the current persona from WorkspaceView and renders every spine and drop-off chip label through resolveStatusLabel (per-persona, falling back to displayName).
  • A customer at pending sees "Project Submitted"; an SDM sees "New Project"; an expert sees "Project Available" — these are the pending labels ported from demo.
  • qualified_out (and any status without a per-persona label) still renders its displayNamequalified_out has no labels, so resolveStatusLabel returns displayName.
  • The journey strip remains read-only — no click-to-preview added.
  • The spec records the two settled decisions (forward-spine-automatic; web's lever catalogue canonical with the named demo-only levers intentionally not ported) — captured in spec.md Proposed change / Out of scope.

Verify result

  • mechanical checks (format · lint · typecheck · build) run in CI + the Vercel preview, not here. Release reads them back from the PR's check runs. No check is expected to fail.

Notes for review

  • The label strings are demo's STATUS_LABELS wording verbatim (e.g. "Project Submitted", "New Project"). These are intentional per-persona status nomenclature, not generic UI copy — kept exactly as the design source to preserve parity, so they retain demo's title-case phrasing rather than being re-cased.
  • persona is web's UserRole (re-exported from @sustentus/services/shared), the same canonical type the workflow engine's Persona alias resolves to — so the label lookup is type-safe with no cast.
  • Only the lead spine (+ its drop-off chip) is lensed; sub-workflow statuses (proposal/quote/milestone/invoice) keep displayName (out of scope).

03_release/output/changelog.md

The lead journey now speaks your language

The journey strip on a lead now reads in wording tuned to your role, not internal jargon. At the first stage a customer sees "Project submitted", an SDM "New project", and an expert "Project available" — the same shared journey, each of you seeing the step in the terms that make sense for your work. You can now follow where a lead sits at a glance without translating someone else's labels.

03_release/output/investor-update.md

The lead journey now reads in each role's own language

Who it's for: All six personas — admin, CSM, SDM, expert, vendor, customer What shipped: The lead workspace journey strip now shows each persona its own status wording instead of one generic label. Why it matters: Clearer journeys at every touchpoint — the interaction-quality goal of the Refine the Bridge initiative, supporting Q2's vendor-engagement objective.

Dig deeper: <merged-PR URL> · <changelog entry URL>