| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- // Read-only verification of the recovered material and the next S1 report input.
- import fs from 'node:fs';
- import crypto from 'node:crypto';
- import assert from 'node:assert/strict';
- import {invoke,classRows} from '../server/scripts/platform-client.mjs';
- const file='work/first-live-S1-v2-template.json';
- const task=JSON.parse(fs.readFileSync(file,'utf8'));
- const sessionId='btrFqkz0yw',previousArtifactId='cOm6c8gg7z';
- const productId='-KbX0Agka-',sourceId='McdwhD7KQq',categoryId='Mc9FJpryn4';
- const evidenceIds=['Cjt9C6V-sF','PkIMIDs38u','za6VI7Xdjh'];
- const requestId='KSF-真实资料-20261102-01:S1:save:v2';
- const hash=x=>crypto.createHash('sha256').update(x).digest('hex');
- const pointer=(className,objectId)=>({__type:'Pointer',className,objectId});
- const get=async(className,objectId)=>{
- const r=await invoke('ksfGetRecord',{className,objectId});
- assert.equal(r.http,200);assert.equal(r.body?.result?.ok,true);
- return r.body.result.data.record;
- };
- try{
- assert.equal(task.sessionId,null);assert.equal(task.version,2);assert.equal(task.stageCode,'S1');
- assert.equal(task.taskKey,'KSF-真实资料-20261102-01:S1');
- assert.deepEqual(task.sourceIds,['BgUB6dnxN1','SFiKA0D7n9',sourceId]);
- assert.equal(task.pendingQuestions.length,6);assert.equal(task.opportunity,undefined);assert.equal(task.projectId,undefined);
- const [session,previous,product,category,origins,evidence,history,operations,products]=await Promise.all([
- get('KfSession',sessionId),get('KfArtifact',previousArtifactId),get('KfProduct',productId),get('KfCategory',categoryId),
- Promise.all(task.sourceIds.map(id=>get('KfSource',id))),Promise.all(evidenceIds.map(id=>get('KfEvidence',id))),
- classRows('KfArtifact',{workshopKey:'KSF-真实资料-20261102-01'}),
- classRows('KsfOperation',{operation:'workshop-task',requestId}),
- classRows('KfProduct',{sourceRef:pointer('KfSource',sourceId)})
- ]);
- assert.equal(session.dataMode,'live');assert.equal(previous.version,1);assert.equal(previous.reportSeriesKey,task.taskKey);
- assert.equal(previous.sessionRef?.objectId,sessionId);assert.equal(previous.dashboardState,'workshop');
- assert.equal(session.meta.attribution.agentKey,previous.meta.attribution.agentKey);
- assert.equal(session.meta.attribution.participantKey,previous.meta.attribution.participantKey);
- assert.equal(history.filter(a=>a.reportSeriesKey===task.taskKey&&a.version===2).length,0,'V2_ALREADY_EXISTS');
- assert.equal(operations.length,0,'REQUEST_ALREADY_EXISTS');
- assert.equal(category.code,'KSF-RESEARCH-INSTANT-MIXED-NOODLES-V1');
- assert.equal(category.updatedAt,'2026-11-02T07:12:09.338Z');
- assert.equal(product.categoryRef?.objectId,categoryId);assert.equal(product.sourceRef?.objectId,sourceId);
- assert.equal(product.productLevel,'product_line');assert.equal(product.isOwnBrand,true);assert.equal(product.dataMode,'live');
- assert.equal(products.length,1);assert.equal(products[0].objectId,productId);
- let quoteCount=0;
- for(const entry of Object.values(task.report.evidence)){
- const origin=origins.find(o=>o.objectId===entry.sourceId);assert.ok(origin);assert.equal(origin.dataMode,'live');
- assert.equal(hash(origin.rawText),origin.contentHash);
- for(const q of entry.quotes){assert.ok(origin.rawText.includes(q.text));quoteCount++;}
- }
- assert.equal(quoteCount,5);
- const ksf=origins.find(o=>o.objectId===sourceId);
- const reportQuotes=task.report.evidence['ksf-brand-statement'].quotes;
- evidence.forEach((e,i)=>{
- assert.equal(e.objectId,evidenceIds[i]);assert.equal(e.sourceRef?.objectId,sourceId);assert.equal(e.productRef?.objectId,productId);
- assert.equal(e.evidenceKind,'official_brand_statement');assert.equal(e.dataMode,'live');
- assert.equal(e.quote,reportQuotes[i].text);
- assert.equal(Array.from(ksf.rawText).slice(e.locator.startCharacter,e.locator.endCharacter).join(''),e.quote);
- });
- const result={ok:true,operation:'live-S1-v2-input-readonly-verified',at:new Date().toISOString(),readOnly:true,businessWrites:0,
- sessionId,previousArtifactId,taskKey:task.taskKey,nextVersion:2,requestId,requestHistoryMatches:operations.length,
- productId,categoryId,sourceIds:task.sourceIds,evidenceIds,linkedProductCount:products.length,reportQuoteCount:quoteCount,
- previousVersionPreserved:true,privateAttributionMatched:true,templateSha256:hash(fs.readFileSync(file)),
- targetSaved:false,browserVerified:false};
- fs.writeFileSync('work/first-live-S1-v2-input-check.json',JSON.stringify(result,null,2)+'\n');
- console.log(JSON.stringify(result,null,2));
- }catch{
- console.error(JSON.stringify({ok:false,error:'LIVE_S1_V2_INPUT_CHECK_STOPPED',readOnly:true,businessWrites:0}));
- process.exitCode=1;
- }
|