Merged PR 2404: case stage analysis

Related work items: #23754
This commit is contained in:
Robert Bond
2026-06-18 16:02:40 +00:00
parent 81a6276f44
commit 60a2ff4594
6 changed files with 941 additions and 7 deletions
+26 -4
View File
@@ -17,6 +17,8 @@ PEDW is in a **late-stage refactor stabilization** phase.
- Broad endpoint contract hardening completed across key clusters.
- Representation Participation Availability investigation completed from a technical discovery/documentation perspective.
- Representation participation behaviour is now documented as one coherent decision model with layered appeal-type, specialist-process, participant-type, consultation, and date-window exceptions.
- CRM Case Progress Display investigation completed from a technical discovery/documentation perspective.
- Case Status tab behaviour is now understood as a portal-owned journey interpretation layer driven by CRM `statuscode`, appeal type, and Rights of Way specialist-process routing.
- Source documents added:
- `docs/representation-participation-availability.md` (developers / architects / maintainers)
- `docs/representation-participation-business-review.md` (business / product / SME validation)
@@ -51,8 +53,28 @@ Top active risks:
- Known divergences and compatibility-sensitive behaviours are documented and should be preserved unless an explicit business decision authorizes change.
- Current state: awaiting business validation of `docs/representation-participation-business-review.md` before any further representation-policy adoption, expansion, or behavioural change work.
## Next likely discovery candidate
## CRM Case Progress Display — Current State
- **Case Lifecycle / Status Decision Model Discovery**
- Investigate how the portal interprets case progress, stages, statuses, closed states, dashboard grouping, and user-facing lifecycle messaging.
- Treat this as discovery only until the new representation participation documentation has been reviewed and business validation feedback is available.
- Technical investigation stream is complete.
- Current architectural conclusion: do **not** treat this area as a new business-policy domain boundary.
- The Case Status tab is best understood as a **portal-owned journey interpretation layer**:
- inputs: CRM `statuscode`, appeal type, specialist process (Rights of Way only)
- resolution model: journey catalogue selection -> user-facing journey representation
- `pinswg_casestage` is not a significant active input to the current status-tab model:
- it was historically associated with DNS/SIPS summary support
- it is not part of active lifecycle resolution for the status tab
- Stage catalogues are best understood as:
- user-facing journey models
- appeal-type interpretation models
- presentation-layer progress visualisation
- Shared catalogue families exist (`PLANNING_S78`, `ENFORCEMENT`, `DNS/SIP`, Rights of Way specialist-process variants) and represent a mixture of:
- genuine shared journey structures
- presentation reuse
- historical consolidation
## Discovery candidate update
- Case Lifecycle / Status Decision Model Discovery is no longer an open next-candidate investigation.
- Current conclusion from the completed CRM Case Progress Display stream:
- this area is primarily presentation architecture + journey interpretation
- further work should only be reopened if a new business-validation or behavioural-change question emerges
+38
View File
@@ -18,6 +18,44 @@ Follow-ups:
---
### CL-2026-06-18-CRM-CASE-PROGRESS-CONTEXT: record CRM Case Progress Display investigation conclusions
date: 2026-06-18
author: Cline
scope: `context/current-platform-state.md`, `memory-bank/{techContext,productContext,change-log}.md`
type: change
rationale: Preserve the completed CRM Case Progress Display investigation conclusions in project context so future contributors do not re-open the same status/lifecycle ambiguity without need.
impact: Documentation/context only; improves architectural clarity around case status display ownership and inputs; no runtime, auth, i18n, API, or behaviour change.
status: completed
Summary:
- Updated project context to record that the Case Status tab is a portal-owned journey interpretation layer.
- Recorded the active input model as:
- CRM `statuscode`
- appeal type
- specialist process (Rights of Way only)
- Recorded that `pinswg_casestage` is not a significant active input to current status-tab lifecycle resolution.
- Recorded that stage catalogues are best understood as:
- user-facing journey models
- appeal-type interpretation models
- presentation-layer progress visualization
- Recorded that shared catalogue families (`PLANNING_S78`, `ENFORCEMENT`, `DNS/SIP`, Rights of Way specialist-process variants) reflect a mixture of shared journey structures, presentation reuse, and historical consolidation.
- Recorded the architectural conclusion that this area is presentation architecture / journey interpretation, not a new business-policy domain boundary candidate.
Validation:
- Documentation/context update only.
- No application code changed.
- No tests changed.
- Lint/tests skipped because this was documentation-only work.
Follow-ups:
- Reopen only if a future business-validation or behaviour-change initiative requires deeper lifecycle/status decision work.
---
### CL-2026-06-18-RPA-DOCS: representation participation availability documentation + context update
date: 2026-06-18
+17 -3
View File
@@ -26,6 +26,7 @@
## Business logic patterns visible in code
- Case summary UI varies by appeal type and case attributes.
- Case status/progress display is portal-shaped rather than a raw CRM passthrough: the portal selects a journey catalogue from CRM `statuscode`, appeal type, and limited Rights of Way specialist-process input to present user-facing progress.
- Representation actions are conditionally shown by appeal type, role, and date windows.
- Representation participation now appears to form one broader business decision model: whether a participant can engage in representation or consultation activity for a case at that point in the process.
- Locale-sensitive behavior affects links, routes, labels, and email template choice.
@@ -40,11 +41,24 @@
- `docs/representation-participation-availability.md`
- `docs/representation-participation-business-review.md`
## Current case progress display state
- Technical investigation for CRM Case Progress Display is complete.
- Current behaviour is best understood as a **user-facing journey representation**, not a business-policy decision model.
- The Case Status tab is driven by:
- CRM `statuscode`
- appeal type
- specialist process for Rights of Way variants only
- `pinswg_casestage` should not currently be treated as a significant input to status-tab lifecycle behaviour.
- Shared catalogue families exist and reflect a mixture of:
- genuine shared journey structures
- presentation reuse
- historical consolidation
## Likely next discovery candidate
- Case Lifecycle / Status Decision Model Discovery
- expected focus: case progress, stages, statuses, closed states, dashboard grouping, and lifecycle messaging
- should be treated as discovery-only pending review of the new representation participation documentation
- No immediate successor discovery candidate is implied by the completed CRM Case Progress Display stream.
- If reopened later, work should focus on business validation or future behavioural change questions rather than first-pass technical characterization.
## Important user-facing behaviors
+9
View File
@@ -54,6 +54,15 @@
- representation participation is best understood as one coherent decision model with layered exceptions
- known consumer divergences and CRM compatibility behaviours are part of the current live contract
- future technical adoption/expansion work should wait for business validation before changing behaviour or broadening policy boundaries
- CRM Case Progress Display investigation has now been concluded as a technical characterization stream.
- Current technical conclusion:
- the Case Status tab is a portal-owned journey interpretation layer
- active inputs are CRM `statuscode`, appeal type, and Rights of Way specialist-process routing only
- `pinswg_casestage` is not a significant active input to status-tab lifecycle resolution
- stage catalogues are not raw CRM lifecycle states and not business-policy decision models
- stage catalogues are best understood as user-facing journey models plus appeal-type interpretation plus presentation-layer progress visualization
- shared catalogue families (`PLANNING_S78`, `ENFORCEMENT`, `DNS/SIP`, Rights of Way specialist-process variants) reflect a mixture of shared journey semantics, presentation reuse, and historical consolidation
- this area is not currently a candidate for a new business-policy domain boundary
## CI/CD and deployment artifacts
@@ -0,0 +1,564 @@
## Case Status Tab Stage Display Characterization
### 1. Purpose
This report characterizes how the portal determines and renders the visual case progress journey shown on the **Case Status** tab.
Scope is limited to the case status tab and directly related stage-display behaviour.
This is discovery/documentation only. It does not propose implementation changes, refactoring, field normalization, or new domain policy.
---
### 2. Business context
- `statuscode` is the standard CRM/Dataverse Incident status field.
- `pinswg_casestage` is a PEDW custom field used to represent more detailed PEDW case-stage information than the standard CRM status model alone provides.
- The portal presents visual case progression to users through the **Case Status** tab.
- The same broader area also exposes status/stage information elsewhere, including summary/details and search-result consumers.
- Current repository evidence shows these consumers do **not** all use the same source field or the same interpretation model.
---
### 3. Status tab rendering flow
#### 3.1 CRM inputs fetched on case page load
The public case page loader in `pages/case/[ticketnumber].js` fetches:
1. `searchResultsObj` via `getBasicSearch(...)`
2. `searchDetailsObj` via `getSearchDetails(searchResultsObj)`
Relevant CRM-derived inputs then get stored into `currentView.caseReference` using `setCurrentReference(...)`:
- `statuscode`
- `ticketnumber`
- `incidentid`
- `pinswg_appealcasetype` as `appealType`
- normalized specialist process from `searchDetailsObj[0].value[0]`
Code reference:
- `pages/case/[ticketnumber].js:213-229`
This means the status-tab journey is seeded primarily from:
- CRM `statuscode`
- CRM appeal type
- CRM specialist-process fields after portal-side normalization
#### 3.2 Specialist-process normalization before rendering
`pages/case/[ticketnumber].js` calls:
```js
normalizeSpecialistProcess(searchDetailsObj[0].value[0]);
```
`normalizeSpecialistProcess(...)` resolves specialist process by preferring:
1. `pinswg_specialistcaseprocess`
2. `pinswg_speacialistcaseprocess`
3. empty string fallback
Code references:
- `pages/case/[ticketnumber].js:225-227`
- `lib/domain/case-lifecycle/normalizeSpecialistProcess.js:1-7`
This is a CRM compatibility step, not a semantic reinterpretation step.
#### 3.3 Case summary hosts the Case Status tab
`components/case/summary.js` owns the tab structure and mounts the status-tab component.
- The tab key is `case-status`
- The tab panel renders `<StatusDetails />`
Code evidence:
- `components/case/summary.js` contains the selected tab state `whichTab == "case-status"`
- `components/case/summary.js` renders `<StatusDetails />`
#### 3.4 StatusDetails builds the stage journey
`components/case/status.js` reads from Redux/currentView and invokes:
```js
getLifecycleStagesForCase(
props.currentView?.caseReference?.appealType,
props.currentView?.caseReference?.statuscode,
specialistProcess
);
```
Important points:
- The second argument is named `currentStageId` in the lifecycle seam, but the actual caller passes **CRM `statuscode`**.
- The component does **not** use `pinswg_casestage`.
- `specialistProcess` is read again from `props.searchResultsObj?.searchDetailsObj[0]?.value[0]?.pinswg_specialistcaseprocess`, i.e. only the canonical field in this component.
Code reference:
- `components/case/status.js:26-36`
#### 3.5 Lifecycle seam delegates to legacy stage-catalogue helper
`getLifecycleStagesForCase(...)` is a thin wrapper:
```js
return getStagesForAppealType(caseType, currentStageId, specialistProcess);
```
Code reference:
- `lib/domain/case-lifecycle/getLifecycleStagesForCase.js:1-9`
This confirms the lifecycle seam is currently a read-only indirection layer, not an independently owned lifecycle engine.
#### 3.6 Stage catalogue selection
`getStagesForAppealType(...)` in `components/case/summary/utils/caseStagesByAppealType.js`:
1. resolves a stage key using `getStageCaseTypeKey(...)`
2. loads the stage array with `getStagesForCaseTypeKey(...)`
3. finds the current stage index with `getLifecycleStageIndex(...)`
4. marks each stage `complete`, `in-progress`, or `not-started` with `getLifecycleStageStatus(...)`
Code references:
- `components/case/summary/utils/caseStagesByAppealType.js:779-796`
#### 3.7 Stage journey rendering
`components/case/status.js` renders the returned stage array as a GOV.UK task-list style visual journey:
- each stage renders translated `titleKey`
- each stage can show `descriptionKey` in expandable details
- each stage gets a status tag:
- `complete`
- `in-progress`
- `not-started`
- `blocked` is defined in the map, though current lifecycle helper path does not produce it
Code references:
- `components/case/status.js:9-21`
- `components/case/status.js:80-137`
#### Rendering-flow summary
CRM data flow to rendered journey is:
```text
CRM incident/search query
-> searchResultsObj.statuscode
-> searchResultsObj.pinswg_appealcasetype
-> searchDetailsObj specialist-process field(s)
-> setCurrentReference(...) on case page
-> StatusDetails reads currentView.caseReference
-> getLifecycleStagesForCase(...)
-> getStagesForAppealType(...)
-> getStageCaseTypeKey(...)
-> getStagesForCaseTypeKey(...)
-> getLifecycleStageIndex(...)
-> getLifecycleStageStatus(...)
-> rendered task-list stage journey
```
---
### 4. Field role assessment
#### `statuscode`
**Where used**
- stored into `currentView.caseReference` on case page load (`pages/case/[ticketnumber].js`)
- used as the current stage input for `getLifecycleStagesForCase(...)` (`components/case/status.js`)
- displayed directly as formatted status labels in search results, summary-type components, my portal, and admin/reporting consumers
- mapped in `components/utils/caseStagesObj.js`
**Purpose**
- operational CRM status field
- primary input for status-tab current-stage resolution
- direct formatted label source for many non-status-tab consumers
**Display impact**
- determines which step in the visual stage journey is marked as current/completed/future
- also appears directly as human-readable status labels outside the journey UI
#### `pinswg_casestage`
**Where used**
- displayed in `components/case/summary.js` as a summary row labelled `summary-case-stage-label`
**Purpose**
- PEDW custom case-stage field
- summary/details informational display field
**Display impact**
- affects the summary/details panel only in the reviewed path
- does **not** drive the Case Status tab journey in the current implementation
#### Appeal type fields
**Where used**
- `pinswg_appealcasetype` stored as `appealType` in `currentView.caseReference`
- mapped through `mapAppealType(...)`
- used to choose the stage catalogue and, in some cases, specialist-process override logic
**Purpose**
- primary selector of the stage-journey family/catalogue
**Display impact**
- determines which stage list the user sees
- appeal types can share or diverge in stage journeys depending on mappings/aliases
#### Specialist process fields
**Where used**
- normalized in `pages/case/[ticketnumber].js` from canonical/misspelled CRM fields
- re-read in `components/case/status.js` from canonical field only
- passed to `getStageCaseTypeKey(...)`
- used by `mapSpecialistProcessStageType(...)` for stage-journey override
**Purpose**
- refine stage-journey selection for selected appeal types, especially Rights of Way variants
**Display impact**
- can switch the status-tab journey from one stage catalogue to another
- affects selection, not just labels
#### Closed/terminal status fields
**Where used**
- `isClosedCaseStatus(...)` treats these values as closed/terminal:
- `1000`
- `5`
- `6`
- `846040013`
- `846040060`
- `846040059`
**Purpose**
- fallback mechanism when the current numeric input does not exactly match a stage in the selected catalogue
**Display impact**
- if the supplied `statuscode` is considered closed, current stage resolves to the stage whose `titleKey === "case-closed"`
- otherwise unmatched values produce `currentIndex === -1`, making all stages render as `not-started`
---
### 5. Stage journey selection
#### 5.1 Appeal-type selection
The portal selects a stage journey first through `mapAppealType(...)` and `caseTypeKeyByAppealTypeId`.
Examples:
- `846040000` -> `PLANNING_S78`
- `846040010` -> `CALL_INS`
- `846040018` -> `ADVERTS`
- `846040019` -> `COMPULSORY_PURCHASE_ORDERS`
- `846040002` -> `SIP`
- `846040011` -> `DNS`
Code reference:
- `lib/domain/case-lifecycle/mapAppealType.js:35-80`
#### 5.2 Appeal-family / alias behaviour
Some stage journeys are shared by alias or indirection rather than unique arrays.
Examples:
- `SIP` resolves by string indirection to `DNS`
- `CONDITIONS_73_79`, `LBCAC`, `LDCS`, `PLANNING_OBLIGATIONS_S106`, `PRIOR_NOTIFICATION` all share `PLANNING_S78`
- `ENFORCEMENT_LISTED_BUILDING` and `MAINTENANCE_OF_LAND` share `ENFORCEMENT`
This is handled by:
- alias mapping in `mapAppealType.js`
- string indirection in `getStagesForCaseTypeKey.js`
#### 5.3 Specialist-process selection
`getStageCaseTypeKey(...)` only applies specialist-process override when the numeric appeal-type mapping is the one in play:
```js
caseTypeKeyByAppealTypeId[appealTypeId] === mappedCaseType
? mapSpecialistProcessStageType(mappedCaseType, specialistProcess)
: undefined;
```
Current override table only exists for `RIGHTS_OF_WAY_SCHEDULE_14`, mapping specialist-process values into:
- `RIGHTS_OF_WAY_ORDERS`
- `RIGHTS_OF_WAY_SCHEDULE_14`
- `REQUESTS_FOR_DIRECTION`
Code references:
- `lib/domain/case-lifecycle/getStageCaseTypeKey.js:9-25`
- `lib/domain/case-lifecycle/mapSpecialistProcessStageType.js:1-19`
#### 5.4 Fallback behaviour
Fallback order in `getStageCaseTypeKey(...)` is:
1. specialist-process-derived stage key
2. mapped appeal type key
3. alias lookup from normalized input
4. normalized raw input
Then `getStagesForCaseTypeKey(...)`:
- returns `[]` when no entry exists
- resolves string indirection to another catalogue
- otherwise returns the array directly
#### Selection classification
Selection appears **mixed**:
- **CRM-driven:** because appeal type and specialist process are CRM inputs
- **presentation-driven:** because the output is selection of a visual journey catalogue with title/description text
- **business-driven:** partially, because different appeal types and specialist processes are clearly treated as meaningfully different journeys
- **not purely CRM status display:** because the portal constructs a catalogue-driven journey rather than simply displaying a single CRM status value
---
### 6. Current stage resolution
#### 6.1 Exact status matching
`getLifecycleStageIndex(...)` converts the incoming current value to a number and tries to find a stage whose `stageId` exactly matches it.
```js
const exactIndex = stages.findIndex(
(stage) => Number(stage.stageId) === currentStageNumber
);
```
This means the status-tab journey currently treats the passed `statuscode` as the numeric identifier to align with stage-catalogue `stageId` values.
#### 6.2 Closed-stage fallback
If exact matching fails, `isClosedCaseStatus(...)` is consulted.
If true, current index becomes the index of the stage whose `titleKey` is `case-closed`.
This is a special fallback path for terminal/closed values rather than exact stage matching.
#### 6.3 Unmatched status handling
If there is no exact match and the value is not recognized as closed, `getLifecycleStageIndex(...)` returns `-1`.
Then `getLifecycleStageStatus(...)` marks **all** stages as `not-started`.
That is important characterized behaviour.
#### 6.4 Completed/current/future stage calculation
`getLifecycleStageStatus(index, currentIndex)` returns:
- `complete` when `index < currentIndex`
- `in-progress` when `index === currentIndex`
- `not-started` when `index > currentIndex`
- `not-started` for all stages when `currentIndex === -1`
#### 6.5 Blocked behaviour
`components/case/status.js` includes `blocked` style/text mappings, but the lifecycle calculation path reviewed here never returns `blocked`.
This suggests either legacy/future intent or another non-reviewed path, but not active current-stage calculation from the status-tab helper chain.
---
### 7. Consumer comparison
#### Case Status Tab
Displays:
- **stage journey:** yes
- **CRM status:** indirectly, as the input driving current stage selection
- **custom case stage (`pinswg_casestage`):** no
- **formatted labels:** yes, but as translated stage titles/descriptions and progress tags, not CRM formatted status labels
- **derived values:** yes, complete/in-progress/not-started status is portal-derived
Primary inputs:
- `statuscode`
- appeal type
- specialist process
#### Case Details / Summary
Displays:
- **CRM status:** yes, via summary-type components using `statuscode@OData.Community.Display.V1.FormattedValue`
- **custom case stage:** yes, in `components/case/summary.js` via `pinswg_casestage@OData.Community.Display.V1.FormattedValue`
- **stage journey:** yes, but only through the separate Case Status tab component
- **formatted labels:** yes
- **derived values:** limited; mostly direct display of CRM formatted values
Important distinction:
- summary/details panel uses `pinswg_casestage` directly for one row
- status tab uses `statuscode`-driven stage-journey derivation
#### Search Results
Displays:
- **CRM status:** yes, direct formatted value via `statuscode@OData.Community.Display.V1.FormattedValue`
- **custom case stage:** no evidence in reviewed search results path
- **stage journey:** no
- **formatted labels:** yes
- **derived values:** no stage derivation; mostly direct CRM-formatted display
Additional role:
- clicking a search result seeds `currentView.caseReference.statuscode`, appeal type, and specialist process for downstream case-page/status-tab behaviour
---
### 8. Divergence catalogue
#### Divergence 1: Status tab uses `statuscode`, summary row uses `pinswg_casestage`
- **Behaviour:** summary/details can display PEDW custom case stage while the Case Status tab derives its journey from `statuscode`.
- **Likely reason:** summary row is informational display of a custom PEDW field; status tab is a portal-constructed journey over a separate stage catalogue.
- **Appears intentional?** **No / unclear**. It is clearly implemented, but the repository does not prove this distinction is consciously documented as an intentional model boundary.
#### Divergence 2: Status tab renders derived journey; search results render direct formatted status label
- **Behaviour:** search results show `statuscode@OData.Community.Display.V1.FormattedValue`, while the case status tab shows a multi-step journey.
- **Likely reason:** search results need compact list display; case page gives richer progress visualization.
- **Appears intentional?** **Yes**, at presentation level.
#### Divergence 3: Specialist-process normalization differs between case page and status tab component
- **Behaviour:**
- case page uses `normalizeSpecialistProcess(...)` with canonical + misspelled fallback
- `components/case/status.js` reads only `pinswg_specialistcaseprocess`
- **Likely reason:** partial refactor / mixed old-new access patterns.
- **Appears intentional?** **No** based on current evidence.
#### Divergence 4: Summary/status consumers display different concepts under similar “status/stage” area
- **Behaviour:** summary-type components use formatted `statuscode`; summary row separately uses `pinswg_casestage`; status tab ignores `pinswg_casestage` and derives stage journey from `statuscode`.
- **Likely reason:** mixture of CRM operational status display and PEDW custom stage display without one unified presentation model.
- **Appears intentional?** **Unclear**.
#### Divergence 5: Closed-state handling is explicit in journey logic but not equivalent in direct status consumers
- **Behaviour:** status tab has a special closed-case fallback through `isClosedCaseStatus(...)`; direct status-label consumers simply display CRM formatted values.
- **Likely reason:** journey UI requires a terminal visual state even when exact stage IDs do not match.
- **Appears intentional?** **Probably yes** for the journey component, though the exact closed-value set may be compatibility-driven.
#### Divergence 6: Unmatched status values collapse whole journey to `not-started`
- **Behaviour:** if a `statuscode` does not match any stage ID and is not considered closed, every stage renders as `not-started`.
- **Likely reason:** simple index-based implementation with no fallback “unknown current stage” state.
- **Appears intentional?** **No / unclear**; more likely inherited behaviour.
---
### 9. Characterization test candidates
#### High Priority
1. **Case page seeds status tab inputs correctly**
- protect that `statuscode`, appeal type, and normalized specialist process are placed into `currentView.caseReference`
2. **Stage catalogue selection by appeal type**
- representative coverage for shared and distinct catalogues (e.g. S78, Call-in, DNS, Advert, CPO)
3. **Specialist-process override selection**
- protect current Rights of Way specialist-process remapping into alternate stage journeys
4. **Exact status-to-stage matching**
- prove that matching `statuscode` selects the expected current stage index
5. **Closed-case fallback behaviour**
- prove unmatched closed values map to `case-closed`
6. **Unmatched non-closed status behaviour**
- prove all stages become `not-started`
7. **Status tab ignores `pinswg_casestage`**
- protect current separation between status-tab journey logic and custom case-stage summary display
#### Medium Priority
1. **String vs numeric appeal type handling in stage selection**
2. **Alias/indirection resolution**
- e.g. `SIP -> DNS`, `ENFORCEMENT_LISTED_BUILDING -> ENFORCEMENT`
3. **Specialist-process normalization divergence coverage**
- protect current canonical vs misspelled field handling at case-page input stage
4. **Representative summary/status/search comparison tests**
- prove summary row uses `pinswg_casestage`, search uses formatted `statuscode`, status tab uses derived journey
#### Low Priority
1. **Expand-all/default-open UI behaviour on the status tab**
2. **Presence/absence of description keys in journey rendering**
3. **Translation-key coverage for representative stage catalogues**
---
### 10. Initial conclusion
**Answer: C. Portal-constructed visual journey based on CRM inputs**
#### Supporting evidence
- The Case Status tab does **not** directly display `pinswg_casestage`.
- It does **not** simply render CRM formatted `statuscode` labels.
- Instead, it uses CRM `statuscode`, appeal type, and specialist process to select a portal-owned stage catalogue and then derive progress state across that catalogue.
- The selected catalogue contains portal presentation metadata (`titleKey`, `descriptionKey`) and is rendered as a visual journey/task list.
- `pinswg_casestage` is displayed elsewhere in summary/details as a separate PEDW custom field, which further shows that the Case Status tab is a constructed layer rather than a simple raw-field display.
Therefore the Case Status tab is best understood as:
> a portal-constructed visual journey that uses CRM operational inputs and portal stage catalogues to present case progression to the user.
It is **not** a pure CRM status display, and it is **not** currently a pure PEDW custom case-stage display either.
---
### 11. Recommended next step
Keep the next slice narrow and characterization-focused.
The strongest follow-on is:
1. characterize **summary/details/search divergence** around:
- `statuscode`
- `pinswg_casestage`
- formatted labels
- specialist-process field usage
Reason:
- this slice established how the Case Status tab works internally
- the remaining ambiguity now sits at the cross-consumer boundary, especially where summary/details and search display different lifecycle/status concepts from the status-tab journey
@@ -0,0 +1,287 @@
## CRM Case Progress Display Planning Review Assessment
Active branch: `feature/crm-case-progress-display-planning`
Assessment scope: planning-only review of existing repository evidence to assess whether CRM Case Progress Display should become a formal investigation stream.
---
## 1. What has already been discovered?
### Known facts
- CRM is the system of record for case progression and status; the portal consumes CRM state through relay-backed API queries rather than owning the operational progression itself.
- The portal already uses CRM-owned `statuscode` widely across public search, case summary, my portal, watched cases, admin dashboards, and lifecycle display.
- The portal also reads `pinswg_casestage` directly in case summary presentation, indicating that both stage-like and status-like CRM fields already influence the UI.
- The portal contains a read-only lifecycle interpretation seam in `lib/domain/case-lifecycle`, but that boundary explicitly does **not** claim ownership of lifecycle semantics, progress/status calculation ownership, dashboard behaviour, or closed-case handling.
- Lifecycle display is currently driven by stage catalogues keyed by appeal type and mapped from CRM-derived inputs, rather than by a single explicit business model.
- Dashboard/worklist grouping uses additional state concepts beyond CRM `statuscode`, including `servicestage eq 1` for awaiting-submission cases and watched-case submission markers such as `pinswg_representationsubmitted`.
### Known ownership boundaries
- **CRM ownership:** operational case status/progression data (`statuscode`, `pinswg_casestage`, related entity fields, formatted labels).
- **Portal API ownership:** fetch and lightly reshape CRM data for consumers; examples include `getmycases_api`, `getawaitingsubmission_api`, and `getwatchedcases_api`.
- **Portal lifecycle seam ownership:** read-only interpretation and lookup behaviour, not source semantics (`lib/domain/case-lifecycle/README.md`).
- **Dashboard policy ownership:** limited watched/submitted classification for watched cases only; not overall dashboard lifecycle meaning (`lib/domain/dashboard-policy/README.md`).
- **Appeal-type policy ownership:** family classification only, not lifecycle/status behaviour (`lib/domain/appeal-type-policy/README.md`).
### Known consumer groups
- Public search results and case pages.
- Authenticated portal users in my portal panels and view-all screens.
- Watched-case and representation users.
- Admin/reporting views that aggregate counts by `statuscode` and appeal type/LPA.
- Case-summary users consuming the staged “status” journey view.
### Known transformations
- Raw CRM `statuscode` is transformed into:
- formatted public-facing status labels,
- stage-journey progress via `getLifecycleStagesForCase(...)`,
- aggregated reporting buckets/counts in admin dashboards,
- worklist segmentation such as awaiting submission, watched, and submitted representations.
- Specialist-process and appeal-type mappings influence which lifecycle stage catalogue is used.
- The portal reshapes watched-case and case query payloads by copying/renaming fields for UI convenience.
- Dashboard/worklist interpretations mix CRM data with portal-owned workflow markers such as blob-backed drafts and representation-submitted flags.
Conclusion: the repository already shows that this area is not a single raw CRM status display. It is a multi-consumer interpretation layer spanning operational status, staged progress presentation, workflow segmentation, and reporting aggregation.
---
## 2. What remains unknown?
The most important genuine unknowns are:
1. **`statuscode` vs `pinswg_casestage` relationship**
- It remains unclear whether these represent parallel CRM concepts, a primary/secondary lifecycle pair, or historical overlap.
2. **Lifecycle journey ownership**
- It is not yet clear whether the staged journey shown in case status is an intentional business-facing lifecycle model or a portal-side presentation mapping layered on top of CRM statuses.
3. **Specialist-process influence on lifecycle display**
- Specialist process is already used to choose stage catalogues in some flows, but the intended ownership and completeness of that influence is unclear.
4. **Closed-state and non-intuitive stage handling intent**
- The lifecycle seam explicitly preserves ambiguity around status vs stage and closed-case behaviour, which implies unresolved semantics.
5. **Progress display consistency across consumers**
- Public search, case summary, my portal panels, watched cases, and admin dashboards all consume status differently; it is unclear which differences are deliberate versus incidental.
6. **Reporting interpretation boundaries**
- Admin dashboards aggregate directly by `statuscode`, but it is unclear whether those counts represent operational CRM reporting only or are intended to align with user-facing lifecycle stages.
7. **Portal workflow vs CRM lifecycle boundary**
- Drafts, awaiting submission, submission processing, and submitted representations already use portal and blob/worklist concepts. The precise boundary between CRM lifecycle and portal workflow state remains unclear.
8. **Whether current stage catalogues encode business meaning or UI narrative only**
- The repository contains large appeal-type-specific stage arrays, but current evidence does not prove whether they are authoritative business semantics or user-guidance presentation.
---
## 3. Classification Assessment
This area should currently be classified as a **mixture** of multiple model types.
### B. Presentation Model
**Selected: Yes**
**Evidence**
- `components/case/status.js` renders a staged progress UI from interpreted lifecycle stages.
- `components/case/summary/utils/caseStagesByAppealType.js` contains appeal-type-specific stage catalogues with title/description translation keys, which is strong evidence of a presentation-oriented journey model.
- The lifecycle boundary README explicitly says it is a read-only interpretation seam and does not define new lifecycle semantics.
### C. CRM Compatibility Layer
**Selected: Yes**
**Evidence**
- `docs/query-profile-compatibility.md` states CRM field names are the source of truth and that downstream status/lifecycle views depend on preserving CRM field variants.
- The system preserves raw CRM `statuscode` and variant field shapes rather than normalizing them into a single clean internal model.
- API routes and search/case components depend on CRM formatted values and raw fields directly.
### D. Reporting Model
**Selected: Yes**
**Evidence**
- Admin endpoints such as `getStatusCountsByAppeal_api.js`, `getStatusCountsByAppealAndLPA_api.js`, and `getAppealsByStatusCounts_api.js` aggregate counts by `statuscode` for dashboards and drill-down search links.
- This is a distinct consumer need from case-summary lifecycle presentation.
### E. User Workflow Model
**Selected: Yes**
**Evidence**
- `context/domain-flows.md` documents portal-visible states such as awaiting submission, pending, and submission processing.
- `getawaitingsubmission_api.js` segments cases using `servicestage eq 1`, and dashboard policy separately classifies watched/submitted records using representation submission markers.
- These workflow concepts are not reducible to the case-summary lifecycle display alone.
### A. Business Decision Model
**Selected: Maybe / partial only**
**Evidence for limited inclusion**
- The portal definitely makes repeatable interpretation decisions about which stage journey to show, which bucket a record belongs in, and which status label/count to expose.
- However, current repository evidence does **not** yet prove that this is a coherent, intentional business decision model in the same way representation participation was shown to be.
- Existing docs explicitly preserve ambiguity: the lifecycle seam says it does not own semantics and must preserve “status-vs-stage ambiguity”.
Assessment: this is **not yet convincingly classifiable as a pure business decision model**. It looks more like a presentation/compatibility/workflow/reporting mixture with some embedded business meaning.
---
## 4. Architectural Value Assessment
If further characterization were performed, the likely outputs would be:
1. **Ownership map**
- Clarify which lifecycle/status meanings are owned by CRM versus interpreted by portal presentation, dashboard logic, and reporting.
2. **Transformation map**
- Trace how raw CRM fields (`statuscode`, `pinswg_casestage`, specialist process, service stage, representation submission flags) become user-facing lifecycle stages, worklists, and reporting summaries.
3. **Presentation model documentation**
- Document what the case-status journey actually represents per appeal type and whether it is intended as user guidance, operational translation, or formal lifecycle narrative.
4. **Compatibility documentation**
- Record which CRM field dependencies and ambiguities are compatibility-sensitive and must be preserved.
5. **Consumer divergence map**
- Identify where public search, case summary, my portal, watched cases, and admin dashboards intentionally diverge or accidentally drift.
6. **Workflow boundary clarification**
- Separate CRM operational lifecycle from portal draft/submission/worklist state.
### Likely value
The main value would be **architectural clarity**, not immediate extraction. It would reduce ambiguity for future refactor slices touching case summary, search, my portal, admin reporting, and CRM integration seams.
---
## 5. Domain Candidate Assessment
**Answer: Maybe**
### Evidence
- There is already a narrow `lib/domain/case-lifecycle` seam, which indicates the codebase has identified this as a potentially separable interpretation concern.
- The area spans multiple consumers and repeated translation logic, which is a common signal of a future domain-layer candidate.
- However, the current seam explicitly avoids owning semantics, progress/status calculation ownership, dashboard behaviour, and closed-case handling.
- The evidence currently points to a mixed concern area rather than a stable, well-bounded domain policy.
Conclusion: this looks like a **future domain-layer candidate only if characterization first clarifies ownership and semantics**. Today it is too ambiguous and multi-purpose to treat as a clearly ready domain boundary.
---
## 6. Cost vs Value Assessment
### Investigation Cost
**Medium**
**Reasoning**
- The evidence is already partially assembled through current docs and the extracted lifecycle seam.
- However, the concern spans many consumers: case summary, search, my portal, watched cases, admin dashboards, API queries, and stage catalogues.
- The ambiguity between status, stage, workflow, and reporting means a slice still requires careful cross-consumer characterization.
### Architectural Value
**High**
**Reasoning**
- This area sits at a boundary between CRM integration, portal presentation, and user workflow interpretation.
- Clarifying it would improve future decision-making in several existing streams and reduce the risk of accidental semantic changes during refactor.
- The repository already names this as the next likely discovery candidate, which aligns with the observed ambiguity.
### Maintenance Value
**Medium to High**
**Reasoning**
- Better understanding would help maintainers avoid conflating raw CRM status, lifecycle stage display, dashboard grouping, and workflow state.
- It would make future changes safer in high-touch files such as `components/case/status.js`, `components/case/summary.js`, `components/myportal/viewall.js`, and related API routes.
- Value is not yet “very high” because characterization alone would not immediately simplify the code unless followed later by carefully bounded extraction work.
---
## 7. Recommendation
**Recommendation: Option B — Perform one characterization slice.**
### Supporting evidence
- Current understanding is **not** sufficient to say this is only CRM compatibility or only presentation.
- Existing evidence already proves this area mixes at least presentation, workflow, reporting, and compatibility concerns.
- A full characterization stream is not yet justified because representation participation business validation is still an active dependency in project context, and the scope here is broad.
- One bounded slice focused on ownership and transformation clarity would likely answer whether the broader stream is worthwhile.
Why not Option A:
- There are still material unknowns around `statuscode` vs `pinswg_casestage`, stage ownership, consumer divergence, and workflow/reporting boundaries.
Why not Option C:
- The current evidence supports further investigation, but not yet a full multi-slice stream without first proving that the ambiguity resolves into a coherent characterization target.
Why not Option D:
- This remains a stronger next investigation candidate than many other areas because the ambiguity is architectural, cross-cutting, and already partially surfaced by existing seams and docs.
---
## 8. Alternative Investigation Candidates
If CRM Case Progress Display is not taken next, the strongest evidenced alternatives from the repository are:
1. **Portal workflow state / my portal worklist segmentation**
- Evidence: `context/domain-flows.md`, `lib/domain/dashboard-policy/README.md`, `components/myportal/viewall.js`, `getawaitingsubmission_api.js`, watched/submitted classification.
- Why candidate: the portal already mixes draft, awaiting submission, watched, submitted, and representation states outside the lifecycle seam.
2. **CRM integration boundary / status-query compatibility**
- Evidence: `docs/query-profile-compatibility.md`, `actions/selectQueryTypes.js`.
- Why candidate: lifecycle and status views depend on CRM field selection and compatibility-preserving query shapes.
3. **Submission journey state boundaries**
- Evidence: awaiting-submission blob flows, service-stage filters, draft continuation routes, and my portal segmentation.
- Why candidate: this may produce a cleaner workflow-state understanding than starting with all lifecycle presentation concerns at once.
4. **Notification / watched-case workflow interpretation**
- Evidence: `getwatchedcases_api.js`, dashboard-policy classification, watched vs submitted representation handling.
- Why candidate: it exposes a narrower but related interpretation boundary between CRM case records and user-facing participation state.
These candidates are all evidenced in current repository state. None are invented.
---
## 9. Final Conclusion
**Answer: B. Probably**
### Supporting evidence
- The codebase already shows this area is broader than simple CRM status display.
- There is clear evidence of multiple overlapping models: CRM operational status, staged case progress presentation, dashboard/worklist workflow grouping, and reporting aggregation.
- The existing lifecycle seam explicitly preserves ambiguity instead of resolving it, which suggests meaningful architectural understanding is still missing.
- However, the area does **not yet** show the same clear coherence as representation participation; therefore the likely value is real but should first be tested with one bounded characterization slice rather than a full stream.
Overall conclusion:
> CRM Case Progress Display is likely to produce meaningful additional architectural understanding beyond what is already known, but only **probably**, not clearly enough yet to justify a full characterization stream immediately.
---
## Assessment Outcome Summary
- **Should this become a formal investigation stream now?** Not yet as a full stream.
- **Best next step:** one bounded characterization slice.
- **Current classification:** mixed presentation + CRM compatibility + reporting + user workflow area, with partial business meaning but no proven single policy model yet.
- **Domain-layer candidate assessment:** Maybe.
- **Cost/value:** Medium investigation cost; High architectural value; Medium-to-High maintenance value.