fix: close final Scene 8 review findings

This commit is contained in:
lda
2026-07-13 23:17:36 +07:00 Verified
parent ea2c88b7de
commit 1f79669cdd
17 changed files with 119 additions and 104 deletions
@@ -34,8 +34,8 @@ can be shown after selecting replay with the runbook's session-storage switch.
| `agent-handoff/request` | I will now show a prepared demonstration built on this platform. The chat is a presentation interface, not the autonomous planner evaluated by the thesis. The chat translates a report request into the same public lifecycle operations an external agent could call. This prepared path demonstrates product behavior and recorded evidence, not a fresh model-performance result. | Agent request surface | Workflow substrate framing | hidden | replay-only; Constrained demo agent and prepared replay recipe | `agent-handoff/request` |
| `prepared-lifecycle/discover` | It inspects sources, capabilities, and schemas rather than guessing at hidden interfaces. | Prepared lifecycle: discovery | Capability/schema evidence | hidden | replay-only; `examples/lda_report_workflow`; deployment inspect replay evidence | `prepared-lifecycle/discover` |
| `prepared-lifecycle/draft` | Focused operations modify mutable authoring state before execution. | Prepared lifecycle: draft | Workflow definition | hidden | replay-only; `examples/lda_report_workflow`; deployment inspect replay evidence | `prepared-lifecycle/draft` |
| `prepared-lifecycle/diagnose` | Structured diagnostics identify the missing output projection. | Diagnostic receipt | Draft authoring surface | hidden | replay-only; `examples/lda_report_workflow`; deployment inspect replay evidence | `prepared-lifecycle/diagnose` |
| `prepared-lifecycle/repair` | One focused output-map edit resolves it; hints do not guarantee automatic repair. | Repair guidance | Diagnostic receipt | hidden | replay-only; `examples/lda_report_workflow`; deployment inspect replay evidence | `prepared-lifecycle/repair` |
| `prepared-lifecycle/diagnose` | Revision 2 is valid; this prepared fault injection, not an accidental discovery, runs `wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok`, producing invalid revision 3 and `missing_outcome_edge`. | Diagnostic receipt | Draft authoring surface | hidden | replay-only; reviewed prepared authoring evidence | `prepared-lifecycle/diagnose` |
| `prepared-lifecycle/repair` | The existing `wf draft set-route lda_report_workflow --revision 3 --step analyze --outcome ok --to __end__` command repairs the route removal and produces valid revision 4. | Repair guidance | Diagnostic receipt | hidden | replay-only; reviewed prepared authoring evidence | `prepared-lifecycle/repair` |
| `prepared-lifecycle/artifact` | It saves the validated plan as immutable artifact lda_report_case_study version 1. | Prepared lifecycle: artifact | Lifecycle state | hidden | replay-only; `examples/lda_report_workflow`; deployment inspect replay evidence | `prepared-lifecycle/artifact` |
| `prepared-lifecycle/deployment` | Deployment binds and validates three local sources; execution starts in the next scene. | Prepared lifecycle: deployment | Binding/readiness evidence | hidden | replay-only; `examples/lda_report_workflow`; deployment inspect replay evidence | `prepared-lifecycle/deployment` |
| `run-from-deployment/input` | The deployment receives selected local documents and an issue-board path. | Workflow input panel | Prepared deployment | hidden | live-capable; `workflow.runs.start` replay evidence | `prepared-lifecycle/deployment` |
+2 -2
View File
@@ -55,7 +55,7 @@ end-to-end run.
### Scene 8 — Prepared Workflow Lifecycle
- Audience takeaway: The request becomes six concise authoring stages: Discover, Draft, Diagnose, Repair, Artifact, and Deployment.
- Visible proof: The phase rail, staged messages, structured diagnostic, focused output-map edit, and changing factual evidence advance across all six beats.
- Visible proof: Draft revision 2 is valid with `analyze.ok -> __end__`; the transcript explicitly labels a prepared fault injection, not an accidental discovery, using `wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok`, then shows invalid revision 3 with `missing_outcome_edge` and repairs it with the existing `wf draft set-route lda_report_workflow --revision 3 --step analyze --outcome ok --to __end__` command to valid revision 4.
- Missing or confusing: Deployment binds and validates three local sources but does not execute; that boundary needs an explicit spoken pause.
- Next action: keep
@@ -97,7 +97,7 @@ end-to-end run.
- Scene 5 -> 6 works if Deployment is the handoff: lifecycle vocabulary becomes the architecture that owns it.
- Scene 6 -> 7 works: architecture hands off to a bounded prepared request surface.
- Scene 7 -> 8 works and is not a duplicate: request/discovery becomes staged lifecycle evidence.
- Scene 8 -> 9 is the critical boundary: Deployment prepares; Scene 9 alone starts execution. Keep the explicit no-run wording.
- Scene 8 -> 9 is the critical boundary: the prepared route-removal fault injection is repaired before Deployment; Deployment prepares, and Scene 9 alone starts execution. Keep the explicit no-run wording.
- Scene 9 -> 10 -> 11 works as one climax in replay, but the revision branch has a factual run-identity defect and the live path is blocked.
- Scene 12 -> 13 works: evaluation limits become the contribution and future-work close.
+1
View File
@@ -14,6 +14,7 @@ export type PreparedAuthoringToolName =
| "workflow.draft_workspaces.create_from_capability"
| "workflow.draft_workspaces.add_step_from_capability"
| "workflow.draft_workspaces.get"
| "workflow.draft_workspaces.remove_route"
| "workflow.draft_workspaces.validate"
| "workflow.draft_workspaces.set_route"
| "workflow.draft_workspaces.compile"
@@ -121,6 +121,9 @@ describe("PresentationRoute", () => {
expect(within(result).getByText("missing_outcome_edge")).toBeInTheDocument();
expect(within(result).getByText("nodes[analyze]")).toBeInTheDocument();
expect(within(result).getByText(/missing edges for outcomes.*ok/i)).toBeInTheDocument();
expect(within(result).getByRole("note", { name: /prepared fault injection/i })).toHaveTextContent(
"wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok",
);
expect(screen.queryByText(/missing output projection/i)).not.toBeInTheDocument();
}, 15000);
@@ -139,6 +142,16 @@ describe("PresentationRoute", () => {
expect(within(result).getByText("0 diagnostics", { exact: true })).toBeInTheDocument();
}, 15000);
it("routes Diagnose to a bounded result scrollport on narrow canvases", async () => {
window.location.hash = "#scene/prepared-lifecycle/diagnose";
const { PresentationRoute } = await import("./PresentationRoute.js");
render(<PresentationRoute />);
const result = await screen.findByRole("region", { name: "draft validation diagnostic" });
expect(result).toHaveAttribute("data-scrollport", "bounded-result");
expect(result).toHaveAttribute("data-scroll-bound", "viewport-relative");
}, 15000);
it("exposes an application-owned readiness signal for rehearsal capture", async () => {
window.location.hash = "#scene/thesis/title";
const { PresentationRoute } = await import("./PresentationRoute.js");
@@ -31,7 +31,7 @@ describe("AuthoringConversation", () => {
const log = screen.getByRole("log", { name: "prepared authoring conversation" });
expect(log).toHaveAttribute("data-surface", "dock");
expect(screen.getByRole("button", { name: /validate.*2 tool calls/i }))
expect(screen.getByRole("button", { name: /validate.*3 tool calls/i }))
.toHaveAttribute("aria-expanded", "true");
expect(screen.getByRole("button", { name: /draft.*3 tool calls/i }))
.toHaveAttribute("aria-expanded", "false");
@@ -60,6 +60,9 @@ describe("AuthoringPhaseVisual", () => {
expect(within(result).getByText(/missing edges for outcomes.*ok/i)).toBeInTheDocument();
expect(within(result).getByText(/cannot prove where execution goes next/i)).toBeInTheDocument();
expect(within(result).getByText("Revision 3")).toBeInTheDocument();
expect(within(result).getByRole("note", { name: /prepared fault injection/i })).toHaveTextContent(
"wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok",
);
});
it("renders route repair as a valid revision with compact prior context", () => {
@@ -74,6 +74,8 @@ const ResultRoot = ({
className={`authoring-visual authoring-result authoring-result--${kind}`}
aria-label={label}
data-authoring-result={kind}
data-scrollport="bounded-result"
data-scroll-bound="viewport-relative"
data-presentation-surface="editorial"
data-visual-role="primary"
>
@@ -152,6 +154,18 @@ const DiagnosticResult = ({ evidence }: { readonly evidence: EvidenceOf<"diagnos
/>
<p className="authoring-result__explanation">{evidence.diagnostic.explanation}</p>
</div>
<aside
className="authoring-result__fault-injection"
role="note"
aria-label={evidence.faultInjection.label}
>
<span>{evidence.faultInjection.label}</span>
<code>{evidence.faultInjection.command}</code>
<p>
Revision {evidence.faultInjection.fromRevision} was valid; this prepared edit intentionally
produced invalid revision {evidence.faultInjection.toRevision} for diagnosis.
</p>
</aside>
</ResultRoot>
);
@@ -190,7 +190,7 @@ describe("PreparedAuthoringLifecycleScene", () => {
expect(screen.getByRole("complementary", { name: /prepared authoring assistant/i }))
.toHaveAttribute("data-phase", "diagnose");
expect(screen.getByRole("button", { name: /validate.*2 tool calls/i }))
expect(screen.getByRole("button", { name: /validate.*3 tool calls/i }))
.toHaveAttribute("aria-expanded", "true");
expect(screen.getByRole("button", { name: /draft.*3 tool calls/i }))
.toHaveAttribute("aria-expanded", "false");
@@ -58,7 +58,7 @@ describe("PresentationAssistantPane", () => {
expect(screen.getByRole("button", { name: /artifact.*3 tool calls/i }))
.toHaveAttribute("aria-expanded", "true");
expect(screen.getByRole("button", { name: /validate.*2 tool calls/i }))
expect(screen.getByRole("button", { name: /validate.*3 tool calls/i }))
.toHaveAttribute("aria-expanded", "false");
});
@@ -12,7 +12,6 @@ describe("projectPreparedAuthoringPhase", () => {
expect(phase.label).toBe("Discover");
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
expect(phase.summary).toMatch(/sources|capabilities|schema/i);
expect(phase.visual).toMatchObject({ kind: "inventory" });
});
it("projects the draft phase with graph and routes", () => {
@@ -20,7 +19,6 @@ describe("projectPreparedAuthoringPhase", () => {
expect(phase.label).toBe("Draft");
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
expect(phase.summary).toMatch(/graph|routes/i);
expect(phase.visual).toMatchObject({ kind: "graph" });
});
it("projects the validate phase with diagnosis and repair", () => {
@@ -28,7 +26,6 @@ describe("projectPreparedAuthoringPhase", () => {
expect(phase.label).toBe("Validate");
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
expect(phase.summary).toMatch(/diagnos|repair/i);
expect(phase.visual).toMatchObject({ kind: "repair" });
});
it("projects the artifact phase with immutable ID and version", () => {
@@ -37,7 +34,6 @@ describe("projectPreparedAuthoringPhase", () => {
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
expect(phase.summary).toMatch(/id/i);
expect(phase.summary).toMatch(/version/i);
expect(phase.visual).toMatchObject({ kind: "artifact" });
});
it("projects the deployment phase with bindings and validation", () => {
@@ -45,7 +41,6 @@ describe("projectPreparedAuthoringPhase", () => {
expect(phase.label).toBe("Deployment");
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
expect(phase.summary).toMatch(/bind|validat/i);
expect(phase.visual).toMatchObject({ kind: "bindings" });
});
it("keeps the validation diagnostic and repair command distinct", () => {
@@ -53,7 +48,14 @@ describe("projectPreparedAuthoringPhase", () => {
const diagnosticCmd = phase.commands.find(
(cmd) => cmd.result === "diagnostic" && cmd.detail?.includes("missing_outcome_edge"),
);
const faultInjectionCmd = phase.commands.find(
(cmd) => cmd.title === "workflow.draft_workspaces.remove_route",
);
const repairCmd = phase.commands.find((cmd) => cmd.command.includes("draft set-route"));
expect(faultInjectionCmd?.command).toBe(
"wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok",
);
expect(faultInjectionCmd?.detail).toMatch(/prepared fault injection/i);
expect(diagnosticCmd).toBeDefined();
expect(repairCmd).toBeDefined();
expect(diagnosticCmd).not.toBe(repairCmd);
@@ -19,7 +19,6 @@ export type AuthoringPhaseProjection = {
readonly summary: string;
readonly proof: readonly string[];
readonly commands: readonly PreparedAuthoringCommand[];
readonly visual: AuthoringPhaseVisualModel;
};
export type PreparedLifecycleStepProjection = AuthoringPhaseProjection & {
@@ -30,89 +29,6 @@ export type PreparedLifecycleStepProjection = AuthoringPhaseProjection & {
readonly evidence: ReviewedAuthoringEvidence;
};
export type AuthoringPhaseVisualModel =
| {
readonly kind: "inventory";
readonly sources: readonly string[];
readonly capability: string;
readonly contract: string;
}
| {
readonly kind: "graph";
readonly nodes: readonly string[];
readonly route: string;
readonly inputBinding: string;
}
| {
readonly kind: "repair";
readonly diagnostic: string;
readonly correction: string;
readonly status: string;
}
| {
readonly kind: "artifact";
readonly artifactId: string;
readonly version: number;
readonly requiredSources: number;
}
| {
readonly kind: "bindings";
readonly deploymentId: string;
readonly bindings: readonly { readonly requirement: string; readonly source: string }[];
readonly status: string;
};
const visualForPhase = (phase: AuthoringPhaseId): AuthoringPhaseVisualModel => {
switch (phase) {
case "discover":
return {
kind: "inventory",
sources: ["local.lda_docs", "local.lda_report", "local.issue_board"],
capability: "local.lda_report.analyze_documents",
contract: "documents → analysis",
};
case "draft":
return {
kind: "graph",
nodes: ["read_documents", "analyze"],
route: "ok → end",
inputBinding: "state.documents → documents",
};
case "validate":
{
const diagnostic = reviewedAuthoringEvidenceFor("diagnose");
const repair = reviewedAuthoringEvidenceFor("repair");
if (diagnostic.kind !== "diagnostic" || repair.kind !== "repair") {
throw new Error("reviewed validation evidence has an unexpected shape");
}
return {
kind: "repair",
diagnostic: `${diagnostic.diagnostic.code} at ${diagnostic.diagnostic.path}: ${diagnostic.diagnostic.message}`,
correction: repair.command,
status: `Revision ${repair.toRevision}: ${repair.status}`,
};
}
case "artifact":
return {
kind: "artifact",
artifactId: "lda_report_case_study",
version: 1,
requiredSources: 3,
};
case "deployment":
return {
kind: "bindings",
deploymentId: "lda_report_case_study.default",
bindings: [
{ requirement: "local.lda_docs", source: "local.lda_docs" },
{ requirement: "local.lda_report", source: "local.lda_report" },
{ requirement: "local.issue_board", source: "local.issue_board" },
],
status: "Deployment valid",
};
}
};
/**
* Projects one phase of the prepared authoring recording for presentation.
*
@@ -135,7 +51,6 @@ export const projectPreparedAuthoringPhase = (
.join(" ") || found.label,
proof: found.proof,
commands: found.commands,
visual: visualForPhase(found.phase),
};
};
@@ -154,7 +69,7 @@ export const projectPreparedLifecycleStep = (
const evidence = reviewedAuthoringEvidenceFor(step);
// Diagnose and repair are presentation choreography over one factual
// recording phase; they select distinct evidence without duplicating it.
const commandIndex = step === "repair" ? 1 : 0;
const commandIndex = step === "repair" ? 2 : step === "diagnose" ? 1 : 0;
const primaryCommand = phase.commands[commandIndex];
if (primaryCommand === undefined) {
throw new Error(
@@ -80,6 +80,7 @@ describe("projectPreparedAuthoring", () => {
"workflow.draft_workspaces.create_from_capability",
"workflow.draft_workspaces.add_step_from_capability",
"workflow.draft_workspaces.get",
"workflow.draft_workspaces.remove_route",
"workflow.draft_workspaces.validate",
"workflow.draft_workspaces.set_route",
"workflow.draft_workspaces.compile",
@@ -109,6 +110,7 @@ describe("projectPreparedAuthoring", () => {
expect(commands.some((command) => command === "wf cap inspect local.lda_report.analyze_documents")).toBe(true);
expect(commands.some((command) => command === "wf schema")).toBe(true);
expect(commands.some((command) => command.startsWith("wf draft add-step lda_report_workflow"))).toBe(true);
expect(commands.some((command) => command === "wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok")).toBe(true);
expect(commands.some((command) => command === "wf draft validate lda_report_workflow")).toBe(true);
expect(commands.some((command) => command === "wf draft set-route lda_report_workflow --revision 3 --step analyze --outcome ok --to __end__")).toBe(true);
expect(commands.some((command) => command === "wf draft compile lda_report_workflow")).toBe(true);
@@ -160,12 +160,22 @@ const recording: readonly PreparedAuthoringPhase[] = [
beatId: "validate",
label: "Validate",
commands: [
{
title: "workflow.draft_workspaces.remove_route",
command:
"wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok",
summary: "Prepare a validation fault injection by removing the terminal route",
result: "success",
detail:
"Prepared fault injection: intentionally remove analyze.ok from valid revision 2; this produces revision 3 invalid with missing_outcome_edge.",
},
{
title: "workflow.draft_workspaces.validate",
command: "wf draft validate lda_report_workflow",
summary: "Validate the workflow draft",
result: "diagnostic",
detail: "missing_outcome_edge at nodes[analyze]: reachable node is missing edges for outcomes ['ok']",
detail:
"Revision 3 is invalid: missing_outcome_edge at nodes[analyze]: reachable node is missing edges for outcomes ['ok']",
},
{
title: "workflow.draft_workspaces.set_route",
@@ -182,7 +192,7 @@ const recording: readonly PreparedAuthoringPhase[] = [
},
{
role: "assistant",
text: "Running diagnosis now. I'll bind the source and repair any issues found in the draft graph.",
text: "Revision 2 is valid. For this prepared validation path, I'll intentionally remove analyze.ok, validate the resulting revision 3, and then repair it.",
},
],
proof: [
@@ -34,6 +34,12 @@ describe("reviewed authoring evidence", () => {
path: "nodes[analyze]",
message: "reachable node is missing edges for outcomes ['ok']",
},
faultInjection: {
command: "wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok",
fromRevision: 2,
toRevision: 3,
label: "prepared fault injection",
},
});
expect(reviewedAuthoringEvidenceFor("repair")).toMatchObject({
@@ -33,6 +33,12 @@ export type ReviewedAuthoringEvidence =
readonly message: string;
readonly explanation: string;
};
readonly faultInjection: {
readonly command: string;
readonly fromRevision: 2;
readonly toRevision: 3;
readonly label: "prepared fault injection";
};
}
| {
readonly kind: "repair";
@@ -107,6 +113,13 @@ const reviewedAuthoringEvidence: Readonly<
message: "reachable node is missing edges for outcomes ['ok']",
explanation: "The workflow cannot prove where execution goes next.",
},
faultInjection: {
command:
"wf draft remove-route lda_report_workflow --revision 2 --step analyze --outcome ok",
fromRevision: 2,
toRevision: 3,
label: "prepared fault injection",
},
},
repair: {
kind: "repair",
@@ -183,6 +183,17 @@ describe("presentation.css", () => {
expect(narrowRows).toContain("grid-template-columns: minmax(0, 1fr);");
});
it("bounds narrow lifecycle results to a viewport-relative scrollport", () => {
const narrowContainer = cssBlock(css, "@container presentation-canvas (max-width: 600px)") ?? "";
const narrowResult = cssBlocks(narrowContainer, '.prepared-lifecycle-scene[data-presentation-surface="editorial"] .authoring-result')
.find((body) => body.includes("max-height: min(34rem, 56vh);"));
expect(narrowResult).toContain("height: min(34rem, 56vh);");
expect(narrowResult).toContain("max-height: min(34rem, 56vh);");
expect(narrowResult).toContain("overflow: auto;");
expect(narrowResult).not.toContain("max-height: 100%;");
});
it("gives the prepared lifecycle rail and operation frame the primary hierarchy", () => {
const frameRules = cssBlocks(css, '.prepared-lifecycle-scene[data-presentation-surface="editorial"] .prepared-lifecycle-scene__frame');
const editorialFrame = frameRules.find((body) => body.includes("background: var(--authoring-paper);"));
@@ -263,9 +274,10 @@ describe("presentation.css", () => {
expect(narrowAssistant).toContain("max-height: min(24rem, 60vh);");
});
it("does not cap lifecycle evidence on wide presentation canvases", () => {
it("does not add a wide-canvas lifecycle evidence cap", () => {
expect(css).not.toContain("@container presentation-canvas (min-width: 1500px)");
expect(css).not.toContain("max-height: min(34rem, 56vh);");
const narrowContainer = cssBlock(css, "@container presentation-canvas (max-width: 600px)") ?? "";
expect(narrowContainer).toContain("max-height: min(34rem, 56vh);");
});
it("bounds prepared conversation scrolling and recenters the agent handoff at compact stage widths", () => {
@@ -4007,8 +4007,8 @@
}
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .authoring-result {
height: auto;
max-height: 100%;
height: min(34rem, 56vh);
max-height: min(34rem, 56vh);
overflow: auto;
padding-inline: 0;
}
@@ -4229,6 +4229,30 @@
border-inline-start: 3px solid var(--accent-amber);
}
.authoring-result__fault-injection {
display: grid;
gap: 0.35rem;
min-width: 0;
padding: 0.75rem 0.9rem;
border: 1px dashed var(--authoring-rule, var(--stage-line));
color: var(--authoring-muted, var(--text-secondary));
}
.authoring-result__fault-injection span {
font: 700 0.64rem/1.1 var(--font-evidence);
letter-spacing: 0.07em;
text-transform: uppercase;
}
.authoring-result__fault-injection code {
overflow-wrap: anywhere;
}
.authoring-result__fault-injection p {
margin: 0;
line-height: 1.4;
}
.authoring-result__prior {
padding-bottom: 0.85rem;
border-bottom: 1px solid var(--authoring-rule, var(--stage-line));