docs: complete scene 8 chat entry slice
This commit is contained in:
@@ -267,9 +267,11 @@ The next presentation work is intentionally split into five implementation
|
||||
slices followed by a rehearsal gate. The broader story-flow review remains a
|
||||
separate activity after these surfaces are stable.
|
||||
|
||||
1. **Scene 8 chat entry:** replace the standalone run button with a full-screen
|
||||
assistant-style chat entry. The composer/send action starts the first
|
||||
prepared authoring conversation; it does not start the workflow run.
|
||||
1. **Completed: Scene 8 chat entry:** replaced the standalone run button with
|
||||
a full-screen assistant-style chat entry. The local composer/send action
|
||||
reveals the first prepared authoring conversation without starting a
|
||||
workflow run. Implementation:
|
||||
[`Scene 8 chat entry`](historical/superpowers/plans/2026-07-12-scene-8-chat-entry.md).
|
||||
2. **Scene 9 assistant modal:** remove the lower chat dock, give the prepared
|
||||
lifecycle canvas the available stage, and expose the synchronized authoring
|
||||
conversation through an assistant-ui modal anchored on the left.
|
||||
|
||||
+3
@@ -1,5 +1,8 @@
|
||||
# Scene 8 Chat Entry Implementation Plan
|
||||
|
||||
> Historical: completed on 2026-07-12. Task commits and final verification are
|
||||
> recorded in repository history.
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox syntax for tracking.
|
||||
|
||||
**Goal:** Replace Scene 8's phase-rail transcript and standalone run button with a full-screen assistant-style chat entry whose Send action reveals the first deterministic authoring turn without starting a workflow run.
|
||||
+12
-9
@@ -180,8 +180,11 @@ claim boundaries and future work explicit, and end on the canonical defense
|
||||
discussion index rather than a benchmark or generic conclusion.
|
||||
|
||||
Scenes 8 and 9 use the canonical prepared-authoring recording as their only
|
||||
execution evidence. Scene 8 is a full-screen conversation that establishes the
|
||||
external agent handoff; Scene 9 breaks the prepared authoring into five phases
|
||||
execution evidence. Scene 8 is a full-screen chat entry: its prefilled request
|
||||
is submitted locally, then reveals the first deterministic user, assistant, and
|
||||
Discover tool group. It is deterministic replay, not a live LLM chat, and does
|
||||
not start a workflow run. The handoff beat reveals the full prepared conversation;
|
||||
Scene 9 breaks the prepared authoring into five phases
|
||||
with the same conversation contracted into a synchronized bottom dock. Each
|
||||
phase opens its matching prepared tool group beneath a factual source, graph,
|
||||
repair, artifact, or deployment view. Neither scene calls workflow authoring
|
||||
@@ -330,11 +333,11 @@ Scenes 8 and 9 are the prepared authoring story. They use deterministic data
|
||||
from the committed `projectPreparedAuthoring()` recording and never call
|
||||
workflow authoring RPC operations.
|
||||
|
||||
- **Scene 8 (Agent Handoff)**: a full-screen prepared conversation that
|
||||
establishes the external agent interface. The `request` beat shows the
|
||||
operator requesting a report workflow; the `handoff` beat reveals the full
|
||||
completed conversation with prepared `wf` tool groups across all authoring
|
||||
phases.
|
||||
- **Scene 8 (Agent Handoff)**: a full-screen deterministic chat entry that
|
||||
pre-fills the report-authoring request. Send is local presentation state and
|
||||
reveals the first prepared Discover tool group; the `handoff` beat reveals
|
||||
the full completed conversation with prepared `wf` tool groups across all
|
||||
authoring phases. This is not a live LLM chat or workflow run.
|
||||
- **Scene 9 (Prepared Workflow Lifecycle)**: a five-phase lifecycle
|
||||
(discover, draft, validate, artifact, deployment) with a compact phase rail
|
||||
and one dominant factual product projection per beat. The Scene 8 thread
|
||||
@@ -342,8 +345,8 @@ workflow authoring RPC operations.
|
||||
current beat. There is no detached trace modal or second transcript.
|
||||
|
||||
The authoring scenes consume deterministic prepared data and never call
|
||||
workflow authoring RPCs — only `workflow.health` infrastructure pings are
|
||||
permitted.
|
||||
workflow authoring RPCs. Scene 8 also skips live target probing so its request
|
||||
and Send path remain fully local; later execution scenes own live-run behavior.
|
||||
|
||||
### Demo Climax (Scenes 10–12)
|
||||
|
||||
|
||||
@@ -263,15 +263,17 @@ describe("PresentationRoute", () => {
|
||||
expect(screen.queryByText(/checking reachability/i)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("keeps Scene 8 local after a healthy target probe", async () => {
|
||||
it("keeps Scene 8 local with a configured target", async () => {
|
||||
window.sessionStorage.setItem("lda.workflowConsole.target", "http://127.0.0.1:8765/rpc");
|
||||
window.location.hash = "#scene/agent-handoff/request";
|
||||
mockedCallOperation.mockClear();
|
||||
const { PresentationRoute } = await import("./PresentationRoute.js");
|
||||
render(<PresentationRoute />);
|
||||
|
||||
expect(await screen.findByText(/Live target ready/i)).toBeInTheDocument();
|
||||
expect(await screen.findByText(/Replay evidence is active/i)).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Send" })).toBeEnabled();
|
||||
expect(screen.queryByRole("button", { name: "Run prepared workflow" })).not.toBeInTheDocument();
|
||||
expect(mockedCallOperation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("opens Scene 10 approval from the canonical hash", async () => {
|
||||
|
||||
@@ -53,7 +53,8 @@ export const PresentationRoute = () => {
|
||||
|
||||
const presentationTarget = useMemo(() => resolvePresentationTarget(), []);
|
||||
const demo = useDemoTimeline(presentationTarget.target, recordEvidence, recording);
|
||||
const targetStatus = usePresentationTargetStatus(presentationTarget, demo.state);
|
||||
const isScene8 = state.location.kind === "main" && state.location.sceneId === "agent-handoff";
|
||||
const targetStatus = usePresentationTargetStatus(presentationTarget, demo.state, !isScene8);
|
||||
const timelineAgent = useTimelineAgent(demo, {
|
||||
mode: presentationTarget.mode === "live" ? "live" : "replay",
|
||||
status: targetStatus,
|
||||
|
||||
@@ -154,9 +154,14 @@ describe("projectPreparedAuthoringThread", () => {
|
||||
});
|
||||
|
||||
it("keeps the canonical projection unchanged without a request override", () => {
|
||||
expect(projectPreparedAuthoringThread("discover")).toEqual(
|
||||
projectPreparedAuthoringThread("discover"),
|
||||
);
|
||||
const firstUser = projectPreparedAuthoringThread("discover")
|
||||
.find((message) => message.role === "user");
|
||||
expect(firstUser?.parts).toEqual([
|
||||
{
|
||||
type: "text",
|
||||
text: "We need to author a report workflow for the lda_report scenario. What sources and capabilities are available?",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("overrides only the first user request and preserves Discover tool data", () => {
|
||||
|
||||
@@ -287,15 +287,15 @@ export const projectPreparedAuthoringThread = (
|
||||
|
||||
let requestReplaced = false;
|
||||
return recording.slice(0, finalPhaseIndex + 1).flatMap((phase) => {
|
||||
const conversation = phase.conversation.map((turn, index) =>
|
||||
agentTextMessage(
|
||||
const conversation = phase.conversation.map((turn, index) => {
|
||||
const shouldReplaceRequest = requestOverride !== undefined && !requestReplaced && turn.role === "user";
|
||||
if (shouldReplaceRequest) requestReplaced = true;
|
||||
return agentTextMessage(
|
||||
`authoring-${phase.phase}-message-${index}`,
|
||||
turn.role,
|
||||
requestOverride !== undefined && !requestReplaced && turn.role === "user"
|
||||
? (requestReplaced = true, requestOverride)
|
||||
: turn.text,
|
||||
),
|
||||
);
|
||||
shouldReplaceRequest ? requestOverride : turn.text,
|
||||
);
|
||||
});
|
||||
const groupId = authoringToolGroupId(phase.phase);
|
||||
const toolParts = phase.commands.flatMap((command, index) => {
|
||||
const callId = `${groupId}-command-${index}`;
|
||||
|
||||
@@ -3030,7 +3030,7 @@
|
||||
padding: clamp(1.5rem, 4vw, 3.75rem) clamp(1rem, 5vw, 4.5rem);
|
||||
border: 1px solid var(--authoring-rule, var(--stage-line));
|
||||
border-radius: 0.35rem;
|
||||
background: color-mix(in oklch, var(--stage-canvas) 92%, white);
|
||||
background: var(--authoring-paper, var(--stage-canvas));
|
||||
box-shadow: 0 1.25rem 3rem color-mix(in oklch, var(--stage-ink) 10%, transparent);
|
||||
}
|
||||
|
||||
@@ -3096,7 +3096,7 @@
|
||||
resize: vertical;
|
||||
border-color: var(--authoring-rule, var(--stage-line));
|
||||
border-radius: 0.2rem;
|
||||
background: color-mix(in oklch, var(--stage-canvas) 82%, white);
|
||||
background: color-mix(in oklch, var(--authoring-paper, var(--stage-canvas)) 88%, var(--authoring-muted, var(--text-secondary)));
|
||||
color: var(--authoring-ink, var(--text-primary));
|
||||
font: 1.05rem/1.45 var(--font-interface);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ const liveActive = (state: DemoTimelineState): boolean =>
|
||||
export const usePresentationTargetStatus = (
|
||||
targetState: PresentationTargetState,
|
||||
demoState: DemoTimelineState,
|
||||
probeEnabled = true,
|
||||
): PresentationTargetHealth => {
|
||||
const [probe, setProbe] = useState<TargetProbeState>(
|
||||
targetState.mode === "live" ? "checking" : "none",
|
||||
@@ -27,6 +28,11 @@ export const usePresentationTargetStatus = (
|
||||
setFailureReason(targetState.reason);
|
||||
return;
|
||||
}
|
||||
if (!probeEnabled) {
|
||||
setProbe("none");
|
||||
setFailureReason("deterministic Scene 8 replay");
|
||||
return;
|
||||
}
|
||||
|
||||
setProbe("checking");
|
||||
setFailureReason(undefined);
|
||||
@@ -50,7 +56,17 @@ export const usePresentationTargetStatus = (
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [targetState]);
|
||||
}, [probeEnabled, targetState]);
|
||||
|
||||
if (!probeEnabled) {
|
||||
return presentationTargetHealth({
|
||||
target: null,
|
||||
probe: "none",
|
||||
liveActive: false,
|
||||
replayActive: true,
|
||||
failureReason: "deterministic Scene 8 replay",
|
||||
});
|
||||
}
|
||||
|
||||
return presentationTargetHealth({
|
||||
target: targetState.mode === "live" ? targetState.target : null,
|
||||
|
||||
Reference in New Issue
Block a user