fix(confidence-engine): preserve focused learning across turns
This commit is contained in:
@@ -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}
|
||||
/>
|
||||
);
|
||||
})()}
|
||||
|
||||
Reference in New Issue
Block a user