import assert from "node:assert/strict"; import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const indexPath = path.join(root, "tests/golden/M15-03A/task-index.json"); const index = JSON.parse(fs.readFileSync(indexPath, "utf8")); const sha256File = (file) => crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex"); const resolve = (value) => path.join(root, value); const planPath = resolve(index.source.path); const catalogPath = resolve(index.catalog.path); assert.equal(index.schemaVersion, 1); assert.equal(sha256File(planPath), index.source.sha256, "task index source plan is stale; regenerate it"); assert.equal(sha256File(catalogPath), index.catalog.sha256, "task catalog hash mismatch"); assert.equal(Object.keys(index.entries).length, index.taskCount); const catalog = fs.openSync(catalogPath, "r"); let activeCount = 0; try { const bytes = fs.statSync(catalogPath).size; let previousEnd = 0; for (const [id, entry] of Object.entries(index.entries)) { assert.equal(entry.offset, previousEnd, `${id} offset is not contiguous`); assert.ok(entry.length > 0, `${id} has an empty record`); assert.ok(entry.offset + entry.length <= bytes, `${id} points past catalog`); const buffer = Buffer.alloc(entry.length); fs.readSync(catalog, buffer, 0, entry.length, entry.offset); const record = JSON.parse(buffer.toString("utf8")); assert.equal(record.id, id); assert.ok(record.gapId && record.ownerFamily && record.targetImplementationClass); if (record.state === "active") activeCount += 1; previousEnd += entry.length; } assert.equal(previousEnd, bytes, "catalog has unindexed bytes"); } finally { fs.closeSync(catalog); } assert.ok(index.entries[index.activeTask]?.previous, "active task must have a parent"); assert.equal(activeCount, 1, "task index must contain exactly one active task"); process.stdout.write(`task-index-ok tasks=${index.taskCount} active=${index.activeTask} catalog=${index.catalog.path}\n`);