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
|
slices followed by a rehearsal gate. The broader story-flow review remains a
|
||||||
separate activity after these surfaces are stable.
|
separate activity after these surfaces are stable.
|
||||||
|
|
||||||
1. **Scene 8 chat entry:** replace the standalone run button with a full-screen
|
1. **Completed: Scene 8 chat entry:** replaced the standalone run button with
|
||||||
assistant-style chat entry. The composer/send action starts the first
|
a full-screen assistant-style chat entry. The local composer/send action
|
||||||
prepared authoring conversation; it does not start the workflow run.
|
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
|
2. **Scene 9 assistant modal:** remove the lower chat dock, give the prepared
|
||||||
lifecycle canvas the available stage, and expose the synchronized authoring
|
lifecycle canvas the available stage, and expose the synchronized authoring
|
||||||
conversation through an assistant-ui modal anchored on the left.
|
conversation through an assistant-ui modal anchored on the left.
|
||||||
|
|||||||
+3
@@ -1,5 +1,8 @@
|
|||||||
# Scene 8 Chat Entry Implementation Plan
|
# 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.
|
> **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.
|
**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.
|
discussion index rather than a benchmark or generic conclusion.
|
||||||
|
|
||||||
Scenes 8 and 9 use the canonical prepared-authoring recording as their only
|
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
|
execution evidence. Scene 8 is a full-screen chat entry: its prefilled request
|
||||||
external agent handoff; Scene 9 breaks the prepared authoring into five phases
|
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
|
with the same conversation contracted into a synchronized bottom dock. Each
|
||||||
phase opens its matching prepared tool group beneath a factual source, graph,
|
phase opens its matching prepared tool group beneath a factual source, graph,
|
||||||
repair, artifact, or deployment view. Neither scene calls workflow authoring
|
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
|
from the committed `projectPreparedAuthoring()` recording and never call
|
||||||
workflow authoring RPC operations.
|
workflow authoring RPC operations.
|
||||||
|
|
||||||
- **Scene 8 (Agent Handoff)**: a full-screen prepared conversation that
|
- **Scene 8 (Agent Handoff)**: a full-screen deterministic chat entry that
|
||||||
establishes the external agent interface. The `request` beat shows the
|
pre-fills the report-authoring request. Send is local presentation state and
|
||||||
operator requesting a report workflow; the `handoff` beat reveals the full
|
reveals the first prepared Discover tool group; the `handoff` beat reveals
|
||||||
completed conversation with prepared `wf` tool groups across all authoring
|
the full completed conversation with prepared `wf` tool groups across all
|
||||||
phases.
|
authoring phases. This is not a live LLM chat or workflow run.
|
||||||
- **Scene 9 (Prepared Workflow Lifecycle)**: a five-phase lifecycle
|
- **Scene 9 (Prepared Workflow Lifecycle)**: a five-phase lifecycle
|
||||||
(discover, draft, validate, artifact, deployment) with a compact phase rail
|
(discover, draft, validate, artifact, deployment) with a compact phase rail
|
||||||
and one dominant factual product projection per beat. The Scene 8 thread
|
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.
|
current beat. There is no detached trace modal or second transcript.
|
||||||
|
|
||||||
The authoring scenes consume deterministic prepared data and never call
|
The authoring scenes consume deterministic prepared data and never call
|
||||||
workflow authoring RPCs — only `workflow.health` infrastructure pings are
|
workflow authoring RPCs. Scene 8 also skips live target probing so its request
|
||||||
permitted.
|
and Send path remain fully local; later execution scenes own live-run behavior.
|
||||||
|
|
||||||
### Demo Climax (Scenes 10–12)
|
### Demo Climax (Scenes 10–12)
|
||||||
|
|
||||||
|
|||||||
@@ -263,15 +263,17 @@ describe("PresentationRoute", () => {
|
|||||||
expect(screen.queryByText(/checking reachability/i)).not.toBeInTheDocument();
|
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.sessionStorage.setItem("lda.workflowConsole.target", "http://127.0.0.1:8765/rpc");
|
||||||
window.location.hash = "#scene/agent-handoff/request";
|
window.location.hash = "#scene/agent-handoff/request";
|
||||||
|
mockedCallOperation.mockClear();
|
||||||
const { PresentationRoute } = await import("./PresentationRoute.js");
|
const { PresentationRoute } = await import("./PresentationRoute.js");
|
||||||
render(<PresentationRoute />);
|
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.getByRole("button", { name: "Send" })).toBeEnabled();
|
||||||
expect(screen.queryByRole("button", { name: "Run prepared workflow" })).not.toBeInTheDocument();
|
expect(screen.queryByRole("button", { name: "Run prepared workflow" })).not.toBeInTheDocument();
|
||||||
|
expect(mockedCallOperation).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("opens Scene 10 approval from the canonical hash", async () => {
|
it("opens Scene 10 approval from the canonical hash", async () => {
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ export const PresentationRoute = () => {
|
|||||||
|
|
||||||
const presentationTarget = useMemo(() => resolvePresentationTarget(), []);
|
const presentationTarget = useMemo(() => resolvePresentationTarget(), []);
|
||||||
const demo = useDemoTimeline(presentationTarget.target, recordEvidence, recording);
|
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, {
|
const timelineAgent = useTimelineAgent(demo, {
|
||||||
mode: presentationTarget.mode === "live" ? "live" : "replay",
|
mode: presentationTarget.mode === "live" ? "live" : "replay",
|
||||||
status: targetStatus,
|
status: targetStatus,
|
||||||
|
|||||||
@@ -154,9 +154,14 @@ describe("projectPreparedAuthoringThread", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("keeps the canonical projection unchanged without a request override", () => {
|
it("keeps the canonical projection unchanged without a request override", () => {
|
||||||
expect(projectPreparedAuthoringThread("discover")).toEqual(
|
const firstUser = projectPreparedAuthoringThread("discover")
|
||||||
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", () => {
|
it("overrides only the first user request and preserves Discover tool data", () => {
|
||||||
|
|||||||
@@ -287,15 +287,15 @@ export const projectPreparedAuthoringThread = (
|
|||||||
|
|
||||||
let requestReplaced = false;
|
let requestReplaced = false;
|
||||||
return recording.slice(0, finalPhaseIndex + 1).flatMap((phase) => {
|
return recording.slice(0, finalPhaseIndex + 1).flatMap((phase) => {
|
||||||
const conversation = phase.conversation.map((turn, index) =>
|
const conversation = phase.conversation.map((turn, index) => {
|
||||||
agentTextMessage(
|
const shouldReplaceRequest = requestOverride !== undefined && !requestReplaced && turn.role === "user";
|
||||||
|
if (shouldReplaceRequest) requestReplaced = true;
|
||||||
|
return agentTextMessage(
|
||||||
`authoring-${phase.phase}-message-${index}`,
|
`authoring-${phase.phase}-message-${index}`,
|
||||||
turn.role,
|
turn.role,
|
||||||
requestOverride !== undefined && !requestReplaced && turn.role === "user"
|
shouldReplaceRequest ? requestOverride : turn.text,
|
||||||
? (requestReplaced = true, requestOverride)
|
|
||||||
: turn.text,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
});
|
||||||
const groupId = authoringToolGroupId(phase.phase);
|
const groupId = authoringToolGroupId(phase.phase);
|
||||||
const toolParts = phase.commands.flatMap((command, index) => {
|
const toolParts = phase.commands.flatMap((command, index) => {
|
||||||
const callId = `${groupId}-command-${index}`;
|
const callId = `${groupId}-command-${index}`;
|
||||||
|
|||||||
@@ -3030,7 +3030,7 @@
|
|||||||
padding: clamp(1.5rem, 4vw, 3.75rem) clamp(1rem, 5vw, 4.5rem);
|
padding: clamp(1.5rem, 4vw, 3.75rem) clamp(1rem, 5vw, 4.5rem);
|
||||||
border: 1px solid var(--authoring-rule, var(--stage-line));
|
border: 1px solid var(--authoring-rule, var(--stage-line));
|
||||||
border-radius: 0.35rem;
|
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);
|
box-shadow: 0 1.25rem 3rem color-mix(in oklch, var(--stage-ink) 10%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3096,7 +3096,7 @@
|
|||||||
resize: vertical;
|
resize: vertical;
|
||||||
border-color: var(--authoring-rule, var(--stage-line));
|
border-color: var(--authoring-rule, var(--stage-line));
|
||||||
border-radius: 0.2rem;
|
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));
|
color: var(--authoring-ink, var(--text-primary));
|
||||||
font: 1.05rem/1.45 var(--font-interface);
|
font: 1.05rem/1.45 var(--font-interface);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const liveActive = (state: DemoTimelineState): boolean =>
|
|||||||
export const usePresentationTargetStatus = (
|
export const usePresentationTargetStatus = (
|
||||||
targetState: PresentationTargetState,
|
targetState: PresentationTargetState,
|
||||||
demoState: DemoTimelineState,
|
demoState: DemoTimelineState,
|
||||||
|
probeEnabled = true,
|
||||||
): PresentationTargetHealth => {
|
): PresentationTargetHealth => {
|
||||||
const [probe, setProbe] = useState<TargetProbeState>(
|
const [probe, setProbe] = useState<TargetProbeState>(
|
||||||
targetState.mode === "live" ? "checking" : "none",
|
targetState.mode === "live" ? "checking" : "none",
|
||||||
@@ -27,6 +28,11 @@ export const usePresentationTargetStatus = (
|
|||||||
setFailureReason(targetState.reason);
|
setFailureReason(targetState.reason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!probeEnabled) {
|
||||||
|
setProbe("none");
|
||||||
|
setFailureReason("deterministic Scene 8 replay");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setProbe("checking");
|
setProbe("checking");
|
||||||
setFailureReason(undefined);
|
setFailureReason(undefined);
|
||||||
@@ -50,7 +56,17 @@ export const usePresentationTargetStatus = (
|
|||||||
return () => {
|
return () => {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
};
|
};
|
||||||
}, [targetState]);
|
}, [probeEnabled, targetState]);
|
||||||
|
|
||||||
|
if (!probeEnabled) {
|
||||||
|
return presentationTargetHealth({
|
||||||
|
target: null,
|
||||||
|
probe: "none",
|
||||||
|
liveActive: false,
|
||||||
|
replayActive: true,
|
||||||
|
failureReason: "deterministic Scene 8 replay",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return presentationTargetHealth({
|
return presentationTargetHealth({
|
||||||
target: targetState.mode === "live" ? targetState.target : null,
|
target: targetState.mode === "live" ? targetState.target : null,
|
||||||
|
|||||||
Reference in New Issue
Block a user