derive-table.spec.ts 4.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { describe, expect, it } from 'vitest'
  2. import type { ChapterFacts } from '../src/derive/scan'
  3. import { deriveChapterFacts } from '../src/derive/derive'
  4. function facts(over: Partial<ChapterFacts> = {}): ChapterFacts {
  5. return {
  6. key: { 卷: 1, 章: 1, 章名: '初见' },
  7. 窗口就绪: false, 候选细纲: false, 确认细纲: false, 材料包状态: null,
  8. 有草稿: false, 唯一待审稿: false, 有审核记录: false, 审核完成: false,
  9. 待定稿包完整: false, 裁决: null, 已定稿: false, 需复核标记: [],
  10. ...over,
  11. }
  12. }
  13. function row(d: ReturnType<typeof deriveChapterFacts>, n: number): boolean {
  14. return d.事实项.find((r) => r.row === n)!.事实
  15. }
  16. describe('§8 扫描事实项清单(R1:逐行如实报告+可选建议,无权威位置)', () => {
  17. it('行1 窗口就绪:该行事实成立,建议=行1', () => {
  18. const d = deriveChapterFacts(facts({ 窗口就绪: true }))
  19. expect(row(d, 1)).toBe(true)
  20. expect(d.建议).toEqual({ row: 1, 环节: '章细纲(待定位)' })
  21. })
  22. it('行2 候选细纲:该行事实成立,建议=行2', () => {
  23. const d = deriveChapterFacts(facts({ 候选细纲: true }))
  24. expect(row(d, 2)).toBe(true)
  25. expect(d.建议).toEqual({ row: 2, 环节: '章细纲(待确认)' })
  26. })
  27. it('行3 确认细纲:该行事实成立,与材料包中间态无关(事实清单不是位置)', () => {
  28. for (const 状态 of [null, '组装中', '段有缺', '有冲突', '已过期'] as const) {
  29. const d = deriveChapterFacts(facts({ 确认细纲: true, 材料包状态: 状态 }))
  30. expect(row(d, 3)).toBe(true)
  31. expect(row(d, 4)).toBe(false)
  32. expect(d.建议).toEqual({ row: 3, 环节: '写作备料' })
  33. }
  34. })
  35. it('行4 材料包段齐备:行3/行4 同时成立,建议取最靠后(行4)', () => {
  36. const d = deriveChapterFacts(facts({ 确认细纲: true, 材料包状态: '段齐备' }))
  37. expect(row(d, 3)).toBe(true)
  38. expect(row(d, 4)).toBe(true)
  39. expect(d.建议).toEqual({ row: 4, 环节: '写稿' })
  40. })
  41. it('行5 有草稿无待审→建议润色', () => {
  42. expect(deriveChapterFacts(facts({ 有草稿: true })).建议).toEqual({ row: 5, 环节: '润色' })
  43. })
  44. it('行6 唯一待审稿→建议审核', () => {
  45. expect(deriveChapterFacts(facts({ 唯一待审稿: true })).建议).toEqual({ row: 6, 环节: '审核' })
  46. })
  47. it('行7 有审核记录未处置→建议改稿', () => {
  48. expect(deriveChapterFacts(facts({ 有审核记录: true })).建议).toEqual({ row: 7, 环节: '改稿' })
  49. })
  50. it('行8 审核完成无包→建议定稿准备与沉淀', () => {
  51. const d = deriveChapterFacts(facts({ 有审核记录: true, 审核完成: true }))
  52. expect(row(d, 8)).toBe(true)
  53. expect(d.建议).toEqual({ row: 8, 环节: '定稿准备与沉淀' })
  54. })
  55. it('行9 包完整无裁决→建议作者定稿裁决(控制点)', () => {
  56. const d = deriveChapterFacts(facts({ 审核完成: true, 待定稿包完整: true }))
  57. expect(d.建议).toEqual({ row: 9, 环节: '作者定稿裁决' })
  58. })
  59. it('行10 已批准未入档:行9/行10 同时成立,建议取行10', () => {
  60. const d = deriveChapterFacts(facts({ 待定稿包完整: true, 裁决: '已批准' }))
  61. expect(row(d, 9)).toBe(true)
  62. expect(row(d, 10)).toBe(true)
  63. expect(d.建议).toEqual({ row: 10, 环节: '定稿入档' })
  64. })
  65. it('行11 定稿文件在→建议完成', () => {
  66. expect(deriveChapterFacts(facts({ 已定稿: true })).建议).toEqual({ row: 11, 环节: '完成' })
  67. })
  68. it('退回:包完整但已退回→行9/行10 不成立,建议回落改稿(行 7)', () => {
  69. const d = deriveChapterFacts(facts({ 审核完成: true, 待定稿包完整: true, 裁决: '已退回', 有审核记录: true }))
  70. expect(row(d, 9)).toBe(false)
  71. expect(row(d, 10)).toBe(false)
  72. expect(d.建议).toEqual({ row: 7, 环节: '改稿' })
  73. })
  74. it('叠加标记:需复核随结果返回,不影响事实与建议', () => {
  75. const d = deriveChapterFacts(facts({ 窗口就绪: true, 需复核标记: ['细纲'] }))
  76. expect(d.建议).toEqual({ row: 1, 环节: '章细纲(待定位)' })
  77. expect(d.叠加标记).toContain('细纲')
  78. })
  79. it('兜底:全行不成立→建议行1 并播报窗口无可进入项(建议仍无权威)', () => {
  80. const d = deriveChapterFacts(facts())
  81. expect(d.建议).toEqual({ row: 1, 环节: '章细纲(待定位)' })
  82. expect(d.叠加标记).toContain('窗口无可进入项→当前卷规划滚动补充')
  83. })
  84. })