9 lines
5.6 KiB
JavaScript
9 lines
5.6 KiB
JavaScript
import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto';import assert from 'node:assert/strict';
|
|
const [qaTag,demoTag]=process.argv.slice(2);assert([qaTag,demoTag].every(t=>/^[a-f0-9]{12}$/.test(t??'')));const run=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')),qa=path.join(run.root,'private/receipt-composition-'+qaTag),demo=path.join(run.root,'private/receipt-composition-'+demoTag),read=p=>JSON.parse(fs.readFileSync(p,'utf8')),hash=p=>crypto.createHash('sha256').update(fs.readFileSync(p)).digest('hex'),tests={};
|
|
for(const [name,base,file,count]of [['receipt_boundary',qa,'receipt-workspace-result.json',27],['guards',demo,'receipt-workspace-guards.json',4],['demo',demo,'receipt-workspace-demo.json',6],['assets',demo,'receipt-workspace-assets.json',3],['final_source',demo,'receipt-workspace-final-source.json',1]]){const p=path.join(base,file),r=read(p);assert(r.passed);assert.equal(r.checks.length,count);tests[name]={file:'private/'+path.basename(base)+'/'+file,sha256:hash(p),checks:count,result:r};}
|
|
const files=['app/Modules/Purchasing/ReceiptController.php','app/Modules/Purchasing/ReceiptCatalogue.php','app/Modules/Purchasing/ReceiptRuntime.php','public/receipt-workspace.mjs','public/supplier-picker-model.mjs','routes/web.php'];for(const base of [qa,demo])for(const f of files)assert.equal(hash(path.join(base,'app',f)),hash(f),f);
|
|
const pins=[];for(const base of [qa,demo]){const p={};for(const dir of ['bundle','economic','internal']){p[dir]=hash(path.join(base,dir,'manifest.json'));for(const [f,h]of Object.entries(read(path.join(base,dir,'manifest.json')).files))assert.equal(hash(path.join(base,dir,f)),h);}pins.push(p);}assert.deepEqual(pins[0],pins[1]);assert.deepEqual(pins[0],read('docs/proofs/purchasing-dossier-composition-20261103.json').pinned_native_manifests);
|
|
function inventoryFiles(base,relative='packages/inventory-write'){return fs.readdirSync(path.join(base,relative),{withFileTypes:true}).flatMap(entry=>{const f=relative+'/'+entry.name;return entry.isDirectory()?inventoryFiles(base,f):[{file:f,sha256:hash(path.join(base,f))}];});}const inventory=inventoryFiles(path.join(qa,'app'));assert.deepEqual(inventory,inventoryFiles(path.join(demo,'app')));
|
|
const previous=['docs/proofs/purchasing-dossier-composition-20261103.json','docs/proofs/purchasing-integrated-composition-20261103.json','docs/proofs/supplier-search-composition-20261103.json','docs/proofs/module-association-consolidation-summary-20261102.json'].map(file=>({file,sha256:hash(file)})),assoc=read(previous.at(-1).file);assert.equal(hash('app/Modules/Identity/Services/ModuleAssociationReview.php'),assoc.source_sha256);assert.equal(hash('app/Modules/Identity/Http/ModuleRecordsController.php'),assoc.controller_sha256);assert.equal(hash('packages/purchasing/current.json'),read(previous[0].file).preservation.installed_purchasing_sha256);
|
|
const checks=Object.values(tests).reduce((n,t)=>n+t.checks,0);assert.equal(checks,41);const out='docs/proofs/receipt-workspace-completion-20261103.json';assert(!fs.existsSync(out));fs.writeFileSync(out,JSON.stringify({date:new Date().toISOString(),increment:'SGF-RECEIPT-WORKSPACE-COMPLETION-QA-v1',passed:true,functional_code:true,checks,tests,sources:files.map(file=>({file,sha256:hash(file)})),pinned_native_manifests:pins[0],matching_inventory_writer_sources:inventory,new_right_names:[],receipt_boundary:{eligible_articles:127,server_pages:[25,100],manual_choice:true,explicit_article_fingerprint_rechecked:true,receipts:27,quantity_milli:1000,history_fixture_receipts_through_original_writer:25,transport_receipts:2,concurrent_same_key:[200,201],new_payments:0,new_invoices:0,new_obligations:0,stock_valuation_added:false},demo:{port:8075,entry:'http://127.0.0.1:8075/qa/enter/requester?open=1',warehouse:'http://127.0.0.1:8075/qa/enter/validator?open=1',initial_main_requests:0,initial_orders:0,initial_receipts:0,initial_movements:0,synthetic_extra_articles:127,locations:0},prior_proofs_preserved:previous,preservation:{installed_purchasing_sha256:hash('packages/purchasing/current.json'),target_database_connected:false,protected_six_records_changed:false,blocked_cache_cleared:false,previous_demo_data_written:false,public_rights_changed:false,publication:false,checkpoint:false},limitations:['Functional consumable/UN boundary tested. Supply/part filters delegate to native services; this is not a complete new regression of those branches.','The unchanged asynchronous choice model reuses its earlier8 checks; it was not re-executed or counted as new tests.','Final UI defers catalogue requests until a line is chosen. Its final served source and syntax were checked separately; browser interaction and visual review remain pending.','Twenty-five partial receipts are explicit history-volume fixtures through the pinned original writer; only the first and last physical commands exercise the changed HTTP transport.','Legacy previews capture explicit item fingerprints server-side. The original writer remains final validator for quantity, quality, unit, bindings and physical effects.','Implicit item bindings already authorised in an order remain native authority; this increment creates no new automatic association.','New receipts and movements exist only in the regression fixture; the team demo begins empty.','No sustained-load capacity or deployment/least-privilege claim follows from127 catalogue records and27 receipts.','Current native schema provisioning and frozen runtime retain their earlier deployment compatibility limitations.'],visual_review_pending:true,deployment_capacity_validated:false},null,2)+'\n');console.log(JSON.stringify({output:out,checks,demo_port:8075}));
|