fix(confidence-engine): preserve focused learning across turns

This commit is contained in:
2026-08-26 14:07:16 +01:00
parent b26ea7d0ba
commit ac5fbe7896
+69 -7
View File
@@ -167,6 +167,7 @@ function FocusedQuestionBody({
setFocusedPresentationItemId,
setDoneForNowIds,
setFollowUpQuestion,
focusedContributions,
}) {
return (
<>
@@ -199,22 +200,33 @@ function FocusedQuestionBody({
{focused?.result && (
<>
{/* Prior accumulated learning (prior turns, current turn excluded — shown above) */}
<PriorContributionsSummary nodeId={nodeId} contributions={focusedContributions || []} />
<div><h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">What this tells us</h3><ul className="list-disc pl-5 space-y-1">{(focused.result.observations || []).map((o, i) => (<li key={i} className="text-sm leading-relaxed text-gray-700">{o}</li>))}</ul></div>
<div><h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">Still unclear</h3><ul className="list-disc pl-5 space-y-1">{(focused.result.uncertainties || []).map((u, i) => (<li key={i} className="text-sm leading-relaxed text-gray-700">{u}</li>))}</ul></div>
<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) => (
{focused.result.possibleFollowUpQuestions.map((q, i) => {
const isCurrentQuestion = q === focused?.question;
return (
<button
key={i}
onClick={(e) => { e.stopPropagation(); setFollowUpQuestion(q); }}
style={{ cursor: "pointer" }}
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 hover:border-blue-300 hover:bg-blue-100/60 transition"
onClick={(e) => { if (!isCurrentQuestion) { e.stopPropagation(); setFollowUpQuestion(q); } }}
style={{ cursor: isCurrentQuestion ? "default" : "pointer" }}
className={`w-full text-left rounded-lg border px-3 py-2.5 text-sm leading-relaxed transition ${
isCurrentQuestion
? "border-gray-200 bg-gray-100/60 text-gray-400 cursor-default"
: "border-blue-200/60 bg-blue-50/40 text-gray-800 hover:border-blue-300 hover:bg-blue-100/60"
}`}
data-testid="follow-up-question"
>
{q} pick this question
{q}
{isCurrentQuestion ? " (current question)" : " → pick this question"}
</button>
))}
);
})}
</div>
) : (
<p className="text-xs text-gray-400">None yet</p>
@@ -403,7 +415,55 @@ function EvidenceLimitCard({ summary }) {
);
}
// ── Per-thread contribution badge (compact indicator) ──────────────
// ── Prior contribution summary (embedded within FocusedQuestionBody) ───
function PriorContributionsSummary({ nodeId, contributions }) {
const threadContribs = contributions.filter((c) => c.targetNodeId === nodeId);
if (!threadContribs.length) return null;
// Exclude the most recent contribution — it is already shown as the current result above.
const priorContribs = threadContribs.slice(0, -1);
if (!priorContribs.length) return null;
return (
<div className="rounded-lg border border-gray-200/60 bg-gray-50/40 px-4 py-3">
<h4 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
Previous learning
</h4>
{priorContribs.map((c, idx) => (
<details key={c.id || idx} className="mb-2 border-b border-gray-200/40 last:border-0 pb-2 last:pb-0" open={idx === 0}>
<summary className="cursor-pointer text-xs font-medium text-gray-500 hover:text-gray-700 select-none py-1">
Turn {c.sequence || idx + 1} contribution ({c.observations?.length ?? 0} observations, {c.uncertainties?.length ?? 0} unclear)
</summary>
<div className="pt-2 space-y-3">
{c.observations?.length ? (
<div>
<h5 className="text-[10px] font-semibold tracking-widest uppercase text-gray-500">What this tells us</h5>
<ul className="list-disc pl-5 space-y-0.5">
{c.observations.map((o, i) => (
<li key={i} className="text-xs leading-relaxed text-gray-700">{o}</li>
))}
</ul>
</div>
) : null}
{c.uncertainties?.length ? (
<div>
<h5 className="text-[10px] font-semibold tracking-widest uppercase text-gray-500">Still unclear</h5>
<ul className="list-disc pl-5 space-y-0.5">
{c.uncertainties.map((u, i) => (
<li key={i} className="text-xs leading-relaxed text-gray-700">{u}</li>
))}
</ul>
</div>
) : null}
</div>
</details>
))}
</div>
);
}
// ── Thread contributions badge (standalone — used outside focused body) ───
function ThreadContributionsBadge({ nodeId, contributions }) {
const threadContribs = contributions.filter((c) => c.targetNodeId === nodeId);
@@ -965,6 +1025,7 @@ function OpenQuestionsPanel({
setFocusedPresentationItemId={setFocusedPresentationItemId}
setDoneForNowIds={setDoneForNowIds}
setFollowUpQuestion={setFollowUpQuestion}
focusedContributions={focusedContributions}
/>
{/* Thread contributions for this node */}
@@ -1575,6 +1636,7 @@ export default function ReasoningWorkspace({
setFocusedPresentationItemId={setFocusedPresentationItemId}
setDoneForNowIds={setDoneForNowIds}
setFollowUpQuestion={setFollowUpQuestion}
focusedContributions={focusedContributions}
/>
);
})()}