Ver Fonte

test(web): compare fixture inventories by Session role and pin the v2 upload

`assertFixtureInventory` folds every retained generation of one parent or
child fixture into a single role before comparing, so an older generation kept
beside the current one is not an inventory drift. The generation spec writes
headers that match each filename, since fixture selection validates the chosen
generation, and asserts that an absent parent resolves only for an
override-only replay. The `dsh_session_log` composition expectation follows the
extension's version 2 payload.
Tianyi Cui há 3 semanas atrás
pai
commit
874b174fd6

+ 13 - 7
apps/web/tests/scaffold-generation.spec.ts

@@ -18,12 +18,16 @@ describe('Web snapshot generation filenames', () => {
   it('selects the highest parent and child generations without counting retained inputs twice', async () => {
   it('selects the highest parent and child generations without counting retained inputs twice', async () => {
     const root = await mkdtemp(join(tmpdir(), 'dsh-web-fixture-generations-'))
     const root = await mkdtemp(join(tmpdir(), 'dsh-web-fixture-generations-'))
     roots.push(root)
     roots.push(root)
-    for (const name of [
-      'session.jsonl',
-      'session.v2.jsonl',
-      'session.1.jsonl',
-      'session.1.v1.jsonl',
-    ]) await writeFile(join(root, name), '')
+    for (const [name, version] of [
+      ['session.jsonl', 0],
+      ['session.v2.jsonl', 2],
+      ['session.1.jsonl', 0],
+      ['session.1.v1.jsonl', 1],
+    ] as const) {
+      await writeFile(join(root, name), `${JSON.stringify({
+        type: 'session', version, id: '{{session:1}}', createdAt: 0, delegationDepth: 0,
+      })}\n`)
+    }
 
 
     await expect(selectedSessionFixture(join(root, 'session.jsonl')))
     await expect(selectedSessionFixture(join(root, 'session.jsonl')))
       .resolves.toBe(join(root, 'session.v2.jsonl'))
       .resolves.toBe(join(root, 'session.v2.jsonl'))
@@ -37,8 +41,10 @@ describe('Web snapshot generation filenames', () => {
     const root = await mkdtemp(join(tmpdir(), 'dsh-web-fixture-generations-'))
     const root = await mkdtemp(join(tmpdir(), 'dsh-web-fixture-generations-'))
     roots.push(root)
     roots.push(root)
 
 
-    await expect(selectedSessionFixture(join(root, 'session.jsonl')))
+    await expect(selectedSessionFixture(join(root, 'session.jsonl'), true))
       .resolves.toBe(join(root, 'session.jsonl'))
       .resolves.toBe(join(root, 'session.jsonl'))
+    await expect(selectedSessionFixture(join(root, 'session.jsonl')))
+      .rejects.toThrow('missing parent session fixture')
   })
   })
 
 
   it('records beside an older generation and preserves the parent or child role', () => {
   it('records beside an older generation and preserves the parent or child role', () => {

+ 7 - 3
apps/web/tests/scaffold.ts

@@ -1466,15 +1466,19 @@ export async function assertFixtureInventory(dir: string, expected: string[]): P
   const entries = (await readdir(dir)).sort()
   const entries = (await readdir(dir)).sort()
   const ownsManifest = entries.includes('snapshot.yml')
   const ownsManifest = entries.includes('snapshot.yml')
   const artifacts = entries.filter(name => name !== 'snapshot.yml')
   const artifacts = entries.filter(name => name !== 'snapshot.yml')
-  expect(artifacts).toEqual([...expected].sort())
+  const roleInventory = (names: readonly string[]): string[] => [...new Set(names.map((name) => {
+    const fixture = parseSessionFixtureName(name)
+    return fixture === undefined ? name : sessionFixtureName(fixture.index, 0)
+  }))].sort()
+  expect(roleInventory(artifacts)).toEqual(roleInventory(expected))
   if (ownsManifest) {
   if (ownsManifest) {
     const manifestPath = join(dir, 'snapshot.yml')
     const manifestPath = join(dir, 'snapshot.yml')
     const manifest = parseSnapshotManifest(await readFile(manifestPath, 'utf8'), manifestPath)
     const manifest = parseSnapshotManifest(await readFile(manifestPath, 'utf8'), manifestPath)
     expect(manifest.profile).toBe('web')
     expect(manifest.profile).toBe('web')
     if (manifest.session === undefined) {
     if (manifest.session === undefined) {
       expect(
       expect(
-        artifacts.includes('session.jsonl'),
-        `${dir}: session owner must carry session.jsonl`,
+        artifacts.some(name => parseSessionFixtureName(name)?.index === 0),
+        `${dir}: session owner must carry a canonical parent Session fixture`,
       ).toBe(true)
       ).toBe(true)
     } else {
     } else {
       expect(existsSync(resolve(dir, manifest.session.source)), `${dir}: session source`).toBe(true)
       expect(existsSync(resolve(dir, manifest.session.source)), `${dir}: session source`).toBe(true)

+ 1 - 1
packages/llm/llm-deepseek/tests/loader-composition.spec.ts

@@ -182,7 +182,7 @@ describe('llm-deepseek real dynamic composition', () => {
       }
       }
     }
     }
     expect(request.dsh_session_log).toMatchObject({
     expect(request.dsh_session_log).toMatchObject({
-      version: 1,
+      version: 2,
       session: { id: 'extension-composition-enabled' },
       session: { id: 'extension-composition-enabled' },
       afterSeq: -1,
       afterSeq: -1,
       throughSeq: 0,
       throughSeq: 0,