fix(confidence-engine): simplify active follow-up presentation
This commit is contained in:
@@ -274,7 +274,19 @@ function FocusedQuestionBody({
|
||||
<div><h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">Questions this raises</h3>
|
||||
{(focused.result.possibleFollowUpQuestions || []).length > 0 ? (
|
||||
<div className="space-y-1 mt-1">
|
||||
{focused.result.possibleFollowUpQuestions.map((q, i) => {
|
||||
{hasActiveFollowUp
|
||||
? focused.result.possibleFollowUpQuestions.filter((q) => q !== focused.question).map((q, i) => (
|
||||
<button
|
||||
key={i}
|
||||
onClick={(e) => { e.stopPropagation(); setFollowUpQuestion(q); }}
|
||||
className="w-full text-left rounded-lg border border-blue-200/60 bg-blue-50/40 px-3 py-2.5 text-sm leading-relaxed text-gray-800 transition hover:border-blue-300 hover:bg-blue-100/60 cursor-pointer"
|
||||
data-testid="follow-up-question"
|
||||
>
|
||||
{q}
|
||||
{" → pick this question"}
|
||||
</button>
|
||||
))
|
||||
: focused.result.possibleFollowUpQuestions.map((q, i) => {
|
||||
const isCurrentQuestion = q === focused?.question;
|
||||
return (
|
||||
<button
|
||||
|
||||
@@ -2158,3 +2158,39 @@ Those are distinct presentation responsibilities. Separating them exposes a dupl
|
||||
- Previous Learning single-owner presentation: CLOSED
|
||||
- Previous Learning newest-first: CLOSED
|
||||
- Post-answer promotion: PRESERVED
|
||||
|
||||
## v0.49 — ACTIVE FOLLOW-UP PRESENTATION SIMPLIFICATION
|
||||
|
||||
### Defect resolved
|
||||
|
||||
Selected follow-up candidate rendered twice inside "QUESTIONS THIS RAISES": once as a disabled `(current question)` row and again in the active continuation block above the textarea. Both rows contained the identical question text, creating visual redundancy.
|
||||
|
||||
### Fix summary
|
||||
|
||||
In `components/reasoning-workspace.jsx`, when `hasActiveFollowUp` is true (a follow-up has been selected), unselected candidates are still rendered with their existing selectable form (`→ pick this question`), but the candidate matching `focused.question` is filtered out from the candidate list entirely. The active continuation block already renders the selected question plus textarea + submit — no second rendering needed.
|
||||
|
||||
- Selected follow-up candidate now transforms into the active response block (single rendering).
|
||||
- Duplicate `(current question)` / second-question rendering removed.
|
||||
- Exactly one selected-question presentation.
|
||||
- One textarea, Submit response visible.
|
||||
- Completed Q/A provenance preserved.
|
||||
- Previous Learning single-owner/newest-first preserved.
|
||||
- Post-answer promotion preserved.
|
||||
|
||||
### Implementation detail
|
||||
|
||||
Production file changed: `components/reasoning-workspace.jsx` (candidate render boundary — lines ~275-300). No state added, no identity changes, no submit mechanics altered.
|
||||
|
||||
### Vitest config hygiene (from 8bded90)
|
||||
|
||||
vitest.config.js change classification: **A** — intentional and necessary (adds `environment: "jsdom"` required for React component testing in this repo).
|
||||
|
||||
### Tests
|
||||
|
||||
- Command: `npx vitest run tests/open-questions-vs-assumptions.test.jsx`
|
||||
- Actual tests passed: **117** (up from 116 — one new regression test added)
|
||||
- New regression assertion: verifies that after selecting a follow-up, the question text appears exactly once and no `(current question)` label is rendered.
|
||||
|
||||
### Build
|
||||
|
||||
- Result: PASS
|
||||
|
||||
@@ -2195,5 +2195,59 @@ describe("v0.49 RENDERED — in-place follow-up context ownership", () => {
|
||||
const prevLearningHeadings = screen.queryAllByText(/previous learning/i);
|
||||
expect(prevLearningHeadings).toHaveLength(1);
|
||||
});
|
||||
|
||||
// ── v0.49 REGRESSION: selected follow-up must not render twice ──
|
||||
it("v0.49 regression: selected follow-up renders exactly once, no '(current question)' duplicate", () => {
|
||||
const turn1Q = "Completed question?";
|
||||
const turn1A = "Complete answer.";
|
||||
|
||||
// Q3 completed with raised follow-up Q4
|
||||
const contribs = [
|
||||
makeContrib(turn1Q, turn1A, 1),
|
||||
];
|
||||
|
||||
// After setFollowUpQuestion: focused.question === "Q4", possibleFollowUpQuestions = ["Q4"], hasActiveFollowUp = true
|
||||
render(
|
||||
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
||||
<FocusedQuestionBody
|
||||
nodeId="node-test"
|
||||
isFocused={true}
|
||||
hasContent={true}
|
||||
processingStep="idle"
|
||||
formulationStep="active"
|
||||
deconstructMsg=""
|
||||
focusedAnswer=""
|
||||
setFocusedAnswer={() => {}}
|
||||
handleDeconstructSubmit={() => {}}
|
||||
retryFormulation={() => {}}
|
||||
setFollowUpQuestion={() => {}}
|
||||
focused={
|
||||
{
|
||||
question: "Q4",
|
||||
answer: null,
|
||||
status: "formulated",
|
||||
result: {
|
||||
observations: ["finding"],
|
||||
uncertainties: [],
|
||||
possibleFollowUpQuestions: ["Q4"],
|
||||
assumptions: [],
|
||||
relationships: [],
|
||||
},
|
||||
error: null,
|
||||
}
|
||||
}
|
||||
focusedContributions={contribs}
|
||||
/>
|
||||
</div>,
|
||||
);
|
||||
|
||||
// The selected follow-up text should appear exactly once (in the active block), not duplicated in candidate row.
|
||||
const q4Text = screen.getAllByText("Q4");
|
||||
expect(q4Text).toHaveLength(1);
|
||||
|
||||
// After selection, "(current question)" label must NOT be rendered — the active form communicates selection unambiguously.
|
||||
const currentQuestionLabels = screen.queryAllByText(/\(current question\)/i);
|
||||
expect(currentQuestionLabels).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user