3 lines
7.1 KiB
JavaScript
3 lines
7.1 KiB
JavaScript
import assert from "node:assert/strict";import crypto from "node:crypto";import fs from "node:fs";import path from "node:path";import {execFileSync} from "node:child_process";import {fileURLToPath} from "node:url";
|
|
const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),"../..");const abs=f=>path.join(root,f);const read=f=>fs.readFileSync(abs(f),"utf8");const json=f=>JSON.parse(read(f));const sha=f=>crypto.createHash("sha256").update(fs.readFileSync(abs(f))).digest("hex");const digest=v=>crypto.createHash("sha256").update(v).digest("hex");const out="tests/golden/WBV2-P19-001",parentPath="tests/golden/WBV2-P19-000/manifest.json",inventoryPath="tests/golden/WBV2-P0-002/parity-map.json",apiPath="blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",clientPath="web/app/src/engine-client/WebEngineClient.ts",planPath=`${out}/parent-task-plan.json`,reportPath=`${out}/object-parent-selection-report.json`,candidatePath=`${out}/object-parent-candidate-set.json`,manifestPath=`${out}/manifest.json`,statusPath="docs/status/WBV2-P19-001.md";const parent=json(parentPath),inventory=json(inventoryPath);assert.equal(parent.status,"done");assert.equal(parent.nextTask,"WBV2-P19-001");for(const a of Object.values(parent.artifacts??{}))assert.equal(sha(a.path),a.sha256,a.path);assert.equal(inventory.summary.inventoryEntries,6900);assert.match(read(apiPath),/setParent/);assert.match(read(clientPath),/applyCommand/);const target=inventory.entries.find(e=>e.id==="operator:object.parent_set");assert.ok(target);assert.equal(target.legacyState,"pending");const behavior={capability:"OBJECT_OPERATIONS.PARENT",operation:"setParent",positive:["parent-relation","keep-transform","undo","redo","save-reopen"],negative:["missing-parent-id","cycle"],browser:"chromium",engine:"compiled-WASM-WebEngine-Main"};const behaviorHash=digest(JSON.stringify(behavior));const candidate={schemaVersion:1,task:"WBV2-P19-001",operation:"OBJECT_PARENT_CANDIDATE_SELECTION",status:"READY",source:{inventory:inventoryPath,inventorySha256:sha(inventoryPath),api:apiPath,apiSha256:sha(apiPath),client:clientPath,clientSha256:sha(clientPath)},candidate:{capabilityId:"OBJECT_OPERATIONS.PARENT",legacyId:target.id,legacyTask:target.evidence.legacyTask,behavior,behaviorHash,dedupeKey:`OBJECT_OPERATIONS.PARENT|${behaviorHash}|${sha(apiPath)}|${sha(clientPath)}`,sourceBacked:true,chromiumProductionReady:true,fullFamilyParity:false},inventory:{matchedEntries:1,pending:1,total:6900,basePending:6618,effectivePending:6614,remainderExplicit:true},entries:[{id:target.id,sourceTask:target.sourceTask,legacyState:target.legacyState,targetImplementationClass:target.targetImplementationClass}],policy:{sourceHistoryReadOnly:true,representativeSliceOnly:true,noRepeatedExecution:true,duplicateValidationAvoided:true,fullHistoricalReproduction:false}};const report={schemaVersion:1,task:"WBV2-P19-001",operation:"SELECT_OBJECT_PARENT_BATCH",status:"PASS",candidate:candidate.candidate,inventory:candidate.inventory,source:candidate.source,matchedEntryDigest:digest(target.id),efficiency:{oneEntryScan:true,existingEvidenceReused:true,repeatedBlenderRuns:0,repeatedChromiumRuns:0,duplicateValidationAvoided:true},nextTask:"WBV2-P19-002"};if(!process.argv.includes("--write")){console.log(`wbv2-parent-selection-ok task=WBV2-P19-001 legacyId=${target.id} behaviorHash=${behaviorHash} pending=6614 repeatedRuns=0 next=WBV2-P19-002`);process.exit(0)}fs.mkdirSync(abs(out),{recursive:true});fs.writeFileSync(abs(candidatePath),`${JSON.stringify(candidate,null,2)}\n`);fs.writeFileSync(abs(reportPath),`${JSON.stringify(report,null,2)}\n`);fs.writeFileSync(abs(statusPath),`# WBV2-P19-001 status\n\n- task: \`WBV2-P19-001\`; parent: \`WBV2-P19-000\`; status: \`done\`\n- selected behavior: \`setParent\`; exact candidate: \`operator:object.parent_set\`\n- base inventory: \`6900\` total, \`6618\` pending; effective carried overlay: \`6614\` pending\n- behavior hash: \`${behaviorHash}\`; duplicate validation: \`forbidden\`\n- nextTask: \`WBV2-P19-002\`\n`);const previous=json("tests/golden/WBV2-P19-000/parent-task-plan.json"),next=structuredClone(previous);next.parentRecoveryPlan={path:"tests/golden/WBV2-P19-000/parent-task-plan.json",sha256:sha("tests/golden/WBV2-P19-000/parent-task-plan.json")};next.tasks=next.tasks.map(t=>t.id==="WBV2-P19-001"?{...t,status:"done",ready:false}:t.id==="WBV2-P19-002"?{...t,status:"in_progress",ready:true}:{...t,ready:false});fs.writeFileSync(abs(planPath),`${JSON.stringify(next,null,2)}\n`);fs.writeFileSync(abs("docs/tasks/WBV2-P19-002.md"),read("docs/tasks/WBV2-P19-002.md").replace("- status: planned","- status: in_progress"));execFileSync(process.execPath,[abs("tools/web/generate-v2-task-index.mjs"),"--plan-path",abs(planPath)],{cwd:root,stdio:"inherit"});execFileSync(process.execPath,[abs("tools/web/check-task-context.mjs"),"--task","WBV2-P19-001","--write"],{cwd:root,stdio:"inherit"});const paths={parentManifest:parentPath,inventory:inventoryPath,api:apiPath,client:clientPath,candidate:candidatePath,report:reportPath,generator:"tools/web/generate-wbv2-parent-selection.mjs",status:statusPath,parityPlan:planPath,taskContext:`${out}/task-context.json`};const artifacts=Object.fromEntries(Object.entries(paths).map(([n,f])=>[n,{path:f,sha256:sha(f)}]));fs.writeFileSync(abs(manifestPath),`${JSON.stringify({schemaVersion:1,task:"WBV2-P19-001",parentTask:"WBV2-P19-000",operation:"SELECT_OBJECT_PARENT_BATCH",status:"done",enablingTask:true,parityStateChange:false,runtime:"READ_ONLY_SOURCE_CANDIDATE_SELECTION",artifacts,assertions:{legacyId:target.id,inventoryTotal:6900,basePending:6618,effectivePending:6614,sourceApiBound:true,representativeSliceOnly:true,fullFamilyParity:false,repeatedBlenderRuns:0,repeatedChromiumRuns:0,duplicateValidationAvoided:true,deterministic:true,historicalReproduction:false},nextTask:"WBV2-P19-002"},null,2)}\n`);let q=read("docs/EXECUTION_QUEUE.md");q=q.replace(/\| 当前任务 \| `[^`]+` \|/u,"| 当前任务 | `WBV2-P19-002` |").replace(/\| parent manifest \| `[^`]+` \|/u,"| parent manifest | `tests/golden/WBV2-P19-001/manifest.json` |").replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u,"| 任务卡 | [`tasks/WBV2-P19-002.md`](tasks/WBV2-P19-002.md) |");fs.writeFileSync(abs("docs/EXECUTION_QUEUE.md"),q);let n=read("nextTask.md");n=n.replace(/\| Current task when this file was written \| `[^`]+` \|/u,"| Current task when this file was written | `WBV2-P19-002` |").replace(/\| Current task state \| `[^`]+` \|/u,"| Current task state | `in_progress` |").replace(/\| Parent manifest \| `[^`]+` \|/u,"| Parent manifest | `tests/golden/WBV2-P19-001/manifest.json` |").replace(/\| Current task card \| `[^`]+` \|/u,"| Current task card | `docs/tasks/WBV2-P19-002.md` |").replace(/\| Current task-context nextTask \| `[^`]+` \|/u,"| Current task-context nextTask | `WBV2-P19-003` |").replace(/\| Focused command \| `[^`]+` \|/u,"| Focused command | `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-object-parent-production.spec.ts` |");fs.writeFileSync(abs("nextTask.md"),n);console.log(`wbv2-parent-selection-written task=WBV2-P19-001 legacyId=${target.id} behaviorHash=${behaviorHash} next=WBV2-P19-002 artifacts=${Object.keys(artifacts).length}`);
|