Procedure for proving that a claimed defect fix actually reached the build under test and actually works. Covers the merge-base ancestry check that proves the running build contains the fix commit rather than trusting a version label, the priority order for choosing which reproduction to re-run, and the VERIFIED / NOT FIXED / BLOCKED verdict table whose governing rule is that any ambiguous, flaky, or unreproducible result resolves to BLOCKED and is never guessed. Scoped to ISTQB confirmation testing (does this specific fix work?), not regression testing (did the fix break something else?), and not triage or severity assignment. Use when a developer has marked a defect Fixed and someone must decide whether it moves to Verified or back to Reopened.
99
94%
Does it follow best practices?
Impact
100%
1.03xAverage score across 10 eval scenarios
Passed
No findings from the security scan
BUG-2264 (exporting a workspace with no projects returns a 500) was fixed in
3ad81c9. It sat in Fixed for six weeks while we shipped 4.0, and 4.0 removed
the endpoint the reporter used: POST /v1/exports is gone. What replaced it is
described in ops/route-changes.md.
So I cannot walk the ticket's steps as written. The compliance reviewer who signs off our defect closures reads the record and wants to see that what was executed corresponds to what was reported - "we ran something similar" comes back with questions every time.
Staging's build details and the containment check are in ops/checks.txt.
qa-record/BUG-2264.md: whether this defect can move to Verified,
the evidence, and - because the reported steps cannot be run as written - a
step-by-step statement of what was executed in place of each original step,
with the reason each substitution preserves what the original step was
testing, and any place where it does not.tests/bug-2264.repro.test.js so the next person does not have to
reconstruct this, and paste its real output into the record. npm test
must pass when you are done.src/exportJob.js, src/exportRoutes.js, src/store.js, the
existing test, the ticket, or anything under ops/.Extract the following files before beginning.
=============== FILE: issues/BUG-2264.md ===============
Status: Fixed (awaiting verification)
Reported: 2026-05-20 by support (acct: Onboarding trial users)
Fix commit: 3ad81c9 on main, merged 2026-06-24
POST /v1/exports with body {"workspaceId": "w_empty"} - a workspace
with zero projects. No format field; v1 defaults to csv.TypeError: Reduce of empty array with no initial value at buildCsv (src/exportJob.js:11)=============== FILE: package.json =============== { "name": "exports-service", "version": "4.2.0", "private": true, "scripts": { "test": "node --test" } }
=============== FILE: src/exportJob.js =============== 'use strict';
function buildCsv(rows) {
const header = 'id,name';
if (rows.length === 0) {
return header;
}
return [header, ...rows.map((r) => ${r.id},${r.name})].join('\n');
}
function buildExport(workspace, format) { const rows = (workspace.projects || []).map((p) => ({ id: p.id, name: p.name })); if (format === 'csv') { return { contentType: 'text/csv', body: buildCsv(rows), rowCount: rows.length }; } return { contentType: 'application/json', body: JSON.stringify(rows), rowCount: rows.length, }; }
module.exports = { buildCsv, buildExport };
=============== FILE: src/exportRoutes.js =============== 'use strict';
const { buildExport } = require('./exportJob');
function postWorkspaceExport(workspaceId, body, store) { const workspace = store[workspaceId]; if (!workspace) { return { status: 404, body: { code: 'NOT_FOUND' } }; } const format = body.format || 'json'; return { status: 200, body: buildExport(workspace, format) }; }
module.exports = { postWorkspaceExport };
=============== FILE: src/store.js =============== 'use strict';
const WORKSPACES = { w_empty: { id: 'w_empty', name: 'Onboarding sandbox', projects: [] }, w_2: { id: 'w_2', name: 'Atlas', projects: [ { id: 'p_1', name: 'Alpha' }, { id: 'p_2', name: 'Beta' }, ], }, };
module.exports = { WORKSPACES };
=============== FILE: tests/exportRoutes.test.js =============== 'use strict';
const test = require('node:test'); const assert = require('node:assert/strict'); const { postWorkspaceExport } = require('../src/exportRoutes'); const { WORKSPACES } = require('../src/store');
test('csv export of a workspace with projects', () => { const res = postWorkspaceExport('w_2', { format: 'csv' }, WORKSPACES); assert.equal(res.status, 200); assert.equal(res.body.rowCount, 2); assert.equal(res.body.body, 'id,name\np_1,Alpha\np_2,Beta'); });
=============== FILE: ops/route-changes.md ===============
| Before | After |
|---|---|
POST /v1/exports, workspace id in the body | POST /v2/workspaces/:id/exports, workspace id in the path |
body field format, defaulting to csv | body field format, defaulting to json |
POST /v1/exports was removed, not aliased. It returns 410 Gone.
The handler for the v2 route is postWorkspaceExport in
src/exportRoutes.js; buildExport is unchanged from v1 apart from the fix
in 3ad81c9.
=============== FILE: ops/checks.txt =============== $ curl -s https://exports.staging.internal/internal/build-info {"service":"exports-service","commit":"1de77b0","branch":"main","deployedAt":"2026-08-11T09:12:40Z"}
$ git merge-base --is-ancestor 3ad81c9 1de77b0; echo $? 0