"use client"; import React, { useState, useRef, useEffect, useMemo } from "react"; import DiagnosticsView from "@/components/diagnostics-view"; import GraphUpdateView from "@/components/graph-update-view"; import SituationGraphView from "@/components/situation-graph-view"; // ── Technical summary detector (main view filters these) ─── const TECHNICAL_PATTERNS = [ /nodes?\s*[:\d]/i, /edges?\s*[:\d]/i, /\b(?:unknown|observation|conclusion)\b\s/i, /\bsorted\b/i, /by_kind/i, /\b(?:node|edge|unknown|state)\s+count/i, ]; function isTechnicalSummary(summary) { if (!summary || typeof summary !== "string") return false; const trimmed = summary.trim(); if (!trimmed) return false; for (const p of TECHNICAL_PATTERNS) { if (p.test(trimmed)) return true; } return false; } function resolveCurrentSummary(currentSummary) { if (isTechnicalSummary(currentSummary)) { return null; } return currentSummary || null; } // ── Status message pools for loading feedback ──────────────── const INITIAL_MESSAGES = [ { min: 0, text: "Reading your situation" }, { min: 10, text: "Building a structured understanding" }, { min: 25, text: "Identifying what is known and still unclear" }, { min: 45, text: "Selecting the next useful question" }, ]; const UPDATE_MESSAGES = [ { min: 0, text: "Considering your answer" }, { min: 10, text: "Updating the situation" }, { min: 25, text: "Checking what changed" }, { 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); useEffect(() => { if (isLoading) { startRef.current = Date.now(); const iv = setInterval(() => { setElapsed(Math.floor((Date.now() - startRef.current) / 1000)); }, 1000); return () => clearInterval(iv); } else { setElapsed(0); startRef.current = null; } }, [isLoading]); const currentMessage = useMemo(() => { if (!messages || messages.length === 0) return ""; let msg = messages[0].text; for (const m of messages) { if (elapsed >= m.min) msg = m.text; } return msg; }, [messages, elapsed]); return { elapsed, currentMessage }; } // ── Revision warning banner ───────────────────────────────── function RevisionWarningCard() { return (
Changing this answer may alter the questions and conclusions that followed it.
); } // ── Revision inline editor ──────────────────────────────────── function RevisionEditor({ turn, onSave, onCancel }) { const [draft, setDraft] = useState(turn.answer); return (

{turn.question}