(value: unknown, label = 'Evidence')
| 83 | } |
| 84 | |
| 85 | function validateEvidence(value: unknown, label = 'Evidence'): asserts value is CliEvidence { |
| 86 | expect(value, `${label}: must be an object`).toBeTypeOf('object'); |
| 87 | expect(value, `${label}: not null`).not.toBeNull(); |
| 88 | const obj = value as Record<string, unknown>; |
| 89 | expectRequired(obj, EVIDENCE_REQUIRED, label); |
| 90 | expectKeysMatch(obj, new Set(EVIDENCE_REQUIRED), label); |
| 91 | expect(EVIDENCE_KINDS.has(obj.kind), `${label}.kind`).toBe(true); |
| 92 | expect(typeof obj.stepIndex, `${label}.stepIndex`).toBe('number'); |
| 93 | expect((obj.stepIndex as number) >= 1, `${label}.stepIndex >= 1`).toBe(true); |
| 94 | expect(typeof obj.url, `${label}.url`).toBe('string'); |
| 95 | expect((obj.url as string).startsWith('https://'), `${label}.url is https`).toBe(true); |
| 96 | // §6.1: summary is non-nullable. M2 ships a deterministic |
| 97 | // synthesizer until the LLM pipeline lands. |
| 98 | expect(typeof obj.summary, `${label}.summary`).toBe('string'); |
| 99 | expect((obj.summary as string).length, `${label}.summary non-empty`).toBeGreaterThan(0); |
| 100 | } |
| 101 | |
| 102 | function validateFailureBlock( |
| 103 | value: unknown, |
no test coverage detected