Fix case report evidence verification

This commit is contained in:
2026-08-22 20:07:16 +02:00
parent 52f0a31f44
commit f455c433b7
5 changed files with 127 additions and 17 deletions
+35 -2
View File
@@ -293,6 +293,18 @@ suite('normalized level persistence API', () => {
const fatherJudgment = await (await adminFetch(`${baseUrl}/api/levels/${imported.playableLevel.id}/documents/${fatherDocument.id}/judge`, { method:'POST' })).json()
expect(fatherJudgment).toMatchObject({ status:'succeeded',subject:'related',awardedFlags:['scene7.father_inventor_discovered'],
goals:[expect.objectContaining({ key:'barricelli.inventor-proof',status:'pending' })] })
const relatedState=await (await fetch(`${baseUrl}/api/levels/${imported.playableLevel.id}`)).json() as CaseState
const relatedClaim=relatedState.exhibits.find(exhibit => exhibit.type === 'claim')!
const relatedConnectionId=randomUUID()
relatedState.connections.push({ id:relatedConnectionId,fromExhibitId:relatedClaim.id,toExhibitId:fatherDocument.id,label:'Proof that the Barricelli family included an inventor.',tightness:65,tagStyle:'luggage',tagPosition:50,tagOffset:0 })
expect((await fetch(`${baseUrl}/api/levels/${relatedState.id}`,{ method:'PUT',headers:{'content-type':'application/json'},body:JSON.stringify(relatedState) })).status).toBe(200)
const relatedSubmission=await (await fetch(`${baseUrl}/api/levels/${relatedState.id}/report/submissions`,{ method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({
investigatorName:'Test Player',evidence:[{ connectionId:relatedConnectionId,documentExhibitId:fatherDocument.id,relationText:'Proof that the Barricelli family included an inventor.' }],
}) })).json()
expect(relatedSubmission).toMatchObject({ status:'evidence_insufficient',issues:expect.arrayContaining(['missing_accepted_evidence','connected_evidence_unverified']),
feedback:expect.stringContaining('related person rather than the claim subject'),claims:[expect.objectContaining({ evidence:[expect.objectContaining({
documentExhibitId:fatherDocument.id,evidenceAccepted:false,verification:expect.objectContaining({ status:'semantic_rejected' }),
})] })] })
const targetUpload = new FormData()
targetUpload.append('file', new Blob([readFileSync(path.join(fixtureDir, 'google-patents-target-ocr.txt'))], { type:'text/plain' }), 'google-patents-source.txt')
@@ -317,9 +329,30 @@ suite('normalized level persistence API', () => {
publishedAt:'1953-08-19',sourceCitation:'Google Patents · GB695913A',sourceUri:'https://patents.google.com/patent/GB695913A/en' }],
}) })
expect(accepted.status).toBe(201)
expect(await accepted.json()).toMatchObject({ status:'accepted',investigatorName:'Test Player',issues:[],claims:[expect.objectContaining({ evidence:[expect.objectContaining({
const acceptedBody=await accepted.json()
expect(acceptedBody).toMatchObject({ status:'accepted',investigatorName:'Test Player',issues:[] })
expect(acceptedBody.claims.flatMap((item:{ evidence:unknown[] }) => item.evidence)).toEqual(expect.arrayContaining([expect.objectContaining({
displayNumber:targetDocument.displayNumber,evidenceAccepted:true,sourceCitation:'Google Patents · GB695913A',publishedAt:'1953-08-19T00:00:00.000Z',
})] })] })
verification:expect.objectContaining({ status:'accepted' }),
})]))
// A later copy of the same correct source must be accepted on its own evaluation,
// even though the first copy already owns the one-time level-flag provenance.
const repeatedUpload=new FormData()
repeatedUpload.append('file',new Blob([readFileSync(path.join(fixtureDir,'google-patents-target-ocr.txt'))],{ type:'text/plain' }),'google-patents-second-copy.txt')
const repeatedDocument=await (await fetch(`${baseUrl}/api/levels/${reportState.id}/documents`,{ method:'POST',body:repeatedUpload })).json() as DocumentExhibit & { analysis:{ matchedFlags:string[];awardedFlags:string[] } }
expect(repeatedDocument.analysis).toMatchObject({ matchedFlags:['scene7.nils_inventor_proved'],awardedFlags:[] })
const repeatedState=await (await fetch(`${baseUrl}/api/levels/${reportState.id}`)).json() as CaseState
const repeatedConnectionId=randomUUID()
repeatedState.connections.push({ id:repeatedConnectionId,fromExhibitId:claim.id,toExhibitId:repeatedDocument.id,label:'Proof that Barricelli is named as the inventor on patent GB695913A.',tightness:65,tagStyle:'luggage',tagPosition:50,tagOffset:0 })
expect((await fetch(`${baseUrl}/api/levels/${repeatedState.id}`,{ method:'PUT',headers:{'content-type':'application/json'},body:JSON.stringify(repeatedState) })).status).toBe(200)
const repeatedReport=await (await fetch(`${baseUrl}/api/levels/${repeatedState.id}/report/submissions`,{ method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({
investigatorName:'Test Player',evidence:[{ connectionId:repeatedConnectionId,documentExhibitId:repeatedDocument.id,relationText:'Proof that Barricelli is named as the inventor on patent GB695913A.',
publishedAt:'1953-08-19',sourceCitation:'Google Patents · GB695913A',sourceUri:'https://patents.google.com/patent/GB695913A/en' }],
}) })).json()
expect(repeatedReport).toMatchObject({ status:'accepted',claims:[expect.objectContaining({ evidence:expect.arrayContaining([expect.objectContaining({
documentExhibitId:repeatedDocument.id,evidenceAccepted:true,verification:expect.objectContaining({ status:'accepted' }),
})]) })] })
judgeVerdict = { subject:'target',supports_claim:true,evidence_excerpt:'Ada Example patented a pocket telescope',confidence:.96 }
judgeHttpStatus = 200
})