Revert "feat: allow earlier evidence to be revised"
This reverts commit 13b14fd01a.
This commit is contained in:
@@ -47,13 +47,6 @@ const UPDATE_MESSAGES = [
|
|||||||
{ min: 45, text: "Choosing the next question" },
|
{ min: 45, text: "Choosing the next question" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const REVISION_MESSAGES = [
|
|
||||||
{ min: 0, text: "Reading what changed" },
|
|
||||||
{ min: 10, text: "Rebuilding the investigation" },
|
|
||||||
{ min: 25, text: "Checking what this affects" },
|
|
||||||
{ min: 45, text: "Choosing the next justified question" },
|
|
||||||
];
|
|
||||||
|
|
||||||
function useLoadingStatus(messages, isLoading) {
|
function useLoadingStatus(messages, isLoading) {
|
||||||
const [elapsed, setElapsed] = useState(0);
|
const [elapsed, setElapsed] = useState(0);
|
||||||
const startRef = useRef(null);
|
const startRef = useRef(null);
|
||||||
@@ -83,59 +76,6 @@ function useLoadingStatus(messages, isLoading) {
|
|||||||
return { elapsed, currentMessage };
|
return { elapsed, currentMessage };
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Revision warning banner ─────────────────────────────────
|
|
||||||
function RevisionWarningCard() {
|
|
||||||
return (
|
|
||||||
<div className="rounded-lg border border-amber-200 bg-amber-50 px-5 py-3 text-sm text-amber-900">
|
|
||||||
Changing this answer may alter the questions and conclusions that followed it.
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Revision inline editor ────────────────────────────────────
|
|
||||||
function RevisionEditor({ turn, onSave, onCancel }) {
|
|
||||||
const [draft, setDraft] = useState(turn.answer);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="rounded-lg border border-amber-200 bg-amber-50 px-5 py-4 space-y-3">
|
|
||||||
<RevisionWarningCard />
|
|
||||||
<p className="text-sm font-medium text-amber-900">{turn.question}</p>
|
|
||||||
<textarea
|
|
||||||
value={draft}
|
|
||||||
onChange={(e) => setDraft(e.target.value)}
|
|
||||||
rows={3}
|
|
||||||
className="w-full rounded-lg border border-amber-300 bg-white px-4 py-2 text-sm focus:border-amber-400 focus:outline-none"
|
|
||||||
/>
|
|
||||||
<div className="flex gap-3">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => onSave(draft)}
|
|
||||||
disabled={!draft.trim()}
|
|
||||||
className="rounded-lg bg-amber-600 px-4 py-2 text-sm font-medium text-white hover:bg-amber-700 disabled:opacity-40"
|
|
||||||
>
|
|
||||||
Save revised answer
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={onCancel}
|
|
||||||
className="text-sm text-amber-700 underline hover:text-amber-900"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Stale turn summary (shown under "Earlier answers that may need reviewing") ───
|
|
||||||
function StaleTurnSummary({ turn, index }) {
|
|
||||||
return (
|
|
||||||
<div className="rounded-lg border border-red-100 bg-red-50/40 px-4 py-2 text-sm text-red-800">
|
|
||||||
<span className="font-medium">Earlier answer #{index + 1}:</span> {turn.question} — "{turn.answer}" may no longer apply.
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Spinner component ───────────────────────────────────────
|
// ── Spinner component ───────────────────────────────────────
|
||||||
function ActivitySpinner() {
|
function ActivitySpinner() {
|
||||||
return (
|
return (
|
||||||
@@ -258,62 +198,40 @@ function CurrentFocusCard({ graph }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Investigation history card ────────────────────────────────
|
// ── Investigation history card ────────────────────────────────
|
||||||
function InvestigationHistoryCard({ turn, onReview }) {
|
function InvestigationHistoryCard({ turn }) {
|
||||||
const hasReview = !onReview && turn.status === "current";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div 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">
|
||||||
<div className="flex items-start justify-between gap-3">
|
<summary className="cursor-pointer text-xs font-semibold uppercase tracking-wide text-gray-400 hover:text-gray-600">
|
||||||
<div>
|
{new Date(turn.timestamp).toLocaleString(undefined, {
|
||||||
<p className="text-xs text-gray-400">
|
month: "short",
|
||||||
{new Date(turn.timestamp).toLocaleString(undefined, {
|
day: "numeric",
|
||||||
month: "short",
|
hour: "2-digit",
|
||||||
day: "numeric",
|
minute: "2-digit",
|
||||||
hour: "2-digit",
|
})}
|
||||||
minute: "2-digit",
|
</summary>
|
||||||
})}
|
<div className="mt-2 space-y-2 text-sm">
|
||||||
</p>
|
<p><strong>{turn.question}</strong></p>
|
||||||
<details className="mt-1">
|
<p className="text-gray-700">{turn.answer}</p>
|
||||||
<summary className="cursor-pointer text-xs font-semibold uppercase tracking-wide text-gray-400 hover:text-gray-600">
|
{turn.engineResponse && (
|
||||||
{turn.question}
|
<p className="italic text-gray-500">{turn.engineResponse}</p>
|
||||||
</summary>
|
|
||||||
<div className="mt-2 space-y-2 text-sm">
|
|
||||||
<p><strong>You told us:</strong> {turn.answer}</p>
|
|
||||||
{turn.engineResponse && (
|
|
||||||
<p className="italic text-gray-500">{turn.engineResponse}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
</div>
|
|
||||||
{hasReview && (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={onReview}
|
|
||||||
className="shrink-0 rounded border border-gray-300 bg-white px-3 py-1 text-xs font-medium text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
|
||||||
>
|
|
||||||
Review answer
|
|
||||||
</button>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</details>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Investigation history section ─────────────────────────────
|
// ── Investigation history section ─────────────────────────────
|
||||||
function InvestigationHistory({ turns, onReviewTurn }) {
|
function InvestigationHistory({ turns }) {
|
||||||
if (!turns || turns.length === 0) return null;
|
if (!turns || turns.length === 0) return null;
|
||||||
|
|
||||||
const activeTurns = turns.filter((t) => t.status !== "superseded");
|
|
||||||
if (activeTurns.length === 0) return null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<h2 className="text-xs font-bold uppercase tracking-wider text-gray-400">
|
<h2 className="text-xs font-bold uppercase tracking-wider text-gray-400">
|
||||||
Investigation history
|
Investigation history
|
||||||
</h2>
|
</h2>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{activeTurns.map((turn, idx) => (
|
{turns.map((turn, idx) => (
|
||||||
<InvestigationHistoryCard key={turn.id ?? idx} turn={turn} onReview={turn.status === "current" ? () => onReviewTurn?.(idx) : undefined} />
|
<InvestigationHistoryCard key={idx} turn={turn} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -464,18 +382,9 @@ export default function ReasoningWorkspace({
|
|||||||
setAnswer,
|
setAnswer,
|
||||||
onAnswerSubmit,
|
onAnswerSubmit,
|
||||||
lastSubmittedAnswer,
|
lastSubmittedAnswer,
|
||||||
isRevisionLoading: propIsRevisionLoading,
|
|
||||||
}) {
|
}) {
|
||||||
const [investigationHistory, setInvestigationHistory] = useState([]);
|
const [investigationHistory, setInvestigationHistory] = useState([]);
|
||||||
|
|
||||||
// Inline revision editor state (local — no parent re-render until submit)
|
|
||||||
const [editingTurnIndex, setEditingTurnIndex] = useState(-1);
|
|
||||||
const [revisionDraft, setRevisionDraft] = useState("");
|
|
||||||
const [showRevisionEditor, setShowRevisionEditor] = useState(false);
|
|
||||||
|
|
||||||
// Track which turn was revised so we can mark stale turns after update succeeds
|
|
||||||
const revisedTurnIndexRef = useRef(-1);
|
|
||||||
|
|
||||||
// Capture the previous question before each new question is set
|
// Capture the previous question before each new question is set
|
||||||
const prevQuestionRef = useRef(null);
|
const prevQuestionRef = useRef(null);
|
||||||
const hasCapturedInitialQuestion = useRef(false);
|
const hasCapturedInitialQuestion = useRef(false);
|
||||||
@@ -487,39 +396,22 @@ export default function ReasoningWorkspace({
|
|||||||
}
|
}
|
||||||
}, [result?.selectedQuestion]);
|
}, [result?.selectedQuestion]);
|
||||||
|
|
||||||
// Append completed turn to history after a successful update (normal or revision)
|
// Append completed turn to history after a successful update
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (updateStatus !== "success" || !lastSubmittedAnswer) return;
|
if (updateStatus === "success" && lastSubmittedAnswer) {
|
||||||
|
const q = prevQuestionRef.current;
|
||||||
const q = prevQuestionRef.current;
|
setInvestigationHistory((prev) => [
|
||||||
setInvestigationHistory((prev) => {
|
...prev,
|
||||||
const newTurn = {
|
{
|
||||||
id: Date.now(),
|
question: typeof q === "string" ? q : q?.question ?? "",
|
||||||
question: typeof q === "string" ? q : q?.question ?? "",
|
answer: lastSubmittedAnswer,
|
||||||
answer: lastSubmittedAnswer,
|
engineResponse: result?.summary || null,
|
||||||
engineResponse: result?.summary || null,
|
timestamp: Date.now(),
|
||||||
graphBeforeAnswer: result?.situationGraph ? JSON.parse(JSON.stringify(result.situationGraph)) : null,
|
},
|
||||||
selectedQuestionBeforeAnswer: q,
|
]);
|
||||||
timestamp: Date.now(),
|
}
|
||||||
status: "current",
|
|
||||||
};
|
|
||||||
|
|
||||||
// If this was a revision, mark the target turn as superseded and all later turns as stale
|
|
||||||
const revIdx = revisedTurnIndexRef.current;
|
|
||||||
if (revIdx >= 0) {
|
|
||||||
return prev.map((t, i) => {
|
|
||||||
if (i === revIdx) return { ...t, status: "superseded" };
|
|
||||||
if (i > revIdx) return { ...t, status: t.status === "superseded" ? "superseded" : "stale" };
|
|
||||||
return t;
|
|
||||||
}).concat(newTurn);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...prev, newTurn];
|
|
||||||
});
|
|
||||||
revisedTurnIndexRef.current = -1;
|
|
||||||
}, [updateStatus, lastSubmittedAnswer]);
|
}, [updateStatus, lastSubmittedAnswer]);
|
||||||
|
|
||||||
const isRevisionLoading = propIsRevisionLoading || false;
|
|
||||||
const { elapsed: startElapsed, currentMessage: startMsg } = useLoadingStatus(
|
const { elapsed: startElapsed, currentMessage: startMsg } = useLoadingStatus(
|
||||||
INITIAL_MESSAGES,
|
INITIAL_MESSAGES,
|
||||||
status === "loading"
|
status === "loading"
|
||||||
@@ -536,7 +428,6 @@ export default function ReasoningWorkspace({
|
|||||||
const canAnswer =
|
const canAnswer =
|
||||||
status === "success" &&
|
status === "success" &&
|
||||||
!isUpdating &&
|
!isUpdating &&
|
||||||
!isRevisionLoading &&
|
|
||||||
Boolean(result?.situationGraph) &&
|
Boolean(result?.situationGraph) &&
|
||||||
hasSelectedQuestion;
|
hasSelectedQuestion;
|
||||||
|
|
||||||
@@ -548,36 +439,6 @@ export default function ReasoningWorkspace({
|
|||||||
|
|
||||||
const genuineCompletion = hasGenuineCompletion(graph);
|
const genuineCompletion = hasGenuineCompletion(graph);
|
||||||
|
|
||||||
// Filter turns into active and stale groups after revision
|
|
||||||
const activeTurns = investigationHistory.filter((t) => t.status !== "superseded");
|
|
||||||
const staleTurns = investigationHistory.filter((t) => t.status === "superseded");
|
|
||||||
|
|
||||||
// Open inline revision editor for a specific turn
|
|
||||||
function openRevisionEditor(idx) {
|
|
||||||
const turn = investigationHistory[idx];
|
|
||||||
if (!turn) return;
|
|
||||||
setEditingTurnIndex(idx);
|
|
||||||
setRevisionDraft(turn.answer);
|
|
||||||
setShowRevisionEditor(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeRevisionEditor() {
|
|
||||||
setEditingTurnIndex(-1);
|
|
||||||
setShowRevisionEditor(false);
|
|
||||||
setRevisionDraft("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save revised answer — use graph checkpoint from the target turn,
|
|
||||||
// or fall back to the current situationGraph as a replay starting point.
|
|
||||||
function saveRevision(draft) {
|
|
||||||
if (!draft?.trim()) return;
|
|
||||||
closeRevisionEditor();
|
|
||||||
const checkpoint = investigationHistory[editingTurnIndex]?.graphBeforeAnswer ?? graph;
|
|
||||||
revisedTurnIndexRef.current = editingTurnIndex;
|
|
||||||
setAnswer(draft.trim());
|
|
||||||
onAnswerSubmit({ preventDefault: () => {} }, { graphCheckpoint: checkpoint, turnIndex: editingTurnIndex });
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
{/* ── Loading overlays ─────────────────────────────── */}
|
{/* ── Loading overlays ─────────────────────────────── */}
|
||||||
@@ -609,32 +470,11 @@ export default function ReasoningWorkspace({
|
|||||||
{/* Post-update acknowledgement */}
|
{/* Post-update acknowledgement */}
|
||||||
{updateStatus === "success" && canAnswer && <UpdateAcknowledgement updateResult={result} />}
|
{updateStatus === "success" && canAnswer && <UpdateAcknowledgement updateResult={result} />}
|
||||||
|
|
||||||
{/* Revision editor inline */}
|
{/* Completion state */}
|
||||||
{showRevisionEditor && investigationHistory[editingTurnIndex] && (
|
{status === "success" && !canAnswer && graph && genuineCompletion && (
|
||||||
<RevisionEditor
|
|
||||||
turn={investigationHistory[editingTurnIndex]}
|
|
||||||
onSave={(draft) => saveRevision(draft)}
|
|
||||||
onCancel={closeRevisionEditor}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Stale turns summary — shown after revision */}
|
|
||||||
{staleTurns.length > 0 && (
|
|
||||||
<div className="space-y-2">
|
|
||||||
<h3 className="text-xs font-bold uppercase tracking-wider text-gray-400">
|
|
||||||
Earlier answers that may need reviewing
|
|
||||||
</h3>
|
|
||||||
{staleTurns.map((turn, idx) => (
|
|
||||||
<StaleTurnSummary key={turn.id} turn={turn} index={idx} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Completion state — suppressed during any loading or revision */}
|
|
||||||
{status === "success" && !canAnswer && graph && genuineCompletion && !isRevisionLoading && (
|
|
||||||
<InvestigationCompleteMessage noQuestionReason={noQuestionReason} />
|
<InvestigationCompleteMessage noQuestionReason={noQuestionReason} />
|
||||||
)}
|
)}
|
||||||
{status === "success" && !canAnswer && graph && !genuineCompletion && updateStatus !== "success" && !isRevisionLoading && (
|
{status === "success" && !canAnswer && graph && !genuineCompletion && updateStatus !== "success" && (
|
||||||
<div className="rounded-lg border border-gray-200 bg-gray-50 px-5 py-4 text-center">
|
<div className="rounded-lg border border-gray-200 bg-gray-50 px-5 py-4 text-center">
|
||||||
<p className="text-sm text-gray-600">There is no further question the engine can justify at the moment.</p>
|
<p className="text-sm text-gray-600">There is no further question the engine can justify at the moment.</p>
|
||||||
<p className="mt-1 text-xs text-gray-500">More evidence may be needed before a next step is clear.</p>
|
<p className="mt-1 text-xs text-gray-500">More evidence may be needed before a next step is clear.</p>
|
||||||
@@ -682,7 +522,7 @@ export default function ReasoningWorkspace({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ── Investigation history (below the answer form) ─ */}
|
{/* ── Investigation history (below the answer form) ─ */}
|
||||||
<InvestigationHistory turns={activeTurns} onReviewTurn={openRevisionEditor} />
|
<InvestigationHistory turns={investigationHistory} />
|
||||||
|
|
||||||
{/* ── Developer details (collapsed by default) ─── */}
|
{/* ── Developer details (collapsed by default) ─── */}
|
||||||
{(status === "success" || status === "error") && graph && (
|
{(status === "success" || status === "error") && graph && (
|
||||||
@@ -716,4 +556,4 @@ export default function ReasoningWorkspace({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { useLoadingStatus, INITIAL_MESSAGES, UPDATE_MESSAGES, REVISION_MESSAGES, LoadingOverlay, resolveCurrentSummary, isTechnicalSummary };
|
export { useLoadingStatus, INITIAL_MESSAGES, UPDATE_MESSAGES, LoadingOverlay, resolveCurrentSummary, isTechnicalSummary };
|
||||||
|
|||||||
@@ -100,16 +100,6 @@ export function ScenarioResultPanels({ status, result }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Spinner for revision loading overlay ─────────────────────
|
|
||||||
function RevisionSpinner() {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className="inline-block h-4 w-4 border-[2px] border-gray-300 border-t-amber-600 rounded-full"
|
|
||||||
style={{ animation: "spin 1s linear infinite" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Message pools ───────────────────────────────────────────
|
// ── Message pools ───────────────────────────────────────────
|
||||||
const INITIAL_MESSAGES = [
|
const INITIAL_MESSAGES = [
|
||||||
{ min: 0, text: "Reading your situation" },
|
{ min: 0, text: "Reading your situation" },
|
||||||
@@ -125,13 +115,6 @@ const UPDATE_MESSAGES = [
|
|||||||
{ min: 45, text: "Choosing the next question" },
|
{ min: 45, text: "Choosing the next question" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const REVISION_MESSAGES = [
|
|
||||||
{ min: 0, text: "Reading what changed" },
|
|
||||||
{ min: 10, text: "Rebuilding the investigation" },
|
|
||||||
{ min: 25, text: "Checking what this affects" },
|
|
||||||
{ min: 45, text: "Choosing the next justified question" },
|
|
||||||
];
|
|
||||||
|
|
||||||
function useLoadingStatus(messages, isLoading) {
|
function useLoadingStatus(messages, isLoading) {
|
||||||
const [elapsed, setElapsed] = useState(0);
|
const [elapsed, setElapsed] = useState(0);
|
||||||
const startRef = useRef(null);
|
const startRef = useRef(null);
|
||||||
@@ -206,12 +189,8 @@ export default function ScenarioForm() {
|
|||||||
const [updateError, setUpdateError] = useState(null);
|
const [updateError, setUpdateError] = useState(null);
|
||||||
const [updateResult, setUpdateResult] = useState(null);
|
const [updateResult, setUpdateResult] = useState(null);
|
||||||
const [lastSubmittedAnswer, setLastSubmittedAnswer] = useState("");
|
const [lastSubmittedAnswer, setLastSubmittedAnswer] = useState("");
|
||||||
const [isRevisionLoading, setIsRevisionLoading] = useState(false);
|
|
||||||
const [revisionTurnIndex, setRevisionTurnIndex] = useState(-1);
|
|
||||||
const textareaRef = useRef(null);
|
const textareaRef = useRef(null);
|
||||||
|
|
||||||
// Loading state tracking for normal update vs revision
|
|
||||||
const isAnyUpdateLoading = updateStatus === "loading" || isRevisionLoading;
|
|
||||||
const { elapsed: startElapsed, currentMessage: startMsg } = useLoadingStatus(
|
const { elapsed: startElapsed, currentMessage: startMsg } = useLoadingStatus(
|
||||||
INITIAL_MESSAGES,
|
INITIAL_MESSAGES,
|
||||||
status === "loading"
|
status === "loading"
|
||||||
@@ -219,12 +198,7 @@ export default function ScenarioForm() {
|
|||||||
|
|
||||||
const { elapsed: updateElapsed, currentMessage: updateMsg } = useLoadingStatus(
|
const { elapsed: updateElapsed, currentMessage: updateMsg } = useLoadingStatus(
|
||||||
UPDATE_MESSAGES,
|
UPDATE_MESSAGES,
|
||||||
updateStatus === "loading" && !isRevisionLoading
|
updateStatus === "loading"
|
||||||
);
|
|
||||||
|
|
||||||
const { elapsed: revisionElapsed, currentMessage: revisionMsg } = useLoadingStatus(
|
|
||||||
REVISION_MESSAGES,
|
|
||||||
isRevisionLoading
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
@@ -257,7 +231,7 @@ export default function ScenarioForm() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdate = async (e, options = {}) => {
|
const handleUpdate = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// Guard empty answer before showing loading state
|
// Guard empty answer before showing loading state
|
||||||
@@ -267,25 +241,19 @@ export default function ScenarioForm() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isRevision = !!options.graphCheckpoint;
|
|
||||||
const turnIndex = options.turnIndex ?? revisionTurnIndex;
|
|
||||||
|
|
||||||
setUpdateStatus("loading");
|
setUpdateStatus("loading");
|
||||||
setIsRevisionLoading(isRevision);
|
|
||||||
if (isRevision) setRevisionTurnIndex(turnIndex);
|
|
||||||
setUpdateError(null);
|
setUpdateError(null);
|
||||||
setLastSubmittedAnswer(answer.trim());
|
setLastSubmittedAnswer(answer.trim());
|
||||||
|
|
||||||
const submission = await submitAnswerForUpdateCase(fetch, {
|
const submission = await submitAnswerForUpdateCase(fetch, {
|
||||||
situationGraph: options.graphCheckpoint ?? result?.situationGraph,
|
situationGraph: result?.situationGraph,
|
||||||
previousQuestion: isRevision ? undefined : result?.selectedQuestion,
|
previousQuestion: result?.selectedQuestion,
|
||||||
answer,
|
answer,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (submission.skipped) {
|
if (submission.skipped) {
|
||||||
setUpdateStatus("error");
|
setUpdateStatus("error");
|
||||||
setUpdateError(submission.data);
|
setUpdateError(submission.data);
|
||||||
setIsRevisionLoading(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,11 +261,10 @@ export default function ScenarioForm() {
|
|||||||
const outcome = submission.data;
|
const outcome = submission.data;
|
||||||
|
|
||||||
if (submission.ok && outcome.success) {
|
if (submission.ok && outcome.success) {
|
||||||
if (isRevision) setIsRevisionLoading(false);
|
|
||||||
setUpdateStatus("success");
|
setUpdateStatus("success");
|
||||||
setUpdateResult({
|
setUpdateResult({
|
||||||
...outcome,
|
...outcome,
|
||||||
previousSituationGraph: options.graphCheckpoint ?? result?.situationGraph ?? null,
|
previousSituationGraph: result?.situationGraph ?? null,
|
||||||
});
|
});
|
||||||
setResult((current) => ({
|
setResult((current) => ({
|
||||||
...current,
|
...current,
|
||||||
@@ -313,12 +280,10 @@ export default function ScenarioForm() {
|
|||||||
setAnswer("");
|
setAnswer("");
|
||||||
} else {
|
} else {
|
||||||
setUpdateStatus("error");
|
setUpdateStatus("error");
|
||||||
setIsRevisionLoading(false);
|
|
||||||
setUpdateError(outcome);
|
setUpdateError(outcome);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setUpdateStatus("error");
|
setUpdateStatus("error");
|
||||||
setIsRevisionLoading(false);
|
|
||||||
setUpdateError({ error: err.message || "Network request failed" });
|
setUpdateError({ error: err.message || "Network request failed" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -351,7 +316,7 @@ export default function ScenarioForm() {
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
{/* ── Initial analysis loading card ─────────────── */}
|
{/* ── Initial analysis loading card ─────────────── */}
|
||||||
{status === "loading" && !isRevisionLoading && (
|
{status === "loading" && (
|
||||||
<LoadingOverlay
|
<LoadingOverlay
|
||||||
isLoading={true}
|
isLoading={true}
|
||||||
elapsed={startElapsed}
|
elapsed={startElapsed}
|
||||||
@@ -360,17 +325,6 @@ export default function ScenarioForm() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ── Revision loading card ─────────────────────── */}
|
|
||||||
{isRevisionLoading && (
|
|
||||||
<div className="rounded-lg border border-amber-200 bg-amber-50 px-5 py-6" role="status" aria-busy="true">
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<RevisionSpinner />
|
|
||||||
<span className="text-base font-medium text-amber-900">Considering your revised answer</span>
|
|
||||||
</div>
|
|
||||||
<p className="mt-2 text-sm text-amber-700">{revisionMsg}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* ── Main result workspace ─────────────────────── */}
|
{/* ── Main result workspace ─────────────────────── */}
|
||||||
{(status === "success" || status === "error" || updateStatus === "success") && (
|
{(status === "success" || status === "error" || updateStatus === "success") && (
|
||||||
<ReasoningWorkspace
|
<ReasoningWorkspace
|
||||||
@@ -388,7 +342,6 @@ export default function ScenarioForm() {
|
|||||||
setAnswer={setAnswer}
|
setAnswer={setAnswer}
|
||||||
onAnswerSubmit={handleUpdate}
|
onAnswerSubmit={handleUpdate}
|
||||||
lastSubmittedAnswer={lastSubmittedAnswer}
|
lastSubmittedAnswer={lastSubmittedAnswer}
|
||||||
isRevisionLoading={isRevisionLoading}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user