diff --git a/lib/qa-evidence.ts b/lib/qa-evidence.ts index 0b04ab54d..d47d004e1 100644 --- a/lib/qa-evidence.ts +++ b/lib/qa-evidence.ts @@ -193,7 +193,8 @@ function checkpoint(root: string, checkpointId: string, source: string | Record< const captured = readQaCapture(root, intent.capture); const value = { observationCommand: intent.observationCommand, observed: captured.observed, hypothesis: intent.hypothesis, nextCommand: intent.nextCommand }; const sha256 = publish(root, `exploration-${checkpointId}.json`, value); - return { action: 'checkpoint', id: checkpointId, status: 'complete', sha256, capture: intent.capture, captureSha256: captured.sha256, intentSha256: hash(bytes), exitCode: 0 }; + return { action: 'checkpoint', id: checkpointId, status: 'complete', sha256, capture: intent.capture, captureSha256: captured.sha256, intentSha256: hash(bytes), + link: `[checkpoint ${checkpointId}](exploration-${checkpointId}.json)`, exitCode: 0 }; } function materialize(root: string, source: string) { diff --git a/qa/templates/functional-report-template.md b/qa/templates/functional-report-template.md index 1838fc585..96a3189c2 100644 --- a/qa/templates/functional-report-template.md +++ b/qa/templates/functional-report-template.md @@ -33,6 +33,7 @@ evidence and regression baselines. Do not combine their scores or outcomes. ## Discoveries and permanent tests Link each `exploration-NNN.json` checkpoint, saved before its next probe, in this report. +Each checkpoint receipt prints its `link`; `.qa-evidence/NNN` capture folders are not checkpoints. Use one Markdown entry per checkpoint, for example: - [checkpoint 001](exploration-001.json) — how this observation shaped the next probe. diff --git a/test/qa-evidence.test.ts b/test/qa-evidence.test.ts index b54e0e8fe..9ec3f7ea9 100644 --- a/test/qa-evidence.test.ts +++ b/test/qa-evidence.test.ts @@ -43,7 +43,7 @@ test('native capture executes once, preserves exact JSON and stderr, and materia f.json('intent.json', { capture: '001', observationCommand: 'first native command', hypothesis: 'The successful boundary suggests testing the rejected input next.', nextCommand: 'second native command' }); const checkpoint = f.run('checkpoint', f.root, '001', 'intent.json'); expect(checkpoint.status, checkpoint.stderr).toBe(0); - expect(receipt(checkpoint.stdout)).toMatchObject({ action: 'checkpoint', status: 'complete', id: '001' }); + expect(receipt(checkpoint.stdout)).toMatchObject({ action: 'checkpoint', status: 'complete', id: '001', link: '[checkpoint 001](exploration-001.json)' }); expect(JSON.parse(fs.readFileSync(path.join(f.root, 'exploration-001.json'), 'utf8'))).toEqual({ observationCommand: 'first native command', observed, hypothesis: 'The successful boundary suggests testing the rejected input next.', nextCommand: 'second native command', });