There is no further question the engine can justify at the moment.
More evidence may be needed before a next step is clear.
@@ -522,7 +682,7 @@ export default function ReasoningWorkspace({
)}
{/* ── Investigation history (below the answer form) ─ */}
-
+
{/* ── Developer details (collapsed by default) ─── */}
{(status === "success" || status === "error") && graph && (
@@ -556,4 +716,4 @@ export default function ReasoningWorkspace({
);
}
-export { useLoadingStatus, INITIAL_MESSAGES, UPDATE_MESSAGES, LoadingOverlay, resolveCurrentSummary, isTechnicalSummary };
+export { useLoadingStatus, INITIAL_MESSAGES, UPDATE_MESSAGES, REVISION_MESSAGES, LoadingOverlay, resolveCurrentSummary, isTechnicalSummary };
diff --git a/components/scenario-form.jsx b/components/scenario-form.jsx
index 904e3c4..8e0c47a 100644
--- a/components/scenario-form.jsx
+++ b/components/scenario-form.jsx
@@ -100,6 +100,16 @@ export function ScenarioResultPanels({ status, result }) {
);
}
+// ── Spinner for revision loading overlay ─────────────────────
+function RevisionSpinner() {
+ return (
+
+ );
+}
+
// ── Message pools ───────────────────────────────────────────
const INITIAL_MESSAGES = [
{ min: 0, text: "Reading your situation" },
@@ -115,6 +125,13 @@ const UPDATE_MESSAGES = [
{ 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) {
const [elapsed, setElapsed] = useState(0);
const startRef = useRef(null);
@@ -189,8 +206,12 @@ export default function ScenarioForm() {
const [updateError, setUpdateError] = useState(null);
const [updateResult, setUpdateResult] = useState(null);
const [lastSubmittedAnswer, setLastSubmittedAnswer] = useState("");
+ const [isRevisionLoading, setIsRevisionLoading] = useState(false);
+ const [revisionTurnIndex, setRevisionTurnIndex] = useState(-1);
const textareaRef = useRef(null);
+ // Loading state tracking for normal update vs revision
+ const isAnyUpdateLoading = updateStatus === "loading" || isRevisionLoading;
const { elapsed: startElapsed, currentMessage: startMsg } = useLoadingStatus(
INITIAL_MESSAGES,
status === "loading"
@@ -198,7 +219,12 @@ export default function ScenarioForm() {
const { elapsed: updateElapsed, currentMessage: updateMsg } = useLoadingStatus(
UPDATE_MESSAGES,
- updateStatus === "loading"
+ updateStatus === "loading" && !isRevisionLoading
+ );
+
+ const { elapsed: revisionElapsed, currentMessage: revisionMsg } = useLoadingStatus(
+ REVISION_MESSAGES,
+ isRevisionLoading
);
const handleSubmit = async (e) => {
@@ -231,7 +257,7 @@ export default function ScenarioForm() {
}
};
- const handleUpdate = async (e) => {
+ const handleUpdate = async (e, options = {}) => {
e.preventDefault();
// Guard empty answer before showing loading state
@@ -241,19 +267,25 @@ export default function ScenarioForm() {
return;
}
+ const isRevision = !!options.graphCheckpoint;
+ const turnIndex = options.turnIndex ?? revisionTurnIndex;
+
setUpdateStatus("loading");
+ setIsRevisionLoading(isRevision);
+ if (isRevision) setRevisionTurnIndex(turnIndex);
setUpdateError(null);
setLastSubmittedAnswer(answer.trim());
const submission = await submitAnswerForUpdateCase(fetch, {
- situationGraph: result?.situationGraph,
- previousQuestion: result?.selectedQuestion,
+ situationGraph: options.graphCheckpoint ?? result?.situationGraph,
+ previousQuestion: isRevision ? undefined : result?.selectedQuestion,
answer,
});
if (submission.skipped) {
setUpdateStatus("error");
setUpdateError(submission.data);
+ setIsRevisionLoading(false);
return;
}
@@ -261,10 +293,11 @@ export default function ScenarioForm() {
const outcome = submission.data;
if (submission.ok && outcome.success) {
+ if (isRevision) setIsRevisionLoading(false);
setUpdateStatus("success");
setUpdateResult({
...outcome,
- previousSituationGraph: result?.situationGraph ?? null,
+ previousSituationGraph: options.graphCheckpoint ?? result?.situationGraph ?? null,
});
setResult((current) => ({
...current,
@@ -280,10 +313,12 @@ export default function ScenarioForm() {
setAnswer("");
} else {
setUpdateStatus("error");
+ setIsRevisionLoading(false);
setUpdateError(outcome);
}
} catch (err) {
setUpdateStatus("error");
+ setIsRevisionLoading(false);
setUpdateError({ error: err.message || "Network request failed" });
}
};
@@ -316,7 +351,7 @@ export default function ScenarioForm() {
{/* ── Initial analysis loading card ─────────────── */}
- {status === "loading" && (
+ {status === "loading" && !isRevisionLoading && (
)}
+ {/* ── Revision loading card ─────────────────────── */}
+ {isRevisionLoading && (
+
+
+
+ Considering your revised answer
+
+
{revisionMsg}
+
+ )}
+
{/* ── Main result workspace ─────────────────────── */}
{(status === "success" || status === "error" || updateStatus === "success") && (
)}