| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- import { test } from 'node:test'
- import assert from 'node:assert/strict'
- import path from 'node:path'
- import { promises as fs } from 'node:fs'
- import { determineNextState } from '../../src/state-machine/index.js'
- import { stageChapter, rejectFrom } from '../../src/staging/index.js'
- import { gitBookCtx } from '../commands/_helper.js'
- // 开关矩阵(PRD #14):自动确认细纲 × 连写。全关=既有回归(router.test.js 全量);
- // 本文件测:单开细纲自动确认的序 6 标志、批次进行中的序 3 明细。全开端到端见 finalize-batch.test.js AC1。
- async function reachOutline(ctx) {
- // sample-book 工作区自带细纲 → 会命中序 3,清掉以到达序 6
- await fs.rm(path.join(ctx.repoPath, '工作区', '细纲.md'), { force: true })
- }
- async function setBookYaml(ctx, key, value) {
- const p = path.join(ctx.repoPath, 'book.yaml')
- const src = await fs.readFile(p, 'utf8')
- const line = `${key}: ${value}`
- const re = new RegExp(`^${key}:.*$`, 'm')
- await fs.writeFile(p, re.test(src) ? src.replace(re, line) : `${src}${line}\n`, 'utf8')
- }
- async function stage3(ctx) {
- await fs.mkdir(path.join(ctx.repoPath, '工作区'), { recursive: true })
- await fs.writeFile(
- path.join(ctx.repoPath, '工作区', '审稿.md'),
- '# 第 3 章审稿单\n\n> 完整两审模式。\n> 共 0 个问题:0 阻断。\n',
- 'utf8'
- )
- const r = await stageChapter(ctx, {
- chapterNum: 3,
- payload: {
- frontMatter: {
- 章号: 3,
- 标题: '连写3',
- 卷: 1,
- 书内时间: '夏月初三',
- 字数: 100,
- 章定位: '推进',
- 钩子: '危机钩-强',
- 情绪定位: '铺垫',
- 伏笔: ['推进 伏笔-001'],
- },
- body: '第3章正文。',
- workspaceFiles: [],
- },
- })
- assert.equal(r.ok, true, r.error)
- }
- test('开关矩阵:全关 → 序 6 dto.自动确认细纲=false,行为与既有一致', async () => {
- const { ctx, cleanup } = await gitBookCtx()
- try {
- await reachOutline(ctx)
- const r = await determineNextState(ctx)
- assert.equal(r.序, 6, JSON.stringify(r))
- assert.equal(r.dto.自动确认细纲, false)
- assert.match(r.dto.期望产物, /作者确认/)
- } finally {
- await cleanup()
- }
- })
- test('开关矩阵:自动确认细纲开 → 序 6 dto 标志与提案直接生效指引', async () => {
- const { ctx, cleanup } = await gitBookCtx()
- try {
- await reachOutline(ctx)
- await setBookYaml(ctx, '自动确认细纲', 'true')
- const r = await determineNextState(ctx)
- assert.equal(r.序, 6, JSON.stringify(r))
- assert.equal(r.dto.自动确认细纲, true)
- assert.match(r.dto.期望产物, /不再问作者/)
- } finally {
- await cleanup()
- }
- })
- test('批次进行中:序 3 dto.批次 带章清单与「继续下一章」建议;打回后建议重写', async () => {
- const { ctx, cleanup } = await gitBookCtx()
- try {
- await reachOutline(ctx)
- await stage3(ctx)
- const r = await determineNextState(ctx)
- assert.equal(r.序, 3, JSON.stringify(r))
- assert.equal(r.state, 'resume')
- assert.equal(r.dto.从哪继续, '待定稿批次续跑')
- assert.equal(r.dto.批次.章数, 1)
- assert.deepEqual(r.dto.批次.章, [{ 章号: 3, 标题: '连写3', 状态: '待审收' }])
- assert.match(r.dto.批次.建议, /继续批内下一章(第 4 章)/)
- const rej = await rejectFrom(ctx.repoPath, 3)
- assert.equal(rej.ok, true, rej.error)
- const r2 = await determineNextState(ctx)
- assert.equal(r2.序, 3)
- assert.match(r2.dto.批次.建议, /重写打回章(第 3 章)/)
- } finally {
- await cleanup()
- }
- })
- test('批次进行中:停止命中(写满)→ 序 3 建议批量过稿', async () => {
- const { ctx, cleanup } = await gitBookCtx()
- try {
- await reachOutline(ctx)
- await setBookYaml(ctx, '连写批次大小', '1')
- await stage3(ctx)
- const r = await determineNextState(ctx)
- assert.equal(r.序, 3, JSON.stringify(r))
- assert.equal(r.dto.批次.停止.stop, true)
- assert.match(r.dto.批次.建议, /批量过稿/)
- } finally {
- await cleanup()
- }
- })
|