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 planPath = path.join(root, "tests/golden/M15-03A/next-task-plan.json"); const outputDir = path.join(root, "tests/golden/M15-03A"); const catalogPath = path.join(outputDir, "task-catalog.jsonl"); const indexPath = path.join(outputDir, "task-index.json"); const sha256 = (bytes) => crypto.createHash("sha256").update(bytes).digest("hex"); const relative = (file) => path.relative(root, file).replaceAll(path.sep, "/"); const planBytes = fs.readFileSync(planPath); const plan = JSON.parse(planBytes); if (!Array.isArray(plan.tasks) || plan.tasks.length === 0) throw new Error("next-task plan has no tasks"); fs.mkdirSync(outputDir, { recursive: true }); const lines = []; const entries = {}; let offset = 0; for (let index = 0; index < plan.tasks.length; index += 1) { const task = plan.tasks[index]; const compactTask = { id: task.id, gapId: task.gapId, ownerFamily: task.ownerFamily, sourceTask: task.sourceTask, state: task.state, targetImplementationClass: task.targetImplementationClass, }; const line = `${JSON.stringify(compactTask)}\n`; const length = Buffer.byteLength(line, "utf8"); lines.push(line); entries[task.id] = { line: index, offset, length, previous: plan.tasks[index - 1]?.id ?? null, next: plan.tasks[index + 1]?.id ?? null, }; offset += length; } const catalogBytes = Buffer.from(lines.join(""), "utf8"); fs.writeFileSync(catalogPath, catalogBytes); const index = { schemaVersion: 1, operation: "BLENDER_TASK_CONTEXT_INDEX", source: { path: relative(planPath), sha256: sha256(planBytes) }, catalog: { path: relative(catalogPath), sha256: sha256(catalogBytes) }, taskCount: plan.tasks.length, activeTask: plan.firstTask, entries, }; fs.writeFileSync(indexPath, `${JSON.stringify(index)}\n`); process.stdout.write(`task-index-generated tasks=${plan.tasks.length} catalogBytes=${catalogBytes.byteLength} output=${relative(indexPath)}\n`);