Setting the file. One moment.
Entity QA Attestation · Wix Replatform · wix/skills · Skills Docs
ContentsBack to the top of the page scripts/ entity-qa-attestation.js
JavaScript · 130 lines · 5 KB
14 // Usage:
15 // node scripts/entity-qa-attestation.js <projectDir> --entities-file <path> [--verified-by <label>]
16
17 const fs = require ( 'node:fs' );
18 const path = require ( 'node:path' );
19 const { BACKEND_COMPLETION_FILE , readMappedEntities } = require ( '../lib/migration-completion.js' );
20 const { hashArtifact } = require ( '../lib/artifact-freshness.js' );
21 const { ENTITY_QA_ATTESTATION_FILE , SCHEMA_VERSION , validateEntityQaAttestation } = require ( '../lib/entity-qa-attestation.js' );
22 const { writeJsonAtomic } = require ( '../lib/orchestration-state.js' );
23
24 function usage () {
25 console. error ( `Usage:
26 node skills/wix-replatform/scripts/entity-qa-attestation.js <projectDir> --entities-file <path> [--verified-by <label>]
27
28 Reads the QA subagent's per-entity results from --entities-file (a JSON array; full-mode rows
29 carry the ten completion-report fields, quick-mode rows carry imported/skipped), computes the
30 digest of <projectDir>/execution/completion-report.json itself, resolves the independent
31 mapped-entity coverage source by mode, and writes <projectDir>/execution/qa/entity-qa-attestation.json
32 ONLY if the result validates. A count mismatch or any other gate failure is printed as a
33 finding and the script exits non-zero without writing the file.
34 ` );
35 }
36
37 function parseArgs ( argv ) {
38 const positional = [];
39 const options = { entitiesFile: null , verifiedBy: 'qa-subagent' };
40 for ( let i = 0 ; i < argv. length ; i += 1 ) {
41 const arg = argv[i];
42 if (arg === '--entities-file' ) {
43 options.entitiesFile = argv[i + 1 ];
44 i += 1 ;
45 } else if (arg === '--verified-by' ) {
46 options.verifiedBy = argv[i + 1 ];
47 i += 1 ;
48 } else {
49 positional. push (arg);
50 }
51 }
52 return { projectDir: positional[ 0 ], ... options };
53 }
54
55 function readJsonFile ( filePath , label ) {
56 let raw;
57 try {
58 raw = fs. readFileSync (filePath, 'utf8' );
59 } catch (error) {
60 throw new Error ( `${ label } not found at ${ filePath }: ${ error . message }` );
61 }
62 try {
63 return JSON . parse (raw);
64 } catch (error) {
65 throw new Error ( `${ label } at ${ filePath } is not valid JSON: ${ error . message }` );
66 }
67 }
68
69 function printFindings ( result ) {
70 if (result.entities && result.entities. length ) {
71 for ( const entry of result.entities) {
72 console. error ( `${ entry . entity }/${ entry . subtype }: ${ entry . reasons . join ( ', ' ) }` );
73 }
74 } else {
75 for ( const reason of result.reasons) {
76 console. error (reason);
77 }
78 }
79 }
80
81 async function main () {
82 const { projectDir : projectDirArg , entitiesFile , verifiedBy } = parseArgs (process.argv. slice ( 2 ));
83 if ( ! projectDirArg || ! entitiesFile) {
84 usage ();
85 process. exit ( 1 );
86 return ;
87 }
88 const projectDir = path. resolve (projectDirArg);
89
90 const report = readJsonFile (path. join (projectDir, BACKEND_COMPLETION_FILE ), 'completion report' );
91 const entities = readJsonFile (path. resolve (entitiesFile), 'entities file' );
92 if ( ! Array. isArray (entities)) {
93 throw new Error ( `--entities-file must contain a JSON array of per-entity rows: ${ entitiesFile }` );
94 }
95
96 const managementImportMode = report.managementImportMode === 'quick' ? 'quick' : 'full' ;
97 const mappedEntities = await readMappedEntities (projectDir, managementImportMode);
98 const completionReportDigest = hashArtifact (projectDir, BACKEND_COMPLETION_FILE );
99
100 const attestation = {
101 schemaVersion: SCHEMA_VERSION ,
102 completionReportDigest,
103 verifiedAt: new Date (). toISOString (),
104 verifiedBy,
105 entities,
106 };
107
108 const result = validateEntityQaAttestation ({
109 attestation,
110 report,
111 reportDigest: completionReportDigest,
112 mappedEntities,
113 });
114
115 if ( ! result.ok) {
116 console. error ( JSON . stringify ({ ok: false , qaStatus: result.qaStatus, projectDir }, null , 2 ));
117 printFindings (result);
118 process. exit ( 1 );
119 return ;
120 }
121
122 const outputPath = path. join (projectDir, ENTITY_QA_ATTESTATION_FILE );
123 await writeJsonAtomic (outputPath, attestation);
124 console. log ( JSON . stringify ({ ok: true , outputPath, qaStatus: result.qaStatus }, null , 2 ));
125 }
126
127 main (). catch (( error ) => {
128 console. error (error && error.message ? error.message : error);
129 process. exit ( 1 );
130 });