feat: add prepared authoring evidence
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { projectPreparedAuthoring } from "./authoring-recording.js";
|
||||
import { projectPreparedAuthoringPhase } from "./authoring-projection.js";
|
||||
|
||||
describe("projectPreparedAuthoringPhase", () => {
|
||||
it("projects the discover phase with sources, capabilities, schema", () => {
|
||||
const phase = projectPreparedAuthoringPhase("discover");
|
||||
expect(phase.label).toBe("Discover");
|
||||
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
|
||||
expect(phase.summary).toMatch(/sources|capabilities|schema/i);
|
||||
});
|
||||
|
||||
it("projects the draft phase with graph and routes", () => {
|
||||
const phase = projectPreparedAuthoringPhase("draft");
|
||||
expect(phase.label).toBe("Draft");
|
||||
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
|
||||
expect(phase.summary).toMatch(/graph|routes/i);
|
||||
});
|
||||
|
||||
it("projects the validate phase with diagnosis and repair", () => {
|
||||
const phase = projectPreparedAuthoringPhase("validate");
|
||||
expect(phase.label).toBe("Validate");
|
||||
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
|
||||
expect(phase.summary).toMatch(/diagnos|repair/i);
|
||||
});
|
||||
|
||||
it("projects the artifact phase with immutable ID and version", () => {
|
||||
const phase = projectPreparedAuthoringPhase("artifact");
|
||||
expect(phase.label).toBe("Artifact");
|
||||
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
|
||||
expect(phase.summary).toMatch(/id|version/i);
|
||||
});
|
||||
|
||||
it("projects the deployment phase with bindings and validation", () => {
|
||||
const phase = projectPreparedAuthoringPhase("deployment");
|
||||
expect(phase.label).toBe("Deployment");
|
||||
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
|
||||
expect(phase.summary).toMatch(/bind|validat/i);
|
||||
});
|
||||
|
||||
it("validates phase diagnostic status is 'repaired'", () => {
|
||||
const phase = projectPreparedAuthoringPhase("validate");
|
||||
const diagnosticCmd = phase.commands.find(
|
||||
(cmd) => cmd.result === "diagnostic" && cmd.detail?.includes("repaired"),
|
||||
);
|
||||
expect(diagnosticCmd).toBeDefined();
|
||||
expect(diagnosticCmd!.detail).toContain("repaired");
|
||||
});
|
||||
|
||||
it("uses real public command syntax from the recording", () => {
|
||||
const recording = projectPreparedAuthoring();
|
||||
const allCommands = recording.flatMap((p) => p.commands);
|
||||
for (const cmd of allCommands) {
|
||||
expect(typeof cmd.command).toBe("string");
|
||||
expect(typeof cmd.summary).toBe("string");
|
||||
expect(["success", "diagnostic"]).toContain(cmd.result);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { projectPreparedAuthoring, type AuthoringPhaseId, type PreparedAuthoringCommand } from "./authoring-recording.js";
|
||||
|
||||
export type AuthoringPhaseProjection = {
|
||||
readonly phase: AuthoringPhaseId;
|
||||
readonly beatId: string;
|
||||
readonly label: string;
|
||||
readonly summary: string;
|
||||
readonly commands: readonly PreparedAuthoringCommand[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Projects one phase of the prepared authoring recording for presentation.
|
||||
*
|
||||
* The validate phase includes a diagnostic command whose detail confirms
|
||||
* the repair status.
|
||||
*/
|
||||
export const projectPreparedAuthoringPhase = (
|
||||
phase: AuthoringPhaseId,
|
||||
): AuthoringPhaseProjection => {
|
||||
const phases = projectPreparedAuthoring();
|
||||
const found = phases.find((p) => p.phase === phase);
|
||||
if (!found) throw new Error(`unknown phase: ${phase}`);
|
||||
return {
|
||||
phase: found.phase,
|
||||
beatId: found.beatId,
|
||||
label: found.label,
|
||||
summary: found.conversation
|
||||
.filter((t) => t.role === "assistant")
|
||||
.map((t) => t.text)
|
||||
.join(" ") || found.label,
|
||||
commands: found.commands,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,82 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
authoringPhaseForBeat,
|
||||
projectPreparedAuthoring,
|
||||
type AuthoringPhaseId,
|
||||
} from "./authoring-recording.js";
|
||||
|
||||
describe("authoringPhaseForBeat", () => {
|
||||
it("returns all five phases in order", () => {
|
||||
const phases: readonly AuthoringPhaseId[] = [
|
||||
"discover",
|
||||
"draft",
|
||||
"validate",
|
||||
"artifact",
|
||||
"deployment",
|
||||
];
|
||||
for (const phase of phases) {
|
||||
expect(authoringPhaseForBeat(phase)).toBe(phase);
|
||||
}
|
||||
});
|
||||
|
||||
it("maps beat IDs to expected phases", () => {
|
||||
expect(authoringPhaseForBeat("discover")).toBe("discover");
|
||||
expect(authoringPhaseForBeat("draft")).toBe("draft");
|
||||
expect(authoringPhaseForBeat("validate")).toBe("validate");
|
||||
expect(authoringPhaseForBeat("artifact")).toBe("artifact");
|
||||
expect(authoringPhaseForBeat("deployment")).toBe("deployment");
|
||||
});
|
||||
|
||||
it("throws for unknown beat IDs", () => {
|
||||
expect(() => authoringPhaseForBeat("unknown" as AuthoringPhaseId)).toThrow("unknown phase");
|
||||
});
|
||||
});
|
||||
|
||||
describe("projectPreparedAuthoring", () => {
|
||||
it("returns all five phases in order", () => {
|
||||
const phases = projectPreparedAuthoring();
|
||||
expect(phases.map((p) => p.phase)).toEqual([
|
||||
"discover",
|
||||
"draft",
|
||||
"validate",
|
||||
"artifact",
|
||||
"deployment",
|
||||
]);
|
||||
});
|
||||
|
||||
it("includes at least one user turn in the recording", () => {
|
||||
const phases = projectPreparedAuthoring();
|
||||
const allMessages = phases.flatMap((p) => p.conversation);
|
||||
const userTurns = allMessages.filter((m) => m.role === "user");
|
||||
expect(userTurns.length).toBeGreaterThanOrEqual(1);
|
||||
});
|
||||
|
||||
it("includes at least two assistant turns total", () => {
|
||||
const phases = projectPreparedAuthoring();
|
||||
const allMessages = phases.flatMap((p) => p.conversation);
|
||||
const assistantTurns = allMessages.filter((m) => m.role === "assistant");
|
||||
expect(assistantTurns.length).toBeGreaterThanOrEqual(2);
|
||||
});
|
||||
|
||||
it("has at least two commands per phase", () => {
|
||||
const phases = projectPreparedAuthoring();
|
||||
for (const phase of phases) {
|
||||
expect(phase.commands.length).toBeGreaterThanOrEqual(2);
|
||||
}
|
||||
});
|
||||
|
||||
it("starts every command with wf or uv run wf", () => {
|
||||
const phases = projectPreparedAuthoring();
|
||||
for (const phase of phases) {
|
||||
for (const cmd of phase.commands) {
|
||||
expect(cmd.command.startsWith("wf") || cmd.command.startsWith("uv run wf")).toBe(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("has unique beat IDs for each phase", () => {
|
||||
const phases = projectPreparedAuthoring();
|
||||
const ids = phases.map((p) => p.beatId);
|
||||
expect(new Set(ids).size).toBe(ids.length);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* Prepared authoring recording — presentation evidence, not a model trace.
|
||||
*
|
||||
* This file owns the canonical recording of the prepared workflow authoring
|
||||
* demonstration. Every command uses real public `wf` CLI syntax verified
|
||||
* against the project's own CLI documentation. Results are bounded
|
||||
* presentation evidence, not live RPC responses.
|
||||
*/
|
||||
|
||||
export type AuthoringPhaseId =
|
||||
| "discover"
|
||||
| "draft"
|
||||
| "validate"
|
||||
| "artifact"
|
||||
| "deployment";
|
||||
|
||||
export type CommandResult = "success" | "diagnostic";
|
||||
|
||||
export type PreparedAuthoringCommand = {
|
||||
readonly command: string;
|
||||
readonly summary: string;
|
||||
readonly result: CommandResult;
|
||||
readonly detail?: string | undefined;
|
||||
};
|
||||
|
||||
export type AuthoringConversationTurn = {
|
||||
readonly role: "user" | "assistant";
|
||||
readonly text: string;
|
||||
};
|
||||
|
||||
export type PreparedAuthoringPhase = {
|
||||
readonly phase: AuthoringPhaseId;
|
||||
readonly beatId: string;
|
||||
readonly label: string;
|
||||
readonly commands: readonly PreparedAuthoringCommand[];
|
||||
readonly conversation: readonly AuthoringConversationTurn[];
|
||||
};
|
||||
|
||||
const unknownPhase = (phase: never): never => {
|
||||
throw new Error(`unknown phase: ${phase}`);
|
||||
};
|
||||
|
||||
/** Maps a scene 9 beat ID to the corresponding authoring phase. */
|
||||
export const authoringPhaseForBeat = (beatId: AuthoringPhaseId): AuthoringPhaseId => {
|
||||
switch (beatId) {
|
||||
case "discover":
|
||||
case "draft":
|
||||
case "validate":
|
||||
case "artifact":
|
||||
case "deployment":
|
||||
return beatId;
|
||||
default:
|
||||
return unknownPhase(beatId);
|
||||
}
|
||||
};
|
||||
|
||||
const recording: readonly PreparedAuthoringPhase[] = [
|
||||
{
|
||||
phase: "discover",
|
||||
beatId: "discover",
|
||||
label: "Discover",
|
||||
commands: [
|
||||
{
|
||||
command: "wf source list",
|
||||
summary: "List available capability sources",
|
||||
result: "success",
|
||||
detail: "2 sources: local (file:///.providers), docs (file:///docs)",
|
||||
},
|
||||
{
|
||||
command: "wf cap inspect",
|
||||
summary: "Inspect declared capabilities",
|
||||
result: "success",
|
||||
detail: "6 capabilities: read_source, create_draft, add_step, bind_source, validate_graph, compile_artifact",
|
||||
},
|
||||
{
|
||||
command: "wf schema list",
|
||||
summary: "List registered workflow schemas",
|
||||
result: "success",
|
||||
detail: "3 schemas: [email protected], [email protected], [email protected]",
|
||||
},
|
||||
],
|
||||
conversation: [
|
||||
{
|
||||
role: "user",
|
||||
text: "We need to author a report workflow for the lda_report scenario. What sources and capabilities are available?",
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
text: "Let me inspect the available sources, capabilities, and schemas to understand what we can work with.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
phase: "draft",
|
||||
beatId: "draft",
|
||||
label: "Draft",
|
||||
commands: [
|
||||
{
|
||||
command: "wf draft create lda_report_workflow",
|
||||
summary: "Create a new workflow draft",
|
||||
result: "success",
|
||||
detail: "Draft 'lda_report_workflow' created with ID draft_a1b2c3",
|
||||
},
|
||||
{
|
||||
command: "wf add-step --id report --action generate_report --source lda_docs",
|
||||
summary: "Add a report generation step",
|
||||
result: "success",
|
||||
},
|
||||
{
|
||||
command: "wf route list",
|
||||
summary: "List routes in the draft graph",
|
||||
result: "success",
|
||||
detail: "2 routes: start->report, report->end",
|
||||
},
|
||||
],
|
||||
conversation: [
|
||||
{
|
||||
role: "assistant",
|
||||
text: "I found the available capabilities. Now I'll create a workflow draft with the report generation step and configure its routes.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
phase: "validate",
|
||||
beatId: "validate",
|
||||
label: "Validate",
|
||||
commands: [
|
||||
{
|
||||
command: "wf bind --source lda_docs --capability read_source",
|
||||
summary: "Bind source to capability",
|
||||
result: "success",
|
||||
detail: "Binding established: lda_docs->read_source",
|
||||
},
|
||||
{
|
||||
command: "wf validate draft_a1b2c3",
|
||||
summary: "Validate the workflow draft",
|
||||
result: "diagnostic",
|
||||
detail: "Diagnostic: Unbound step 'report' — missing output destination. Repair applied: connected report output to end. Status: repaired.",
|
||||
},
|
||||
],
|
||||
conversation: [
|
||||
{
|
||||
role: "user",
|
||||
text: "Is the draft valid? Can you check and fix any issues?",
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
text: "Running diagnosis now. I'll bind the source and repair any issues found in the draft graph.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
phase: "artifact",
|
||||
beatId: "artifact",
|
||||
label: "Artifact",
|
||||
commands: [
|
||||
{
|
||||
command: "wf compile draft_a1b2c3",
|
||||
summary: "Compile draft into an immutable artifact",
|
||||
result: "success",
|
||||
detail: "Compiled artifact art_x9y8z7 (version 1). 3 nodes, 2 edges. Schema: [email protected]",
|
||||
},
|
||||
{
|
||||
command: "wf artifact inspect art_x9y8z7",
|
||||
summary: "Inspect the compiled artifact",
|
||||
result: "success",
|
||||
detail: "Artifact art_x9y8z7 v1 — immutable. Created: 2026-07-11. Nodes: 3. Routes: 2.",
|
||||
},
|
||||
],
|
||||
conversation: [
|
||||
{
|
||||
role: "assistant",
|
||||
text: "The draft is valid and repaired. Let me compile it into an immutable artifact and inspect the result.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
phase: "deployment",
|
||||
beatId: "deployment",
|
||||
label: "Deployment",
|
||||
commands: [
|
||||
{
|
||||
command: "wf deployment save --artifact art_x9y8z7 --bind lda_docs:local.lda_docs",
|
||||
summary: "Save deployment with source bindings",
|
||||
result: "success",
|
||||
detail: "Deployment dep_m4n5p6 saved. Binding: lda_docs -> local.lda_docs",
|
||||
},
|
||||
{
|
||||
command: "wf deployment validate dep_m4n5p6",
|
||||
summary: "Validate deployment bindings",
|
||||
result: "success",
|
||||
detail: "Deployment dep_m4n5p6 valid — all 1 bindings resolved. Ready for run.",
|
||||
},
|
||||
],
|
||||
conversation: [
|
||||
{
|
||||
role: "user",
|
||||
text: "Now save everything as a deployment and make sure the bindings are valid.",
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
text: "Saving the deployment with the source bindings and validating that everything is correctly configured.",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/** Returns the full prepared authoring recording. */
|
||||
export const projectPreparedAuthoring = (): readonly PreparedAuthoringPhase[] => recording;
|
||||
Reference in New Issue
Block a user