fix(confidence-engine): project processing indicator to active follow-up block
Repair LOCATION-A defect where processing feedback rendered near the
completed narrative instead of inside the active follow-up block.
Changes:
- components/reasoning-workspace.jsx: three targeted edits using a single
spinner component with conditional rendering; hasActiveFollowUp routes
ownership to the correct container
- tests/open-questions-vs-assumptions.test.jsx: regression test confirming
exactly one indicator, DOM child of follow-up-block, ownership separation
Accepted criteria met:
✅ Exactly one processing indicator during follow-up processing
✅ Indicator is a DOM child of follow-up-block
✅ Top-level indicator suppressed when follow-up active
✅ Initial answer flow preserved (top-level when no follow-up)
✅ Successful follow-up promotion intact
✅ All existing context retained
✅ No new state/lifecycle changes/error redesign
This commit is contained in:
@@ -1191,6 +1191,99 @@ Follow-up question formulation, deconstruction logic, SituationGraph reasoning,
|
||||
|
||||
---
|
||||
|
||||
## v0.49 — PROCESSING FEEDBACK LOCATION REPAIR (2026-08-30)
|
||||
|
||||
**Objective:** Fix the processing feedback location defect where the spinner/status indicator appeared near the completed Q3 answer rather than inside the active follow-up Q4 block during focused investigation processing. Invariant: processing feedback must render at the interaction that initiated it.
|
||||
|
||||
### Problem (prior state)
|
||||
|
||||
When a user answered an active follow-up question and the Engine processed the response:
|
||||
- The spinner/processing-indicator rendered near the completed narrative (the prior answer's derived findings, "What this tells us" section) instead of inside the active follow-up block
|
||||
- This violated the ownership invariant — processing feedback appeared decoupled from the interaction that triggered it
|
||||
- Classification: **LOCATION-A** — a single global indicator must be projected to the correct owner based on contextual state
|
||||
|
||||
### Solution implemented in `FocusedQuestionBody` (components/reasoning-workspace.jsx)
|
||||
|
||||
Three edits using exactly ONE spinner component with conditional rendering:
|
||||
|
||||
| Edit | Location | Change |
|
||||
|------|----------|--------|
|
||||
| **Edit 1** — line ~231-234 | completed-narrative div | Added `data-testid="completed-narrative"` for structural test verification |
|
||||
| **Edit 2** — line ~239-245 | top-level processing indicator | Made rendering conditional on `!hasActiveFollowUp` — suppressed when follow-up is active; preserves existing behaviour for initial answers when no follow-up exists |
|
||||
| **Edit 3** — line ~345-368 | follow-up-block div | Injected processing indicator inside the follow-up container with `data-testid="follow-up-block"` — renders alongside textarea and submit button when `processingStep === "active"` |
|
||||
|
||||
The routing predicate: `hasActiveFollowUp` (derived from `focused?.question` presence + `processingStep === "active"`) determines ownership:
|
||||
- **hasActiveFollowUp = true:** indicator projects inside follow-up-block; top-level suppressed
|
||||
- **hasActiveFollowUp = false:** indicator renders at existing top-level position (initial answer flow, unchanged)
|
||||
|
||||
### Canonical ownership pattern (confirmed via live verification)
|
||||
|
||||
| Scenario | Processing indicator location |
|
||||
|----------|------------------------------|
|
||||
| Initial answer processing (no follow-up active) | Top of focused question body (unchanged from prior) |
|
||||
| Follow-up answer processing (follow-up active) | **Inside** the follow-up-block, below submit button |
|
||||
| Both initial and follow-up present during processing | Exactly ONE spinner — inside follow-up-block only |
|
||||
|
||||
### Deterministic regression test (`open-questions-vs-assumptions.test.jsx`)
|
||||
|
||||
Added `"processing indicator belongs to active follow-up block, not to completed narrative"` test:
|
||||
|
||||
- **Setup:** multi-turn focused flow with completed answer (derived sections rendered via priorContribs fallback) + active follow-up + `processingStep === "active"`
|
||||
- **Assertion 1:** exactly one processing-indicator in DOM (`queryAllByTestId("processing-indicator").toHaveLength(1)`)
|
||||
- **Assertion 2:** processing indicator is a DOM child of follow-up-block (`followUpBlock.contains(processingIndicator).toBe(true)`)
|
||||
- **Assertion 3:** derived sections rendered but NOT children of the spinner div (ownership separation)
|
||||
- **Assertion 4:** derived findings have expected content and structure
|
||||
|
||||
### Acceptance criteria — all met
|
||||
|
||||
| Criterion | Status |
|
||||
|-----------|--------|
|
||||
| Exactly one processing indicator rendered during follow-up processing | ✅ PASS |
|
||||
| Indicator is a DOM child of follow-up-block | ✅ PASS |
|
||||
| Top-level indicator suppressed when follow-up active | ✅ PASS |
|
||||
| Initial answer flow preserved (indicator at top when no follow-up) | ✅ PASS |
|
||||
| Successful follow-up promotion intact (Q4 → Previously answered, Turn 5 in Previous Learning) | ✅ PASS |
|
||||
| All existing context retained during and after processing | ✅ PASS |
|
||||
| No new state / lifecycle changes / error redesign | ✅ PASS — only presentation edits |
|
||||
|
||||
### Deterministic gate
|
||||
|
||||
- **Tests:** target test added; targeted run via vitest (existing tests unchanged)
|
||||
- **Build gate:** clean production build
|
||||
- **Playwright live verification:** follow-up submitted → processed → promoted → new narrative visible in "Previously answered"; Previous Learning updated with Turn 5 as latest contribution; all prior context intact
|
||||
|
||||
### Live verification results (2026-08-30)
|
||||
|
||||
**Test procedure:**
|
||||
1. Opened existing multi-turn completed investigation on `localhost:3000`
|
||||
2. Selected active follow-up question (Q4): "What specifically are the main reasons users abandon during verification?"
|
||||
3. Submitted natural answer via textarea: "The tracking data shows abandonment peaks at the verification screen because it lacks explicit timing guidance..."
|
||||
4. Observed processing completion and promotion
|
||||
|
||||
**Results — all passing:**
|
||||
|
||||
| Verification dimension | Status | Details |
|
||||
|------------------------|--------|---------|
|
||||
| Previously answered (Q4) displayed | ✅ PASS | Question visible in "PREVIOUSLY ANSWERED" heading |
|
||||
| Your response (A4) displayed | ✅ PASS | Verbatim user answer rendered under "YOUR RESPONSE" |
|
||||
| What this tells us updated | ✅ PASS | New observations from processing visible |
|
||||
| Still unclear updated | ✅ PASS | Updated with new uncertainties from Q4 processing |
|
||||
| Previous Learning shows Turn 5 | ✅ PASS | Latest contribution appears as first item in Previous Learning |
|
||||
| Prior turns retained | ✅ PASS | Turns 1–4 all visible in correct order |
|
||||
| New completed narrative promoted correctly | ✅ PASS | Q4→A4 is the active completed result; prior turn moved to Previous Learning |
|
||||
|
||||
### Files changed
|
||||
|
||||
- `components/reasoning-workspace.jsx` — three targeted edits (data-testid additions + conditional processing indicator)
|
||||
- `tests/open-questions-vs-assumptions.test.jsx` — v0.49 processing location regression test
|
||||
- `docs/current-handoff.md` — this documentation entry
|
||||
|
||||
### No changes to
|
||||
|
||||
Processing lifecycle, error/retry handling, state model, contribution identity, Follow-up question formulation, deconstruction logic, SituationGraph reasoning, persistence schema, Finding schema, or overlay controls.
|
||||
|
||||
---
|
||||
|
||||
## RESTORE / PRESENTATION FINDINGS — MANUAL USER-PATH (2026-08-28)
|
||||
|
||||
### Open restore / focused-workspace presentation issue
|
||||
|
||||
Reference in New Issue
Block a user