Files
SGF/scripts/summarize-purchasing-continuity.mjs
2026-11-04 09:37:20 +02:00

9 lines
6.5 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,readTag,demoTag]=process.argv.slice(2);assert([qaTag,readTag,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),reader=path.join(run.root,'private/purchasing-continuity-read-'+readTag),demo=path.join(run.root,'private/receipt-composition-'+demoTag),priorDemo=path.join(run.root,'private/receipt-composition-0275f83f7456'),read=p=>JSON.parse(fs.readFileSync(p,'utf8')),hash=p=>crypto.createHash('sha256').update(fs.readFileSync(p)).digest('hex'),digest=text=>crypto.createHash('sha256').update(text).digest('hex'),tests={};
for(const [name,base,file,count]of [['real_ui',qa,'receipt-ui-http.json',17],['boundaries',qa,'continuity-boundaries.json',8],['history',reader,'purchasing-continuity-read-result.json',12],['inline_ui',qa,'continuity-ui.json',9],['demo',demo,'purchasing-continuity-demo.json',9]]){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};}assert.equal(tests.history.result.before_sha256,tests.history.result.after_sha256);assert.equal(tests.history.result.tables_checked,142);
const files=['app/Modules/Purchasing/ProcessHistory.php','app/Modules/Purchasing/RequestController.php','app/Modules/Purchasing/SourcingController.php','app/Modules/Purchasing/ReceiptController.php','config/receipt_qa.php','public/purchasing-focus.mjs',...['receipt-workspace','supplier-invoice-workspace','supplier-obligation-workspace'].flatMap(n=>['public/'+n+'.mjs','resources/views/'+n+'.blade.php'])];for(const base of [qa,reader,demo])for(const file of files)assert.equal(hash(path.join(base,'app',file)),hash(file),file);
const mutationBlocks=[];for(const name of ['RequestController','SourcingController','ReceiptController']){const file='app/Modules/Purchasing/'+name+'.php',old=fs.readFileSync(path.join(priorDemo,'app',file),'utf8'),now=fs.readFileSync(file,'utf8'),tail=t=>{const at=t.indexOf('public function preview(');assert(at>=0);return t.slice(at);};assert.equal(tail(old),tail(now));mutationBlocks.push({file,sha256:digest(tail(now)),unchanged_since_demo8078:true});}for(const name of ['InvoiceController','ObligationController']){const file='app/Modules/Purchasing/'+name+'.php';assert.equal(hash(file),hash(path.join(priorDemo,'app',file)));assert.equal(hash(file),hash(path.join(demo,'app',file)));}
const readState=read(path.join(reader,'state.json')),pins=[];for(const base of [qa,readState.original_root,demo]){const p={};for(const dir of ['bundle','economic','internal']){p[dir]=hash(path.join(base,dir,'manifest.json'));for(const [file,h]of Object.entries(read(path.join(base,dir,'manifest.json')).files))assert.equal(hash(path.join(base,dir,file)),h);}pins.push(p);}assert.deepEqual(pins[0],pins[1]);assert.deepEqual(pins[0],pins[2]);assert.deepEqual(pins[0],read('docs/proofs/purchasing-focus-composition-20261103.json').pinned_native_manifests);
const previous=['docs/proofs/purchasing-focus-composition-20261103.json','docs/proofs/receipt-workspace-completion-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 count=Object.values(tests).reduce((n,t)=>n+t.checks,0);assert.equal(count,55);const out='docs/proofs/purchasing-continuity-composition-20261103.json';assert(!fs.existsSync(out));fs.writeFileSync(out,JSON.stringify({date:new Date().toISOString(),increment:'SGF-PURCHASING-USABLE-CONTINUITY-QA-v1',passed:true,functional_code:true,checks:count,tests,sources:files.map(file=>({file,sha256:hash(file)})),pinned_native_manifests:pins[0],unchanged_mutation_blocks:mutationBlocks,authority:{new_right_names:[],new_business_writers:0,inline_links_use_present_menu_as_presentation_hint:true,destination_api_remains_authority:true,stage_history_filtered_in_sql_before_pagination:true,original_audit_records_preserved:true},regression:{receipt_form_uses_real_http:true,dom_simulation_not_browser:true,explicit_article_choice_and_revision:true,receipt_count:1,physical_quantity_milli:1000,physical_movements:1,lost_response_statuses:[201,200],new_concurrency_trial:false,additional_open_request_fixture_minor:100,history_uses_completed_canonical_book_without_commands:true,tables_and_sequences_preserved:142,prior_suites_not_repeated:true},demo:{port:8079,entry:'http://127.0.0.1:8079/qa/enter/requester?open=1',warehouse:'http://127.0.0.1:8079/qa/enter/validator?open=1',finance:'http://127.0.0.1:8079/qa/enter/issuer?open=1',initial_main_requests:0,initial_receipts:0,initial_invoices:0,initial_obligations: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:['DOM-to-real-HTTP validation is functional evidence, not browser rendering, accessibility or visual acceptance.','The lost-response recovery is sequential201/200, not a new concurrency measurement. Existing valid concurrency proofs are retained.','The additional1MZN open request is targeted supplier-picker fixture preparation, not another full order or payable cycle.','Menu visibility controls presentation only; a stale or modified menu cannot grant destination API authority.','Request direct history remains its latest25 own-stage events. Sourcing remains paginated; the dossier keeps independently filtered transversal evidence.','No new React/Vite build: affected UI is served as static ES modules and Blade views. Syntax and served hashes of the affected modules are checked; prior valid React build proof is retained.','Sustained load, visual review, general installation and deployment capacity remain pending.'],visual_review_pending:true,deployment_capacity_validated:false},null,2)+'\n');console.log(JSON.stringify({output:out,checks:count,demo_port:8079}));