Keep creation as a living DAG and archive playable products separately.

Opening accept no longer locks the graph; session.json stays creation-only while play starts from an instance snapshot. Sidebar products nest run saves, and play reading fills the feed at a denser type size.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-01 00:52:05 +08:00
co-authored by Cursor
parent bd5d88abfa
commit f37388761b
22 changed files with 930 additions and 303 deletions
+39
View File
@@ -293,4 +293,43 @@ describe("phase runtime", () => {
flow?.steps.find((s) => s.name === "开场白与开场变量")?.depends_on,
).toEqual(["美学纲领与交互范式"]);
});
it("prepareEnterPlay seals when closer is already accepted", () => {
const session = createSession("default");
const blackboard = new Blackboard();
blackboard.write({
tag: "设计.创作流程",
content: JSON.stringify({
status: "open",
steps: [
{
id: "开场白与开场变量",
name: "开场白与开场变量",
depends_on: [],
},
],
}),
source: "runtime",
});
const runtime = new PhaseRuntime({
initialSession: {
...session,
slots: {
...session.slots,
creationAcceptedUnits: ["开场白与开场变量"],
},
},
initialBlackboardItems: blackboard.exportItems(),
});
runtime.prepareEnterPlay();
expect(runtime.getSession().slots.creationSealedByOpening).toBe(true);
expect(runtime.getSession().slots.designInstanceReady).toBe(true);
expect(
runtime.getBlackboard().getContentByTag("设计.worker集")?.trim(),
).toBeTruthy();
const flow = parseCreationFlow(
runtime.getBlackboard().getContentByTag("设计.创作流程"),
);
expect(flow?.status).not.toBe("closed");
});
});