test(ui): make inferred questions originate branches
This commit is contained in:
@@ -362,17 +362,28 @@ function BranchNotebookContent({
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Why this branch exists */}
|
||||
{/* Why this branch exists — origin question is primary */}
|
||||
{branchContext && (
|
||||
<div className="rounded-lg border border-blue-200/60 bg-blue-50/40 px-5 py-4">
|
||||
<h2 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Current branch
|
||||
Investigating
|
||||
</h2>
|
||||
<p className="text-base font-medium leading-tight text-gray-900">{branchContext.label}</p>
|
||||
{branchContext.origin && (
|
||||
<p className="mt-2 text-sm leading-relaxed text-gray-600">
|
||||
Trying to understand: {branchContext.origin}
|
||||
</p>
|
||||
{branchContext.originQuestion ? (
|
||||
<>
|
||||
<p className="text-base leading-relaxed text-gray-900">{branchContext.originQuestion.text}</p>
|
||||
{branchContext.label && branchContext.originQuestion.text !== branchContext.label && (
|
||||
<p className="mt-2 text-xs text-gray-500/70">Branch: {branchContext.label}</p>
|
||||
)}
|
||||
</>
|
||||
) : branchContext.origin ? (
|
||||
<>
|
||||
<p className="text-base font-medium leading-tight text-gray-900">{branchContext.label}</p>
|
||||
<p className="mt-2 text-sm leading-relaxed text-gray-600">
|
||||
Trying to understand: {branchContext.origin}
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<p className="text-base font-medium leading-tight text-gray-900">{branchContext.label}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -237,8 +237,8 @@ export function derivePrimarySurface(result, status, showExperimentView, scenari
|
||||
|
||||
const valid = hasValidInvestigationContext(result, status, scenario);
|
||||
|
||||
// RTO.28A: show branch-selection surface when investigation exists but no branch is active
|
||||
if (showExperimentView && valid && !activeBranchId) return "BRANCH_SELECTION";
|
||||
// RTO.28B: show question-selection surface when investigation exists but no question/branch is active
|
||||
if (showExperimentView && valid && !activeBranchId) return "QUESTION_SELECTION";
|
||||
|
||||
if (showExperimentView && valid) return "EXPERIMENT_NOTEBOOK";
|
||||
if (!showExperimentView && valid) return "NORMAL_WORKSPACE";
|
||||
@@ -283,6 +283,15 @@ export default function ScenarioForm() {
|
||||
// Use fixture branches as the authoritative source when available
|
||||
const BRANCHES = useMemo(() => branchScoped.getBranches(), [branchScoped]);
|
||||
|
||||
// Track the originating question for provenance
|
||||
const [originQuestion, setOriginQuestion] = useState(null);
|
||||
|
||||
// Extract inferred questions from the fixture (flat list for post-Analyse surface)
|
||||
const inferredQuestions = useMemo(() => {
|
||||
if (!branchScoped || typeof branchScoped.getAllInferredQuestions !== 'function') return [];
|
||||
return branchScoped.getAllInferredQuestions();
|
||||
}, [branchScoped]);
|
||||
|
||||
// Simulate a late semantic result arriving on Branch A ~2s after a graph loads
|
||||
useEffect(() => {
|
||||
if (status !== "success" && status !== "error") return;
|
||||
@@ -538,7 +547,7 @@ export default function ScenarioForm() {
|
||||
<>
|
||||
<PulseStyle />
|
||||
{!activeBranchId ? (
|
||||
/* RTO.28A: no active branch — show branch-selection surface */
|
||||
/* RTO.28B: inferred questions surface — user chooses what to investigate */
|
||||
<div className="max-w-xl mx-auto space-y-6">
|
||||
<div className="space-y-4">
|
||||
{/* Situation remains visible */}
|
||||
@@ -552,25 +561,30 @@ export default function ScenarioForm() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Branch selection */}
|
||||
{/* Inferred questions — user chooses what to investigate */}
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-xs font-medium text-gray-700">Choose a branch to continue</h2>
|
||||
<p className="text-sm text-gray-500">These are the current lines of inquiry. Pick whichever you want to work on.</p>
|
||||
<h2 className="text-xs font-medium text-gray-700">Questions to explore</h2>
|
||||
<p className="text-sm text-gray-500">Click a question to start investigating. A branch will be created for your choice.</p>
|
||||
|
||||
{BRANCHES.map((branch) => (
|
||||
{inferredQuestions.map((q) => (
|
||||
<button
|
||||
key={branch.id}
|
||||
onClick={() => setActiveBranchId(branch.id)}
|
||||
key={q.id}
|
||||
onClick={() => {
|
||||
const targetBranch = BRANCHES.find(b => b.id === q.branchId);
|
||||
if (targetBranch) {
|
||||
setActiveBranchId(targetBranch.id);
|
||||
setOriginQuestion({ id: q.id, text: q.text });
|
||||
}
|
||||
}}
|
||||
className="w-full text-left rounded-lg border border-gray-200 bg-white px-5 py-4 transition hover:border-gray-300 hover:bg-gray-50"
|
||||
>
|
||||
<span className="block font-medium text-sm text-gray-900">{branch.label}</span>
|
||||
{branch.origin && (
|
||||
<span className="block mt-1 text-xs leading-relaxed text-gray-500/80">
|
||||
{branch.origin}
|
||||
</span>
|
||||
)}
|
||||
<span className="block text-sm leading-relaxed text-gray-900">{q.text}</span>
|
||||
</button>
|
||||
))}
|
||||
|
||||
{inferredQuestions.length === 0 && (
|
||||
<p className="text-sm text-gray-400">No questions available yet.</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@@ -592,7 +606,7 @@ export default function ScenarioForm() {
|
||||
setAnswer={() => {}}
|
||||
onAnswerSubmit={async (e) => e.preventDefault()}
|
||||
lastSubmittedAnswer=""
|
||||
branchContext={branchContext}
|
||||
branchContext={{ ...branchContext, originQuestion: originQuestion }}
|
||||
experimentalBranches={BRANCHES.length > 0 ? BRANCHES : undefined}
|
||||
branchLocalQuestions={experimentalBranchQuestions.length > 0 ? experimentalBranchQuestions : undefined}
|
||||
branchLocalContributions={experimentalBranchContributions.length > 0 ? experimentalBranchContributions : undefined}
|
||||
|
||||
Reference in New Issue
Block a user