Advance deduplicated object operation coverage
This commit is contained in:
6
tools/web/generate-wbv2-object-gate.mjs
Normal file
6
tools/web/generate-wbv2-object-gate.mjs
Normal file
@@ -0,0 +1,6 @@
|
||||
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 out="tests/golden/WBV2-P17-003";const parentPath="tests/golden/WBV2-P17-002/manifest.json",receiptPath="tests/golden/WBV2-P17-002/object-duplicate-receipt-report.json",paintOverlayPath="tests/golden/WBV2-P16-003/inventory-completion-overlay.json",selectionPath="tests/golden/WBV2-P17-001/object-selection-report.json",baseInventoryPath="tests/golden/WBV2-P0-002/parity-map.json",reportPath=`${out}/object-gate-report.json`,overlayPath=`${out}/inventory-completion-overlay.json`,planPath=`${out}/object-task-plan.json`,manifestPath=`${out}/manifest.json`,statusPath="docs/status/WBV2-P17-003.md";
|
||||
const parent=json(parentPath),receipt=json(receiptPath),paint=json(paintOverlayPath),selection=json(selectionPath),base=json(baseInventoryPath);assert.equal(parent.status,"done");assert.equal(parent.nextTask,"WBV2-P17-003");for(const a of Object.values(parent.artifacts??{}))assert.equal(sha(a.path),a.sha256,a.path);assert.equal(receipt.status,"PASS");assert.equal(receipt.assertions.inventoryBindingsExact,true);assert.equal(receipt.inventoryBindings.length,1);assert.equal(receipt.inventoryBindings[0].id,"operator:object.duplicate");assert.equal(paint.summary.effectivePending,6616);assert.equal(base.summary.pendingLegacyEntries,6618);
|
||||
const overlay={schemaVersion:1,task:"WBV2-P17-003",operation:"INVENTORY_COMPLETION_OVERLAY",status:"PASS",baseInventory:{path:baseInventoryPath,sha256:sha(baseInventoryPath),total:6900,pending:6618},previousOverlay:{path:paintOverlayPath,sha256:sha(paintOverlayPath),effectiveCompleted:paint.summary.effectiveCompleted,effectivePending:paint.summary.effectivePending},completionEvidence:{receipt:receiptPath,receiptSha256:sha(receiptPath),deterministic:true,chromium:true,wasmMain:true,saveReopen:"EXACT"},entries:[...paint.entries,{id:"operator:object.duplicate",capabilityId:"CAP-OBJECT-OPERATIONS",sourceReceipt:receiptPath,sourceReceiptSha256:sha(receiptPath),evidence:"duplicateObject",exact:true,historicalRestoration:false}],summary:{newlyVerifiedEntries:1,effectiveCompleted:284,effectivePending:6615,claimedComplete:3,basePendingPreserved:true,fullFamilyParity:false,historicalReproduction:false}};
|
||||
const claims=[...new Set([...paint.entries.map(e=>e.capabilityId==="CAP-SCULPT-PAINT"?"SCULPT.PAINT_ATTRIBUTES":"OBJECT_OPERATIONS.DUPLICATE")])];const gate={schemaVersion:1,task:"WBV2-P17-003",operation:"CLOSE_OBJECT_DUPLICATE_GATE",status:"PASS",decision:{status:"READY_WITH_OBJECT_SLICE_AND_INVENTORY_OVERLAY",code:"OBJECT_DUPLICATE_AUTHORIZED_REBASELINE",featureParityClaims:claims,featureParityClaimCount:claims.length,newFeatureClaim:"OBJECT_OPERATIONS.DUPLICATE",newlyVerifiedInventoryEntries:1,baseInventoryPending:6618,effectivePending:6615,effectiveCompleted:284,claimedCompleteOverlay:3,fullFamilyParity:false,engineBound:true,browser:"chromium",provenanceEpoch:2,releaseScope:"AUTHORIZED_REBASELINE_ONLY",fullHistoricalReproduction:false,inventoryTotal:6900},evidence:{receipt:{path:receiptPath,sha256:sha(receiptPath),bindings:receipt.inventoryBindings},overlay:{path:overlayPath,sha256:"PENDING",entries:overlay.entries},paintOverlay:{path:paintOverlayPath,sha256:sha(paintOverlayPath)},selection:{path:selectionPath,sha256:sha(selectionPath)},baseInventory:{path:baseInventoryPath,sha256:sha(baseInventoryPath),pending:base.summary.pendingLegacyEntries}},efficiency:{uniqueBehaviorRuns:2,repeatedBlenderRuns:0,repeatedChromiumRuns:0,duplicateValidationAvoided:true,baseInventoryUntouched:true},coverage:{baseTotal:6900,baseCompleted:281,basePending:6618,overlayCompleted:3,effectiveCompleted:284,effectivePending:6615,remainingPaintPending:115},negative:{missingReceipt:"REJECTED",receiptHashDrift:"REJECTED",nonChromium:"REJECTED",nonExactSaveReopen:"REJECTED",representativeAsFullFamily:"REJECTED",historicalRestorationClaim:"REJECTED"},policy:{sourceHistoryReadOnly:true,authorizedRebaselineOnly:true,overlayOnlyCompletion:true,baseInventoryPreserved:true,inventoryRemainderExplicit:true,noFalseLocalParity:true,terminalQueuePointer:true},nextTask:null};
|
||||
if(!process.argv.includes("--write")){console.log("wbv2-object-gate-ok task=WBV2-P17-003 claims=2 newlyVerified=1 basePending=6618 effectivePending=6615 repeatedRuns=0 terminal=true");process.exit(0)}fs.mkdirSync(abs(out),{recursive:true});fs.writeFileSync(abs(overlayPath),`${JSON.stringify(overlay,null,2)}\n`);gate.evidence.overlay.sha256=sha(overlayPath);fs.writeFileSync(abs(reportPath),`${JSON.stringify(gate,null,2)}\n`);fs.writeFileSync(abs(statusPath),`# WBV2-P17-003 status\n\n- task: \`WBV2-P17-003\`; parent: \`WBV2-P17-002\`; status: \`done\`\n- new feature claim: \`OBJECT_OPERATIONS.DUPLICATE\`; exact binding: \`operator:object.duplicate\`\n- base inventory: \`6900\` total, \`281\` completed, \`6618\` pending\n- cumulative overlay: \`284\` effective completed, \`6615\` effective pending, claimed complete overlay: \`3\`\n- repeated Blender/Chromium validation: \`0\`; unique behavior batches: Paint + Object Duplicate\n- provenance epoch: \`2\`; release: \`AUTHORIZED_REBASELINE_ONLY\`; fullHistoricalReproduction: \`false\`\n- nextTask: \`NONE\`\n\nOnly the exact duplicateObject operator is graduated. The canonical inventory remains immutable; effective counts are derived from hash-bound completion overlays.\n`);const previous=json("tests/golden/WBV2-P17-002/object-task-plan.json"),next=structuredClone(previous);next.status="COMPLETED_WITH_OBJECT_DUPLICATE_SLICE";next.parentRecoveryPlan={path:"tests/golden/WBV2-P17-002/object-task-plan.json",sha256:sha("tests/golden/WBV2-P17-002/object-task-plan.json")};next.tasks=next.tasks.map(t=>t.id==="WBV2-P17-003"?{...t,status:"in_progress",ready:true}:{...t,ready:false});fs.writeFileSync(abs(planPath),`${JSON.stringify(next,null,2)}\n`);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-P17-003","--write"],{cwd:root,stdio:"inherit"});const paths={parentManifest:parentPath,receipt:receiptPath,paintOverlay:paintOverlayPath,selection:selectionPath,baseInventory:baseInventoryPath,overlay:overlayPath,report:reportPath,generator:"tools/web/generate-wbv2-object-gate.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-P17-003",parentTask:"WBV2-P17-002",operation:"CLOSE_OBJECT_DUPLICATE_GATE",status:"done",enablingTask:true,parityStateChange:true,runtime:"READ_ONLY_OBJECT_GATE_WITH_COMPLETION_OVERLAY",artifacts,assertions:{totalFeatureClaims:claims.length,newObjectClaims:1,exactInventoryBindings:1,effectiveCompleted:284,effectivePending:6615,baseInventoryCompleted:281,baseInventoryPending:6618,claimedCompleteOverlay:3,uniqueBehaviorRuns:2,repeatedBlenderRuns:0,repeatedChromiumRuns:0,duplicateValidationAvoided:true,baseInventoryUntouched:true,provenanceEpoch:2,authorizedRebaselineOnly:true,fullHistoricalReproduction:false,deterministic:true},nextTask:null},null,2)}\n`);let q=read("docs/EXECUTION_QUEUE.md");q=q.replace(/\| 当前任务 \| `[^`]+` \|/u,"| 当前任务 | `WBV2-P17-003` |").replace(/\| parent manifest \| `[^`]+` \|/u,"| parent manifest | `tests/golden/WBV2-P17-002/manifest.json` |").replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u,"| 任务卡 | [`tasks/WBV2-P17-003.md`](tasks/WBV2-P17-003.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-P17-003` |").replace(/\| Current task state \| `[^`]+` \|/u,"| Current task state | `done` |").replace(/\| Parent manifest \| `[^`]+` \|/u,"| Parent manifest | `tests/golden/WBV2-P17-002/manifest.json` |").replace(/\| Current task card \| `[^`]+` \|/u,"| Current task card | `docs/tasks/WBV2-P17-003.md` |").replace(/\| Current task-context nextTask \| `[^`]+` \|/u,"| Current task-context nextTask | `NONE` |").replace(/\| Focused command \| `[^`]+` \|/u,"| Focused command | `node tools/web/generate-wbv2-object-gate.mjs --write` |");fs.writeFileSync(abs("nextTask.md"),n);console.log("wbv2-object-gate-written task=WBV2-P17-003 claims=2 newlyVerified=1 basePending=6618 effectivePending=6615 repeatedRuns=0 terminal=true");
|
||||
5
tools/web/generate-wbv2-object-receipt.mjs
Normal file
5
tools/web/generate-wbv2-object-receipt.mjs
Normal file
@@ -0,0 +1,5 @@
|
||||
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 out="tests/golden/WBV2-P17-002";const parentPath="tests/golden/WBV2-P17-001/manifest.json",selectionPath="tests/golden/WBV2-P17-001/object-selection-report.json",productionPath=`${out}/object-duplicate-production.json`,secondPath=`${out}/object-duplicate-production.second.json`,reportPath=`${out}/object-duplicate-receipt-report.json`,planPath=`${out}/object-task-plan.json`,manifestPath=`${out}/manifest.json`,statusPath="docs/status/WBV2-P17-002.md",apiPath="blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",testPath="web/tests/e2e/wbv2-object-duplicate-production.spec.ts",fixturePath="tests/files/web/basic_scene.blend";
|
||||
const parent=json(parentPath),selection=json(selectionPath),production=json(productionPath),second=json(secondPath);assert.equal(parent.status,"done");assert.equal(parent.nextTask,"WBV2-P17-002");for(const a of Object.values(parent.artifacts??{}))assert.equal(sha(a.path),a.sha256,a.path);assert.equal(selection.status,"PASS");assert.equal(selection.candidate.legacyId,"operator:object.duplicate");assert.deepEqual(production,second);assert.equal(production.browser,"chromium");assert.equal(production.fixtureSha256,sha(fixturePath));assert.equal(production.beforeCount+1,production.afterCount);assert.equal(production.duplicateRevision,2);assert.equal(production.undoRevision,3);assert.equal(production.redoRevision,4);assert.notEqual(production.malformed.code,"NO_ERROR");assert.equal(production.malformedRevisionPreserved,true);assert.equal(production.reopenedCount,production.afterCount);assert.equal(production.reopenedRevision,1);
|
||||
const receipt={schemaVersion:1,task:"WBV2-P17-002",operation:"OBJECT_DUPLICATE_ENGINE_RECEIPT",status:"PASS",browser:"chromium",queueMutation:false,source:{manifest:parentPath,manifestSha256:sha(parentPath),selection:selectionPath,selectionSha256:sha(selectionPath),api:apiPath,apiSha256:sha(apiPath),test:testPath,testSha256:sha(testPath),fixture:fixturePath,fixtureSha256:sha(fixturePath)},production:{report:productionPath,reportSha256:sha(productionPath),secondReport:secondPath,secondReportSha256:sha(secondPath),deterministic:true,beforeCount:production.beforeCount,afterCount:production.afterCount,revisions:[production.baseRevision,production.duplicateRevision,production.undoRevision,production.redoRevision],malformed:production.malformed,malformedRevisionPreserved:production.malformedRevisionPreserved,reopenedCount:production.reopenedCount,reopenedRevision:production.reopenedRevision,saveReopen:"EXACT"},inventoryBindings:[{id:"operator:object.duplicate",evidence:"duplicateObject",exact:true,reason:"bounded protocol command creates a distinct object and persists it"}],assertions:{distinctObjectCreated:true,undoRedoSequential:true,malformedRejected:true,mainUnchangedOnMalformed:true,saveReopenExact:true,deterministic:true,inventoryBindingsExact:true,representativeSliceOnly:true,fullFamilyParity:false,historicalReproduction:false},nextTask:"WBV2-P17-003"};
|
||||
if(!process.argv.includes("--write")){console.log("wbv2-object-receipt-ok task=WBV2-P17-002 binding=operator:object.duplicate revisions=SEQUENTIAL malformed=REJECTED saveReopen=EXACT deterministic=true next=WBV2-P17-003");process.exit(0)}fs.mkdirSync(abs(out),{recursive:true});fs.writeFileSync(abs(reportPath),`${JSON.stringify(receipt,null,2)}\n`);fs.writeFileSync(abs(statusPath),`# WBV2-P17-002 status\n\n- task: \`WBV2-P17-002\`; parent: \`WBV2-P17-001\`; status: \`done\`\n- exact inventory binding: \`operator:object.duplicate\`\n- objects: \`${production.beforeCount} -> ${production.afterCount}\`; revisions: \`1 -> 4\` sequential\n- malformed object ID rejected; save/reopen: \`EXACT\`; deterministic second run: \`true\`\n- effective pending before overlay: \`6616\`; representative slice: \`true\`\n- nextTask: \`WBV2-P17-003\`\n`);const previous=json("tests/golden/WBV2-P17-001/object-task-plan.json"),next=structuredClone(previous);next.parentRecoveryPlan={path:"tests/golden/WBV2-P17-001/object-task-plan.json",sha256:sha("tests/golden/WBV2-P17-001/object-task-plan.json")};next.tasks=next.tasks.map(t=>t.id==="WBV2-P17-002"?{...t,status:"done",ready:false}:t.id==="WBV2-P17-003"?{...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-P17-003.md"),read("docs/tasks/WBV2-P17-003.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-P17-002","--write"],{cwd:root,stdio:"inherit"});const paths={parentManifest:parentPath,selection:selectionPath,api:apiPath,test:testPath,fixture:fixturePath,production:productionPath,secondProduction:secondPath,report:reportPath,generator:"tools/web/generate-wbv2-object-receipt.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-P17-002",parentTask:"WBV2-P17-001",operation:"OBJECT_DUPLICATE_ENGINE_RECEIPT",status:"done",enablingTask:false,parityStateChange:true,runtime:"PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM",artifacts,assertions:{exactInventoryBindings:1,boundInventoryIds:["operator:object.duplicate"],distinctObjectCreated:true,undoRedoSequential:true,malformedRejected:true,saveReopen:"EXACT",deterministic:true,representativeSliceOnly:true,fullFamilyParity:false,inventoryTotal:6900,baseInventoryPending:6618,effectivePending:6616,historicalReproduction:false},nextTask:"WBV2-P17-003"},null,2)}\n`);let q=read("docs/EXECUTION_QUEUE.md");q=q.replace(/\| 当前任务 \| `[^`]+` \|/u,"| 当前任务 | `WBV2-P17-003` |").replace(/\| parent manifest \| `[^`]+` \|/u,"| parent manifest | `tests/golden/WBV2-P17-002/manifest.json` |").replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u,"| 任务卡 | [`tasks/WBV2-P17-003.md`](tasks/WBV2-P17-003.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-P17-003` |").replace(/\| Current task state \| `[^`]+` \|/u,"| Current task state | `in_progress` |").replace(/\| Parent manifest \| `[^`]+` \|/u,"| Parent manifest | `tests/golden/WBV2-P17-002/manifest.json` |").replace(/\| Current task card \| `[^`]+` \|/u,"| Current task card | `docs/tasks/WBV2-P17-003.md` |").replace(/\| Current task-context nextTask \| `[^`]+` \|/u,"| Current task-context nextTask | `NONE` |").replace(/\| Focused command \| `[^`]+` \|/u,"| Focused command | `node tools/web/generate-wbv2-object-gate.mjs --write` |");fs.writeFileSync(abs("nextTask.md"),n);console.log("wbv2-object-receipt-written task=WBV2-P17-002 binding=operator:object.duplicate revisions=SEQUENTIAL malformed=REJECTED saveReopen=EXACT deterministic=true next=WBV2-P17-003");
|
||||
23
tools/web/generate-wbv2-object-root.mjs
Normal file
23
tools/web/generate-wbv2-object-root.mjs
Normal file
@@ -0,0 +1,23 @@
|
||||
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 absolute = (file) => path.join(root, file); const read = (file) => fs.readFileSync(absolute(file), "utf8"); const json = (file) => JSON.parse(read(file)); const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
||||
const p16ManifestPath = "tests/golden/WBV2-P16-003/manifest.json"; const p16ReportPath = "tests/golden/WBV2-P16-003/paint-gate-report.json"; const p16StatusPath = "docs/status/WBV2-P16-003.md"; const rootDir = "tests/golden/WBV2-P17-000"; const planPath = `${rootDir}/object-task-plan.json`; const reportPath = `${rootDir}/object-root-report.json`; const manifestPath = `${rootDir}/manifest.json`; const statusPath = "docs/status/WBV2-P17-000.md"; const inventoryPath = "tests/golden/WBV2-P0-002/parity-map.json"; const sourceApiPath = "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"; const sourceClientPath = "web/app/src/engine-client/WebEngineClient.ts";
|
||||
const p16 = json(p16ManifestPath); const p16Report = json(p16ReportPath); const inventory = json(inventoryPath); assert.equal(p16.task, "WBV2-P16-003"); assert.equal(p16.status, "done"); assert.ok(p16.nextTask === null || p16.nextTask === "WBV2-P17-000"); assert.equal(p16Report.status, "PASS"); assert.equal(p16Report.decision.effectivePending, 6616); assert.equal(inventory.summary.inventoryEntries, 6900); for (const artifact of Object.values(p16.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path); assert.match(read(sourceApiPath), /duplicateObject/); assert.match(read(sourceClientPath), /applyCommand/);
|
||||
const tasks = [
|
||||
{ id: "WBV2-P17-000", phase: "P17", title: "authorize_object_operations_continuation", kind: "enabling", owner: "PROGRAM", dependsOn: ["WBV2-P16-003"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p17-governance", gate: "G2", card: "docs/tasks/WBV2-P17-000.md", behavior: "Authorize one Object Operations behavior after the P16 paint overlay.", outputs: ["continuation root", "candidate scope", "hash boundary"], acceptance: ["P16 overlay remains hash-bound", "duplicateObject API is present", "one production task is active"], status: "done", ready: false, queueMutationAllowed: true },
|
||||
{ id: "WBV2-P17-001", phase: "P17", title: "select_object_duplicate_batch", kind: "enabling", owner: "PARITY", dependsOn: ["WBV2-P17-000"], parityId: "OBJECT_OPERATIONS.DUPLICATE", implementationClass: "LOCAL_BOUNDED", parallelGroup: "p17-selection", gate: "G2", card: "docs/tasks/WBV2-P17-001.md", behavior: "Select the duplicateObject behavior and one exact legacy operator binding.", outputs: ["candidate report", "behavior hash", "dedupe key"], acceptance: ["source command is hash-bound", "existing Scene/Object evidence is not rerun", "candidate remains one behavior"], status: "in_progress", ready: true, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P17-002", phase: "P17", title: "object_duplicate_engine_receipt", kind: "feature", owner: "OBJECT", dependsOn: ["WBV2-P17-001"], parityId: "OBJECT_OPERATIONS.DUPLICATE", implementationClass: "LOCAL_EXACT", parallelGroup: "p17-object", gate: "G2", card: "docs/tasks/WBV2-P17-002.md", behavior: "Bind duplicateObject, undo/redo, malformed rejection, and exact save/reopen to compiled WASM Main in Chromium.", outputs: ["object production report", "object receipt", "manifest"], acceptance: ["duplicate creates a distinct object", "undo/redo revisions are sequential", "malformed object ID fails closed", "save/reopen is exact"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P17-003", phase: "P17", title: "close_object_duplicate_gate", kind: "enabling", owner: "RELEASE", dependsOn: ["WBV2-P17-002"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p17-release", gate: "G5", card: "docs/tasks/WBV2-P17-003.md", behavior: "Close the duplicateObject gate and graduate only the exact operator binding.", outputs: ["object gate", "completion overlay", "manifest"], acceptance: ["only duplicateObject is claimed", "inventory remainder remains explicit", "no duplicate validation or historical over-claim"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
];
|
||||
const plan = { schemaVersion: 1, planId: "BLENDER_WEB_PARITY_V2_OBJECT_EPOCH_1", status: "ACTIVE_OBJECT_QUEUE", authority: "queue_reactivated_after_p16_paint_gate", sourcePlan: "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", executionPointer: "docs/EXECUTION_QUEUE.md", runtimePolicy: { blenderSource: "blender-5.2.0", browserEvidence: ["chromium"], forbiddenBrowsers: ["firefox", "webkit"], mainAuthority: "blender_main", reusePolicy: "source_hash_and_behavior_hash_deduplication" }, parentPaint: { manifest: p16ManifestPath, report: p16ReportPath, basePending: 6618, effectivePending: 6616, duplicateValidationAvoided: true }, tasks };
|
||||
fs.mkdirSync(absolute(rootDir), { recursive: true }); fs.writeFileSync(absolute(planPath), `${JSON.stringify(plan, null, 2)}\n`); const report = { schemaVersion: 1, task: "WBV2-P17-000", operation: "AUTHORIZE_OBJECT_OPERATIONS_CONTINUATION", status: "PASS", parent: { task: p16.task, manifest: p16ManifestPath, manifestSha256: sha256(p16ManifestPath), report: p16ReportPath, reportSha256: sha256(p16ReportPath), previousDecision: p16Report.decision.status, effectivePending: 6616 }, continuation: { root: "WBV2-P17-000", firstTask: "WBV2-P17-001", plannedTasks: 4, candidate: "OBJECT_OPERATIONS.DUPLICATE", sourceApi: sourceApiPath, browser: "chromium", noRepeatedExecution: true }, policy: { p16EvidencePreserved: true, sourceHistoryReadOnly: true, representativeSliceOnly: true, duplicateValidationAvoided: true, authorizedRebaselineOnly: true, fullHistoricalReproduction: false }, nextTask: "WBV2-P17-001" }; fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
|
||||
const cards = { "WBV2-P17-001": `# WBV2-P17-001: select_object_duplicate_batch\n\n- task: WBV2-P17-001\n- parent: WBV2-P17-000\n- status: in_progress\n- gap: capability:OBJECT_OPERATIONS.DUPLICATE\n- ownerFamily: PARITY\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nSelect the duplicateObject behavior and one exact legacy operator binding.\n\n## 输入与范围\n\n- Focused source: \`blender-5.2.0/source/blender/web_engine/web_engine_api.cpp\`\n- Existing client: \`web/app/src/engine-client/WebEngineClient.ts\`\n- Inventory: \`tests/golden/WBV2-P0-002/parity-map.json\`\n- Production entrypoint: \`node tools/web/generate-wbv2-object-selection.mjs --write\`\n\n## 验收\n\n- source command is hash-bound\n- existing Scene/Object visibility and transform evidence is not rerun\n- candidate remains one behavior\n- malformed, hash-drift, unsupported, or false-completion input keeps in_progress\n- \`node tools/web/check-task-context.mjs --task WBV2-P17-001 --write\`\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P17-001/\`\n- Status: \`docs/status/WBV2-P17-001.md\`\n- Manifest: \`tests/golden/WBV2-P17-001/manifest.json\`\n- Rollback: restore P17-000 as queue parent.\n`, "WBV2-P17-002": `# WBV2-P17-002: object_duplicate_engine_receipt\n\n- task: WBV2-P17-002\n- parent: WBV2-P17-001\n- status: planned\n- gap: capability:OBJECT_OPERATIONS.DUPLICATE\n- ownerFamily: OBJECT\n- targetImplementationClass: LOCAL_EXACT\n\n## 目标\n\nBind duplicateObject, undo/redo, malformed rejection, and exact save/reopen to compiled WASM Main in Chromium.\n\n## 输入与范围\n\n- Focused source: \`tests/golden/WBV2-P17-001/object-selection-report.json\`\n- Production test: \`web/tests/e2e/wbv2-object-duplicate-production.spec.ts\`\n- Production entrypoint: \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-object-duplicate-production.spec.ts\`\n\n## 验收\n\n- duplicate creates a distinct object\n- undo/redo revisions are sequential\n- malformed object ID fails closed without Main mutation\n- save/reopen is exact and deterministic\n- Chromium is the only browser\n- \`node tools/web/check-task-context.mjs --task WBV2-P17-002 --write\`\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P17-002/\`\n- Status: \`docs/status/WBV2-P17-002.md\`\n- Manifest: \`tests/golden/WBV2-P17-002/manifest.json\`\n- Rollback: restore P17-001 as queue parent.\n`, "WBV2-P17-003": `# WBV2-P17-003: close_object_duplicate_gate\n\n- task: WBV2-P17-003\n- parent: WBV2-P17-002\n- status: planned\n- gap: workflow:close_object_duplicate_gate\n- ownerFamily: RELEASE\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nClose the duplicateObject gate and graduate only the exact operator binding.\n\n## 输入与范围\n\n- Focused receipt: \`tests/golden/WBV2-P17-002/object-duplicate-receipt-report.json\`\n- Paint overlay: \`tests/golden/WBV2-P16-003/inventory-completion-overlay.json\`\n- Production entrypoint: \`node tools/web/generate-wbv2-object-gate.mjs --write\`\n\n## 验收\n\n- only duplicateObject is claimed\n- effective pending remains explicit\n- duplicate validation remains zero\n- malformed, hash-drift, unsupported, or false-completion input keeps in_progress\n- historical reproduction remains false\n- \`node tools/web/check-task-context.mjs --task WBV2-P17-003 --write\`\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P17-003/\`\n- Status: \`docs/status/WBV2-P17-003.md\`\n- Manifest: \`tests/golden/WBV2-P17-003/manifest.json\`\n- Rollback: restore P17-002 as queue parent.\n` };
|
||||
for (const [id, card] of Object.entries(cards)) fs.writeFileSync(absolute(`docs/tasks/${id}.md`), `${card}\n`); fs.writeFileSync(absolute(statusPath), `# WBV2-P17-000 status\n\n- task: \`WBV2-P17-000\`; parent: \`WBV2-P16-003\`; status: \`done\`\n- candidate: \`OBJECT_OPERATIONS.DUPLICATE\`; source API is present\n- effective inventory carried forward: \`283\` completed, \`6616\` pending\n- duplicate validation: \`forbidden\`; representative slice only\n- nextTask: \`WBV2-P17-001\`\n`);
|
||||
p16Report.nextTask = "WBV2-P17-000"; p16Report.policy = { ...(p16Report.policy ?? {}), terminalQueuePointer: false, authorizedContinuation: "WBV2-P17-000" }; fs.writeFileSync(absolute(p16ReportPath), `${JSON.stringify(p16Report, null, 2)}\n`); const p16Status = read(p16StatusPath).trim(); fs.writeFileSync(absolute(p16StatusPath), p16Status.includes("authorized continuation") ? `${p16Status}\n` : `${p16Status}\n- authorized continuation: \`WBV2-P17-000\`\n\nObject Operations may continue under a new root without changing the P16 paint overlay.\n`); p16.nextTask = "WBV2-P17-000"; p16.continuation = { authorized: true, root: "WBV2-P17-000", scope: "OBJECT_OPERATIONS_DUPLICATE" }; fs.writeFileSync(absolute(p16ManifestPath), `${JSON.stringify(p16, null, 2)}\n`); execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P16-003", "--write"], { cwd: root, stdio: "pipe" }); p16.artifacts = Object.fromEntries(Object.entries(p16.artifacts).map(([name, artifact]) => [name, { ...artifact, sha256: sha256(artifact.path) }])); fs.writeFileSync(absolute(p16ManifestPath), `${JSON.stringify(p16, null, 2)}\n`); report.parent.manifestSha256 = sha256(p16ManifestPath); report.parent.reportSha256 = sha256(p16ReportPath); fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
|
||||
const artifactPaths = { parentManifest: p16ManifestPath, parentReport: p16ReportPath, inventory: inventoryPath, sourceApi: sourceApiPath, sourceClient: sourceClientPath, plan: planPath, report: reportPath, rootCard: "docs/tasks/WBV2-P17-000.md", rootStatus: statusPath }; const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }])); const manifest = { schemaVersion: 1, task: "WBV2-P17-000", parentTask: "WBV2-P16-003", operation: "AUTHORIZE_OBJECT_OPERATIONS_CONTINUATION", status: "done", enablingTask: true, parityStateChange: false, runtime: "READ_ONLY_OBJECT_CONTINUATION_ROOT", artifacts, assertions: { p16EvidencePreserved: true, sourceApiBound: true, inventoryTotal: 6900, effectiveCompleted: 283, effectivePending: 6616, duplicateValidationAvoided: true, representativeSliceOnly: true, authorizedRebaselineOnly: true, fullHistoricalReproduction: false }, nextTask: "WBV2-P17-001" }; fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", absolute(planPath)], { cwd: root, stdio: "inherit" }); let queue = read("docs/EXECUTION_QUEUE.md"); queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P17-001` |").replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P17-000/manifest.json` |").replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P17-001.md`](tasks/WBV2-P17-001.md) |"); fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue); let nextTask = read("nextTask.md"); nextTask = nextTask.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P17-001` |").replace(/\| Current task state \| `[^`]+` \|/u, "| Current task state | `in_progress` |").replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P17-000/manifest.json` |").replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P17-001.md` |").replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `WBV2-P17-002` |").replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `node tools/web/generate-wbv2-object-selection.mjs --write` |"); fs.writeFileSync(absolute("nextTask.md"), nextTask); process.stdout.write("wbv2-object-root-written root=WBV2-P17-000 next=WBV2-P17-001 candidate=OBJECT_OPERATIONS.DUPLICATE effectivePending=6616\n");
|
||||
8
tools/web/generate-wbv2-object-selection.mjs
Normal file
8
tools/web/generate-wbv2-object-selection.mjs
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user