session-snapshot-corpus-policy.spec.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import { describe, expect, it } from 'vitest'
  2. import { SESSION_FORMAT_VERSION } from '@deepseek-ai/dsh-session'
  3. import { assertSnapshotCorpusPolicy } from './session-snapshot-corpus-policy.ts'
  4. const completeV0 = {
  5. key: 'session/v0',
  6. selectedVersions: [0],
  7. retained: {
  8. version: 0,
  9. coverage: ['multi-hop', 'packed-row', 'retry-failure', 'shipped-profile'],
  10. },
  11. } as const
  12. const adjacent = Array.from({ length: SESSION_FORMAT_VERSION - 1 }, (_, index) => ({
  13. key: `sdk/v${index + 1}`,
  14. selectedVersions: [index + 1],
  15. retained: { version: index + 1, coverage: ['adjacent-migration'] as const },
  16. }))
  17. const current = { key: 'session/current', selectedVersions: Array<number>(8).fill(SESSION_FORMAT_VERSION) }
  18. describe('recorded-session corpus policy', () => {
  19. it('accepts a current majority and complete bounded migration coverage', () => {
  20. expect(assertSnapshotCorpusPolicy([
  21. current,
  22. {
  23. key: 'session/multi-hop',
  24. selectedVersions: [0, 0, 0],
  25. retained: { version: 0, coverage: ['multi-hop', 'shipped-profile'] },
  26. },
  27. { key: 'session/packed', selectedVersions: [0], retained: { version: 0, coverage: ['packed-row'] } },
  28. { key: 'session/retry', selectedVersions: [0], retained: { version: 0, coverage: ['retry-failure'] } },
  29. ...adjacent,
  30. ])).toEqual({ currentRoles: 8, retainedRoles: 5 + adjacent.length, retainedScenarios: 3 + adjacent.length })
  31. })
  32. it('retains retired tools in the current format without claiming migration coverage', () => {
  33. const retired = {
  34. key: 'web/retired', selectedVersions: [SESSION_FORMAT_VERSION],
  35. retained: { version: SESSION_FORMAT_VERSION, coverage: ['retired-tools'] as const },
  36. }
  37. expect(assertSnapshotCorpusPolicy([current, completeV0, ...adjacent, retired]).retainedScenarios)
  38. .toBe(2 + adjacent.length)
  39. expect(() => assertSnapshotCorpusPolicy([current, completeV0, retired]))
  40. .toThrow('coverage: adjacent-migration')
  41. expect(() => assertSnapshotCorpusPolicy([current, completeV0, ...adjacent, {
  42. ...retired, selectedVersions: [SESSION_FORMAT_VERSION + 1],
  43. retained: { ...retired.retained, version: SESSION_FORMAT_VERSION + 1 },
  44. }])).toThrow('retained Session format must precede')
  45. })
  46. it('requires v0 coverage from v0 fixtures', () => {
  47. expect(() => assertSnapshotCorpusPolicy([current, ...adjacent]))
  48. .toThrow('Session corpus lacks v0 coverage')
  49. })
  50. it.each(adjacent)('requires direct coverage from $key', (fixture) => {
  51. expect(() => assertSnapshotCorpusPolicy([
  52. current, completeV0, ...adjacent.filter(other => other !== fixture),
  53. ])).toThrow(`Session corpus lacks v${fixture.retained.version} coverage: adjacent-migration`)
  54. })
  55. it('does not let one retained generation claim another edge\'s coverage', () => {
  56. expect(() => assertSnapshotCorpusPolicy([
  57. current,
  58. completeV0,
  59. {
  60. key: 'sdk/adjacent',
  61. selectedVersions: [1],
  62. retained: { version: 1, coverage: ['adjacent-migration', 'multi-hop'] },
  63. },
  64. ])).toThrow('sdk/adjacent: v1 retained coverage must be adjacent-migration')
  65. expect(() => assertSnapshotCorpusPolicy([
  66. { ...completeV0, retained: { version: 0, coverage: ['adjacent-migration'] } },
  67. ])).toThrow('session/v0: v0 retained coverage must be multi-hop, packed-row, retry-failure, shipped-profile')
  68. })
  69. it('rejects absent roles, undeclared history, and mixed selected generations', () => {
  70. expect(() => assertSnapshotCorpusPolicy([{ key: 'session/empty', selectedVersions: [] }]))
  71. .toThrow('session/empty: scenario owns no selected Session role')
  72. expect(() => assertSnapshotCorpusPolicy([{ key: 'session/old', selectedVersions: [1] }]))
  73. .toThrow(`session/old: selected Session generation v1 does not match expected v${SESSION_FORMAT_VERSION}`)
  74. expect(() => assertSnapshotCorpusPolicy([{ ...completeV0, selectedVersions: [0, SESSION_FORMAT_VERSION] }]))
  75. .toThrow(`session/v0: selected Session generation v${SESSION_FORMAT_VERSION} does not match expected v0`)
  76. })
  77. it.each([SESSION_FORMAT_VERSION, SESSION_FORMAT_VERSION + 1, -1, 0.5])(
  78. 'rejects retained generation %s outside released history', (version) => {
  79. expect(() => assertSnapshotCorpusPolicy([{
  80. key: 'session/not-historical', selectedVersions: [version],
  81. retained: { version, coverage: ['adjacent-migration'] },
  82. }])).toThrow(`session/not-historical: retained Session format must precede current v${SESSION_FORMAT_VERSION}`)
  83. },
  84. )
  85. it('bounds historical roles and requires a current majority', () => {
  86. expect(() => assertSnapshotCorpusPolicy([
  87. { ...current, selectedVersions: Array<number>(20).fill(SESSION_FORMAT_VERSION) },
  88. { ...completeV0, selectedVersions: Array<number>(11).fill(0) },
  89. ...adjacent,
  90. ])).toThrow(`Session corpus retains ${11 + adjacent.length} historical roles; maximum is 10`)
  91. expect(() => assertSnapshotCorpusPolicy([
  92. { ...current, selectedVersions: [SESSION_FORMAT_VERSION] }, completeV0, ...adjacent,
  93. ])).toThrow(`Session corpus requires a current majority; current=1, retained=${1 + adjacent.length}`)
  94. })
  95. })