test(ui): clarify branch provenance and hierarchy
This commit is contained in:
@@ -46,7 +46,7 @@ function NewIndicator({ visible }) {
|
||||
|
||||
/* ── Single branch row ─────────────────────────────────── */
|
||||
|
||||
function BranchRow({ id, label, active, isNew, onClick }) {
|
||||
function BranchRow({ id, label, active, isNew, origin, onClick }) {
|
||||
const isActive = Boolean(active);
|
||||
|
||||
return (
|
||||
@@ -54,7 +54,7 @@ function BranchRow({ id, label, active, isNew, onClick }) {
|
||||
onClick={onClick}
|
||||
disabled={isActive}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={`w-full flex items-center gap-2 rounded-md px-3 py-2 text-left transition text-sm ${
|
||||
className={`w-full flex items-start gap-2 rounded-md px-3 py-2 text-left transition text-sm ${
|
||||
isActive
|
||||
? "bg-blue-50/80 border border-blue-200/60 text-blue-900 font-medium"
|
||||
: "text-gray-600 hover:bg-gray-100/70 hover:text-gray-800 border border-transparent"
|
||||
@@ -70,8 +70,15 @@ function BranchRow({ id, label, active, isNew, onClick }) {
|
||||
{isActive ? "●" : "○"}
|
||||
</span>
|
||||
|
||||
{/* Branch label */}
|
||||
<span className="flex-1 truncate">{label}</span>
|
||||
{/* Branch label + origin */}
|
||||
<span className="flex-1 min-w-0">
|
||||
<span className="truncate block">{label}</span>
|
||||
{origin && (
|
||||
<span className="block text-[11px] leading-tight text-gray-500/80 truncate" title={origin}>
|
||||
{origin}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
|
||||
{/* Passive new-result indicator (only for inactive branches) */}
|
||||
{!isActive && <NewIndicator visible={isNew} />}
|
||||
@@ -96,11 +103,11 @@ export default function ExperimentalBranchSwitcher({
|
||||
aria-label="Experimental branch switcher — RTO.25A"
|
||||
>
|
||||
{/* Label — clearly experimental */}
|
||||
<h2 className="mb-1 text-[10px] font-semibold tracking-widest uppercase text-gray-400">
|
||||
<h2 className="mb-1 text-[10px] font-semibold tracking-widest uppercase text-gray-600">
|
||||
Branches{" "}
|
||||
<span className="font-normal text-gray-300">(exp)</span>
|
||||
<span className="font-normal text-gray-500">(exp)</span>
|
||||
</h2>
|
||||
<p className="mb-3 text-[11px] text-gray-400/60">
|
||||
<p className="mb-3 text-[11px] font-medium leading-tight text-gray-500/80">
|
||||
Browse branches. Current focus is preserved.
|
||||
</p>
|
||||
|
||||
@@ -112,6 +119,7 @@ export default function ExperimentalBranchSwitcher({
|
||||
label={branch.label}
|
||||
active={activeBranchId === branch.id}
|
||||
isNew={Boolean(branchNewResults[branch.id])}
|
||||
origin={branch.origin}
|
||||
onClick={() => onBranchSelect?.(branch.id)}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -84,10 +84,10 @@ export default function InvestigationMap({ turnCount = 0 }) {
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-gray-200/60 bg-gray-50/30 p-4" role="region" aria-label="Investigation map preview">
|
||||
<h2 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h2 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Investigation Map
|
||||
</h2>
|
||||
<p className="mb-3 text-xs text-gray-400/70">
|
||||
<p className="mb-3 text-xs font-medium leading-tight text-gray-500/80">
|
||||
Active investigation topics and their status.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ function InvestigationSummaryPanelV2({ graph, selectedQuestion, result, updateSt
|
||||
<div>
|
||||
{stillInvestigating.length > 1 ? (
|
||||
<>
|
||||
<h3 className="mb-2 text-xs font-medium text-gray-400">Still investigating</h3>
|
||||
<h3 className="mb-2 text-xs font-medium text-gray-500">Still investigating</h3>
|
||||
<ul className="space-y-1.5">
|
||||
{Object.entries(investigatingByGroup).map(([group, items]) => (
|
||||
<li key={group}>
|
||||
@@ -227,7 +227,7 @@ function InvestigationSummaryPanelV2({ graph, selectedQuestion, result, updateSt
|
||||
{/* ── What we have learned ────────────────────────── */}
|
||||
{known.length > 0 && (
|
||||
<div>
|
||||
<h3 className="mb-2 text-xs font-medium text-gray-400">What we know</h3>
|
||||
<h3 className="mb-2 text-xs font-medium text-gray-500">What we know</h3>
|
||||
<ul className="space-y-1.5">
|
||||
{known.map((item, i) => (
|
||||
<li key={i} className="flex items-start gap-2">
|
||||
@@ -243,8 +243,8 @@ function InvestigationSummaryPanelV2({ graph, selectedQuestion, result, updateSt
|
||||
|
||||
{/* ── Quiet reasoning summary — secondary ─────────── */}
|
||||
<div className="pt-2 border-t border-gray-200/40">
|
||||
<p className="text-[10px] font-medium tracking-widest uppercase text-gray-300 mb-1.5">Reasoning</p>
|
||||
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-gray-400">
|
||||
<p className="text-[10px] font-semibold tracking-widest uppercase text-gray-500 mb-1.5">Reasoning</p>
|
||||
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-gray-500">
|
||||
{reasonEntries.map(([label, count]) => (
|
||||
<span key={label}>
|
||||
{count} {label}
|
||||
|
||||
@@ -47,7 +47,7 @@ function KnownSection({ title, items }) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-400">
|
||||
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-500">
|
||||
{title}
|
||||
</h3>
|
||||
<ul className="space-y-1.5">
|
||||
@@ -67,7 +67,7 @@ function InvestigatingSection({ title, items }) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-400">
|
||||
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-500">
|
||||
{title}
|
||||
</h3>
|
||||
<ul className="space-y-1.5">
|
||||
@@ -87,7 +87,7 @@ function ExplanationSection({ items }) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-400">
|
||||
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-500">
|
||||
Possible explanations
|
||||
</h3>
|
||||
<ul className="space-y-1.5">
|
||||
@@ -102,10 +102,10 @@ function QuietSummary({ text }) {
|
||||
|
||||
return (
|
||||
<div className="pt-2 border-t border-gray-200/40">
|
||||
<p className="text-[10px] font-medium tracking-widest uppercase text-gray-300 mb-1.5">
|
||||
<p className="text-[10px] font-semibold tracking-widest uppercase text-gray-500 mb-1.5">
|
||||
Investigation state
|
||||
</p>
|
||||
<p className="text-xs text-gray-400">{text}</p>
|
||||
<p className="text-xs text-gray-500">{text}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ function InvestigationSummaryPanel({ graph, selectedQuestion, result, updateStat
|
||||
{/* Current understanding */}
|
||||
{currentUnderstanding && (
|
||||
<div>
|
||||
<h3 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-400/70">
|
||||
<h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
What we understand so far
|
||||
</h3>
|
||||
<p className="text-sm leading-relaxed text-gray-600">{currentUnderstanding}</p>
|
||||
|
||||
@@ -320,7 +320,7 @@ function CurrentUnderstandingCard({ currentSummary, plainLanguage }) {
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-gray-100/80 bg-transparent px-6 pt-5 pb-6">
|
||||
<h2 className="mb-3 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h2 className="mb-3 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Understanding
|
||||
</h2>
|
||||
<p className="text-sm leading-relaxed text-gray-600">{summary}</p>
|
||||
@@ -334,7 +334,7 @@ function PlainLanguageCard({ summary }) {
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-gray-100/80 bg-transparent px-6 pt-5 pb-6">
|
||||
<h2 className="mb-3 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h2 className="mb-3 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Understanding
|
||||
</h2>
|
||||
<p className="text-sm leading-relaxed text-gray-600">{summary}</p>
|
||||
@@ -382,7 +382,7 @@ function InvestigationHistory({ turns }) {
|
||||
|
||||
return (
|
||||
<div className="space-y-3" data-testid="investigation-history">
|
||||
<h2 className="text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h2 className="text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
History
|
||||
</h2>
|
||||
<div className="space-y-2">
|
||||
@@ -402,7 +402,7 @@ function OriginalSituation({ scenario, centralStatement }) {
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-gray-200/60 bg-gray-50/40 px-5 py-4">
|
||||
<h2 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h2 className="mb-2 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Situation
|
||||
</h2>
|
||||
|
||||
@@ -832,7 +832,7 @@ export default function ReasoningWorkspace({
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h2 className="text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
In this branch — Open questions
|
||||
</h2>
|
||||
<div className="space-y-1">
|
||||
@@ -894,7 +894,7 @@ export default function ReasoningWorkspace({
|
||||
{/* Formulated question */}
|
||||
{focused?.question?.trim() ? (
|
||||
<div>
|
||||
<h3 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Question
|
||||
</h3>
|
||||
<p className="text-base font-medium leading-relaxed text-gray-900">
|
||||
@@ -944,7 +944,7 @@ export default function ReasoningWorkspace({
|
||||
{focused?.result && (
|
||||
<>
|
||||
<div>
|
||||
<h3 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
What we learned
|
||||
</h3>
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
@@ -955,7 +955,7 @@ export default function ReasoningWorkspace({
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Still unclear
|
||||
</h3>
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
@@ -967,7 +967,7 @@ export default function ReasoningWorkspace({
|
||||
|
||||
{focused.result.assumptions && focused.result.assumptions.length > 0 && (
|
||||
<div>
|
||||
<h3 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Assumptions in this response
|
||||
</h3>
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
@@ -980,7 +980,7 @@ export default function ReasoningWorkspace({
|
||||
|
||||
{focused.result.relationships && focused.result.relationships.length > 0 && (
|
||||
<div>
|
||||
<h3 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Connections
|
||||
</h3>
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
@@ -993,7 +993,7 @@ export default function ReasoningWorkspace({
|
||||
|
||||
{focused.result.possibleFollowUpQuestions && focused.result.possibleFollowUpQuestions.length > 0 && (
|
||||
<div>
|
||||
<h3 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Questions this raises
|
||||
</h3>
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
@@ -1059,7 +1059,7 @@ export default function ReasoningWorkspace({
|
||||
{/* Done for now — separate visual area */}
|
||||
{doneForNowIds.length > 0 && (
|
||||
<div className="pt-3 border-t border-gray-200">
|
||||
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-300">
|
||||
<h3 className="mb-2 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
|
||||
Done for now
|
||||
</h3>
|
||||
<div className="space-y-1">
|
||||
|
||||
@@ -225,8 +225,16 @@ export default function ScenarioForm() {
|
||||
/* ── RTO.25A — passive late-result branch switcher (experimental) ── */
|
||||
|
||||
const BRANCHES = [
|
||||
{ id: "branch-a", label: "Competitor development" },
|
||||
{ id: "branch-b", label: "Customer demand" },
|
||||
{
|
||||
id: "branch-a",
|
||||
label: "Competitor development",
|
||||
origin: "Whether competitors are developing similar products and when they might release them",
|
||||
},
|
||||
{
|
||||
id: "branch-b",
|
||||
label: "Customer demand",
|
||||
origin: "How many customers will buy the product, and what revenue that represents",
|
||||
},
|
||||
];
|
||||
|
||||
const [activeBranchId, setActiveBranchId] = useState("branch-b");
|
||||
|
||||
Reference in New Issue
Block a user