fix: preserve accurate investigation history

This commit is contained in:
2026-08-04 13:27:23 +01:00
parent 91168a8213
commit dced344680
+51 -37
View File
@@ -103,18 +103,14 @@ function SituationCard({ centralStatement }) {
function CurrentUnderstanding({ currentSummary }) {
const summary = resolveCurrentSummary(currentSummary);
if (!summary) return null;
return (
<div className="investigation-card rounded-lg border border-gray-200 bg-white p-5">
<h2 className="mb-3 text-sm font-semibold uppercase tracking-wide text-gray-500">
What we&#x27;ve established
</h2>
{summary ? (
<p className="text-sm leading-relaxed text-gray-700">{summary}</p>
) : (
<p className="text-sm leading-relaxed text-gray-600">
We have separated what is known from what still needs checking.
</p>
)}
<p className="text-sm leading-relaxed text-gray-700">{summary}</p>
</div>
);
}
@@ -199,21 +195,30 @@ function CurrentFocusCard({ graph }) {
// ── Investigation history card ────────────────────────────────
function InvestigationHistoryCard({ turn }) {
const qSnippet = turn.question.length > 80
? turn.question.slice(0, 80) + "…"
: turn.question;
return (
<details className="rounded-lg border border-gray-100 bg-gray-50/60 px-4 py-3">
<details className="rounded-lg border border-gray-100 bg-gray-50/60 px-4 py-3" key={turn.id}>
<summary className="cursor-pointer text-xs font-semibold uppercase tracking-wide text-gray-400 hover:text-gray-600">
{new Date(turn.timestamp).toLocaleString(undefined, {
month: "short",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
})}
})} {qSnippet}
</summary>
<div className="mt-2 space-y-2 text-sm">
<p><strong>{turn.question}</strong></p>
<p><strong>Question</strong></p>
<p>{turn.question}</p>
<p><strong>You answered</strong></p>
<p className="text-gray-700">{turn.answer}</p>
{turn.acknowledgement && (
<p className="italic text-gray-500">{turn.acknowledgement}</p>
<>
<p><strong>What changed</strong></p>
<p className="italic text-gray-500">{turn.acknowledgement}</p>
</>
)}
</div>
</details>
@@ -230,8 +235,8 @@ function InvestigationHistory({ turns }) {
Investigation history
</h2>
<div className="space-y-2">
{turns.map((turn, idx) => (
<InvestigationHistoryCard key={idx} turn={turn} />
{turns.map((turn) => (
<InvestigationHistoryCard key={turn.id} turn={turn} />
))}
</div>
</div>
@@ -384,33 +389,42 @@ export default function ReasoningWorkspace({
lastSubmittedAnswer,
}) {
const [investigationHistory, setInvestigationHistory] = useState([]);
const turnCounter = useRef(0);
const pendingTurnRef = useRef(null);
// Capture the previous question before each new question is set
const prevQuestionRef = useRef(null);
const hasCapturedInitialQuestion = useRef(false);
// Capture the current selected question at submit time (not from a stale ref)
const capturePendingTurn = (selectedQuestion, answerText) => {
if (!selectedQuestion || !answerText?.trim()) return null;
const q = typeof selectedQuestion === "string" ? selectedQuestion : selectedQuestion.question;
if (!q) return null;
turnCounter.current += 1;
return {
id: `turn-${turnCounter.current}`,
question: q,
answer: answerText.trim(),
acknowledgement: null,
timestamp: Date.now(),
};
};
// Append the captured pending turn to history after a successful update only
useEffect(() => {
if (result?.selectedQuestion && !hasCapturedInitialQuestion.current) {
prevQuestionRef.current = result.selectedQuestion;
hasCapturedInitialQuestion.current = true;
}
}, [result?.selectedQuestion]);
const pending = pendingTurnRef.current;
if (!pending || updateStatus !== "success") return;
// Append completed turn to history after a successful update
useEffect(() => {
if (updateStatus === "success" && lastSubmittedAnswer) {
const q = prevQuestionRef.current;
setInvestigationHistory((prev) => [
...prev,
{
question: typeof q === "string" ? q : q?.question ?? "",
answer: lastSubmittedAnswer,
acknowledgement: result?.summary || null,
timestamp: Date.now(),
},
]);
}
}, [updateStatus, lastSubmittedAnswer, result]);
setInvestigationHistory((prev) => [
...prev,
{ ...pending, acknowledgement: result?.summary || null },
]);
pendingTurnRef.current = null;
}, [updateStatus, result]);
const handleUpdateCaptureAndSubmit = async (e) => {
e.preventDefault();
if (!answer?.trim() || !result?.selectedQuestion) return;
pendingTurnRef.current = capturePendingTurn(result.selectedQuestion, answer);
await onAnswerSubmit(e);
};
const { elapsed: startElapsed, currentMessage: startMsg } = useLoadingStatus(
INITIAL_MESSAGES,
@@ -494,7 +508,7 @@ export default function ReasoningWorkspace({
{/* ── Answer form ──────────────────────────────── */}
{canAnswer && (
<form onSubmit={onAnswerSubmit} className="space-y-4 rounded-lg border border-gray-200 bg-white p-5">
<form onSubmit={handleUpdateCaptureAndSubmit} className="space-y-4 rounded-lg border border-gray-200 bg-white p-5">
<div>
<label htmlFor="rw-answer" className="mb-2 block text-sm font-medium text-gray-700">
Your response