From e7a1d4bbc99a91331395667cd177a16171ad75b1 Mon Sep 17 00:00:00 2001 From: Zhao73 <156770117+Zhao73@users.noreply.github.com> Date: Tue, 2 Jun 2026 00:51:20 +0800 Subject: [PATCH 1/2] Improve first-run onboarding with demo seed Add an idempotent demo data seed path so new users can open the local studio with a project, reference sample, style card, and queued planning job already visible. Document the flow in both READMEs and cover it with a focused Vitest case. Constraint: Keep the change dependency-free and compatible with the existing local SQLite store. Rejected: Hard-code demo fixtures in the UI | would make the real empty local state less honest. Confidence: high Scope-risk: narrow Tested: XIAOSHUO_HOME=/var/folders/5h/_fph5b9d3wzfbcfxj31pxt0w0000gn/T/tmp.Z7jziSNV7N node node_modules/tsx/dist/cli.mjs scripts/seed-demo.ts Tested: node node_modules/vitest/vitest.mjs run tests/ts/demo-seed.test.ts Tested: pytest tests/python -q Not-tested: Full npm test, npm run lint, npm run build blocked by incomplete local npm install leaving Next package files missing. --- README.en.md | 21 ++++++++++ README.md | 10 +++++ package.json | 1 + scripts/seed-demo.ts | 9 +++++ src/lib/server/demo-seed.ts | 78 +++++++++++++++++++++++++++++++++++++ tests/ts/demo-seed.test.ts | 48 +++++++++++++++++++++++ 6 files changed, 167 insertions(+) create mode 100644 scripts/seed-demo.ts create mode 100644 src/lib/server/demo-seed.ts create mode 100644 tests/ts/demo-seed.test.ts diff --git a/README.en.md b/README.en.md index 9ca60e0..aaa3a06 100644 --- a/README.en.md +++ b/README.en.md @@ -65,6 +65,7 @@ flowchart TD | Goal | Command | | --- | --- | | Run locally | `npm install && npm run dev` | +| Seed a playable demo | `npm run demo:seed && npm run dev` | | Verify locally | `npm run lint && npm test && npm run build && pytest tests/python -q` | | Export one remembered entry skill for Codex | `npm run skills:export -- --target codex --mode aggregator-only` | | Export full bundle for Codex | `npm run skills:export -- --target codex --mode full-bundle` | @@ -78,6 +79,26 @@ Defaults: - Codex installs to `~/.codex/skills` unless `CODEX_HOME` is set - Claude installs to `~/.claude/skills` unless `CLAUDE_HOME` is set +## Quick Start + +```bash +npm install +npm run dev +``` + +Open `http://localhost:3000`, or the local port printed by Next.js. + +To see the studio with useful first-run content: + +```bash +npm run demo:seed +npm run dev +``` + +The seed command creates one idempotent local demo project, reference sample, +style card, and queued planning job. Running it again will not duplicate the +same demo. + ## Top-level Skill If you only want to remember one skill name, use: diff --git a/README.md b/README.md index b3c8030..c675b10 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ flowchart TD | 目标 | 命令 | | --- | --- | | 本地开发运行 | `npm install && npm run dev` | +| 预置一个可试玩 demo | `npm run demo:seed && npm run dev` | | 本地完整验证 | `npm run lint && npm test && npm run build && pytest tests/python -q` | | 为 Codex 导出一个总入口 skill | `npm run skills:export -- --target codex --mode aggregator-only` | | 为 Codex 导出完整 skill bundle | `npm run skills:export -- --target codex --mode full-bundle` | @@ -96,6 +97,15 @@ npm run dev 打开 `http://localhost:3000`,或者 Next.js 启动时显示的本地端口。 +想先看一个有内容的仪表盘,可以运行: + +```bash +npm run demo:seed +npm run dev +``` + +这个命令会创建一个幂等的本地示例项目、参考素材、风格卡和排队任务。重复运行不会重复插入同一个 demo。 + 推荐第一轮使用顺序: 1. 打开 `/wizard/new-novel` diff --git a/package.json b/package.json index 2838fc6..042d591 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "build": "next build", "start": "next start", "lint": "eslint", + "demo:seed": "tsx scripts/seed-demo.ts", "skills:export": "tsx scripts/export-skills.ts", "skills:install": "tsx scripts/install-skills.ts", "test": "vitest run", diff --git a/scripts/seed-demo.ts b/scripts/seed-demo.ts new file mode 100644 index 0000000..e94b6fb --- /dev/null +++ b/scripts/seed-demo.ts @@ -0,0 +1,9 @@ +import { seedDemoData } from "../src/lib/server/demo-seed"; + +function main() { + const result = seedDemoData(); + + console.log(JSON.stringify(result, null, 2)); +} + +main(); diff --git a/src/lib/server/demo-seed.ts b/src/lib/server/demo-seed.ts new file mode 100644 index 0000000..8c60f29 --- /dev/null +++ b/src/lib/server/demo-seed.ts @@ -0,0 +1,78 @@ +import { + createDraftJob, + createProject, + createReferenceWork, + createStyleProfile, + listProjects, +} from "./db"; + +const DEMO_PROJECT_TITLE = "雾港债火"; + +type ProjectRow = { + id: number; + title: string; +}; + +export function seedDemoData() { + const existingProject = (listProjects() as ProjectRow[]).find( + (project) => project.title === DEMO_PROJECT_TITLE, + ); + + if (existingProject) { + return { + created: false, + message: "Demo data already exists.", + projectId: existingProject.id, + title: existingProject.title, + }; + } + + const project = createProject({ + genre: "都市奇幻 / 悬疑", + premise: + "负债的夜班修表师在雾港听见旧钟里的亡者留言,被迫用七天查清一场债火案。", + title: DEMO_PROJECT_TITLE, + }); + + const reference = createReferenceWork({ + creatorLabel: "demo sample", + projectId: project.id, + sourceLabel: "demo://fog-harbor-opening", + sourceType: "excerpt", + title: "雾港开场节奏样本", + }); + + const styleProfile = createStyleProfile({ + antiPatterns: ["解释动机过早", "段尾连续抽象总结", "对白缺少动作承接"], + metrics: { + averageSentenceLength: 15.8, + dialogueRatio: 0.31, + hookDensity: 0.42, + }, + name: "雾港悬压推进卡", + referenceWorkId: reference.id, + summary: + "短场景切换、物件线索推进、对白后接动作反应,章末保留一个可验证谜面。", + }); + + const job = createDraftJob({ + jobType: "plan", + payload: { + chapter: 1, + focus: "建立债火案、旧钟留言和主角七天倒计时。", + styleProfileId: styleProfile.id, + }, + projectId: project.id, + status: "queued", + }); + + return { + created: true, + jobId: job.id, + message: "Demo data created.", + projectId: project.id, + referenceId: reference.id, + styleProfileId: styleProfile.id, + title: project.title, + }; +} diff --git a/tests/ts/demo-seed.test.ts b/tests/ts/demo-seed.test.ts new file mode 100644 index 0000000..2eb2914 --- /dev/null +++ b/tests/ts/demo-seed.test.ts @@ -0,0 +1,48 @@ +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +async function loadDemoModules() { + vi.resetModules(); + return { + dashboard: await import("@/lib/server/dashboard"), + db: await import("@/lib/server/db"), + demoSeed: await import("@/lib/server/demo-seed"), + }; +} + +describe("demo seed data", () => { + afterEach(async () => { + const { db } = await loadDemoModules(); + db.resetDatabaseForTests(); + delete process.env.XIAOSHUO_HOME; + }); + + test("creates an idempotent first-run project, style card, and queued job", async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), "xiaoshuo-demo-seed-")); + process.env.XIAOSHUO_HOME = home; + + const { dashboard, demoSeed } = await loadDemoModules(); + + const first = demoSeed.seedDemoData(); + const second = demoSeed.seedDemoData(); + const snapshot = dashboard.getDashboardSnapshot(); + + expect(first).toMatchObject({ + created: true, + title: "雾港债火", + }); + expect(second).toMatchObject({ + created: false, + projectId: first.projectId, + }); + expect(snapshot.metrics).toMatchObject({ + projects: 1, + queuedJobs: 1, + references: 1, + styleProfiles: 1, + }); + expect(snapshot.projects[0]?.title).toBe("雾港债火"); + expect(snapshot.styleProfiles[0]?.name).toBe("雾港悬压推进卡"); + }); +}); From f6681156e7882de60196d760a04dadbc81a40455 Mon Sep 17 00:00:00 2001 From: Zhao73 <156770117+Zhao73@users.noreply.github.com> Date: Tue, 2 Jun 2026 00:53:09 +0800 Subject: [PATCH 2/2] Keep CI Python checks executable Install pytest in the GitHub Actions job before running the Python analyzer tests. The workflow already declared Python 3.11 but did not install the test runner, so clean CI failed before exercising the tests. Constraint: Preserve the existing npm and Python verification sequence. Confidence: high Scope-risk: narrow Tested: gh run view 26769020498 --repo Zhao73/xiaoshuo-studio --log-failed Not-tested: Fresh GitHub Actions rerun pending after push. --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 833f679..9945262 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,9 @@ jobs: with: python-version: "3.11" + - name: Install Python test dependencies + run: python -m pip install pytest + - name: Install dependencies run: npm ci