fix: close remaining compositor correctness gaps
- F1: Preload replayEvidence on mount so evidence drawer shows records in replay mode - F2: close_overlay forces evidenceModeOverride to hidden when beat-default is open - F3: Add CSS transitions (opacity, scale, border, background) for beat-driven elements - F4: Fix planned time from 20 to 15 minutes for defense presentation - F5: Fix stale speaker notes by keying textarea on beat.id - F6: Lazy-initialize startedAt via useReducer initializer instead of module-level Date.now() - F7: Fix MCP evidence pointer to Anthropic + Cloudflare
This commit is contained in:
@@ -36,13 +36,16 @@ export const PresentationRoute = () => {
|
||||
const [state, dispatch] = useReducer(
|
||||
presentationReducer,
|
||||
initialPresentationState,
|
||||
(initial) => presentationReducer(initial, { type: "jump_hash", hash: window.location.hash }),
|
||||
(initial) => presentationReducer(
|
||||
{ ...initial, startedAt: Date.now() },
|
||||
{ type: "jump_hash", hash: window.location.hash },
|
||||
),
|
||||
);
|
||||
|
||||
const recording = useMemo(() => loadCanonicalDemoRecording(), []);
|
||||
const replayEvidence = useMemo(() => projectRecordingToEvidence(recording), [recording]);
|
||||
|
||||
const [evidence, setEvidence] = useState<readonly EvidenceRecord[]>([]);
|
||||
const [evidence, setEvidence] = useState<readonly EvidenceRecord[]>(replayEvidence);
|
||||
const recordEvidence = useCallback((record: EvidenceRecord) => {
|
||||
setEvidence((records) => [...records, record]);
|
||||
}, []);
|
||||
|
||||
@@ -56,7 +56,7 @@ export const PresenterControls = ({
|
||||
return `${m}:${s.toString().padStart(2, "0")}`;
|
||||
};
|
||||
|
||||
const plannedMinutes = 20;
|
||||
const plannedMinutes = 15;
|
||||
|
||||
return (
|
||||
<div className="presenter-controls" role="dialog" aria-label="presenter controls">
|
||||
@@ -76,6 +76,7 @@ export const PresenterControls = ({
|
||||
<label>
|
||||
Speaker notes
|
||||
<textarea
|
||||
key={currentBeat?.id ?? "none"}
|
||||
defaultValue={currentBeat?.caption ?? ""}
|
||||
rows={3}
|
||||
placeholder="Add notes for this beat..."
|
||||
|
||||
@@ -181,6 +181,13 @@ export const presentationReducer = (
|
||||
case "close_overlay": {
|
||||
if (state.selectedNodeId !== null) return { ...state, selectedNodeId: null };
|
||||
if (state.evidenceModeOverride !== null) return { ...state, evidenceModeOverride: null };
|
||||
const derivedEvidenceMode = (() => {
|
||||
if (state.location.kind === "discussion") return "hidden" as const;
|
||||
const scene = findScene(state.location.sceneId);
|
||||
const beat = scene?.beats.find((b) => b.id === (state.location as MainLocation).beatId);
|
||||
return beat?.evidenceMode ?? "hidden";
|
||||
})();
|
||||
if (derivedEvidenceMode !== "hidden") return { ...state, evidenceModeOverride: "hidden" };
|
||||
if (state.discussionIndexOpen) return { ...state, discussionIndexOpen: false };
|
||||
if (state.controlsOpen) return { ...state, controlsOpen: false };
|
||||
if (state.location.kind === "discussion") {
|
||||
|
||||
@@ -828,42 +828,77 @@ body {
|
||||
/* Beat-driven active states */
|
||||
.scene-body__boundary-side--dim {
|
||||
opacity: 0.4;
|
||||
transform: scale(0.97);
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
|
||||
.scene-body__boundary-side {
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
|
||||
.scene-body__lifecycle-stage,
|
||||
.scene-body__authoring-step {
|
||||
transition: opacity 0.3s ease, transform 0.25s ease, border-color 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.scene-body__lifecycle-stage:not(.scene-body__lifecycle-stage--active) {
|
||||
opacity: 0.4;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.scene-body__lifecycle-stage--active {
|
||||
border-color: oklch(0.7 0.16 195);
|
||||
background: oklch(0.2 0.06 195);
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.scene-body__architecture-layer {
|
||||
transition: opacity 0.3s ease, transform 0.25s ease, border-color 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.scene-body__architecture-layer:not(.scene-body__architecture-layer--active):not(.scene-body__architecture-layer--node) {
|
||||
opacity: 0.4;
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
.scene-body__architecture-layer--active {
|
||||
border-color: oklch(0.7 0.16 195);
|
||||
background: oklch(0.2 0.06 195);
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.scene-body__authoring-step:not(.scene-body__authoring-step--active) {
|
||||
opacity: 0.4;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.scene-body__authoring-step--active {
|
||||
border-color: oklch(0.7 0.16 195);
|
||||
background: oklch(0.2 0.06 195);
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.scene-body__evaluation-stat {
|
||||
transition: opacity 0.3s ease, transform 0.25s ease, border-color 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.scene-body__evaluation-stat:not(.scene-body__evaluation-stat--active) {
|
||||
opacity: 0.4;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.scene-body__evaluation-stat--active {
|
||||
border-color: oklch(0.7 0.16 195);
|
||||
background: oklch(0.2 0.06 195);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.scene-body__positioning-card {
|
||||
transition: opacity 0.3s ease, transform 0.25s ease, border-color 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.scene-body__positioning-card--active {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
@media (max-height: 760px) {
|
||||
|
||||
@@ -281,7 +281,7 @@ export const discussionBranches = defineDiscussionBranches([
|
||||
parentSceneId: "positioning",
|
||||
title: "MCP and agent-facing scale",
|
||||
claimClass: "external-context",
|
||||
evidencePointer: "Thesis: Model Context Protocol; Anthropic MCP documentation; Cloudflare Code Mode",
|
||||
evidencePointer: "Thesis: Model Context Protocol; Anthropic MCP; Cloudflare Code Mode",
|
||||
summary: "MCP is a capability protocol; progressive discovery addresses large agent-facing surfaces.",
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user