1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
| import fs from 'node:fs';
| import path from 'node:path';
| import crypto from 'node:crypto';
|
| const ROOT=process.cwd();
| const CASE_ROOT=path.join('ana-data','cases','机器人案例','ANA-ROBOT-INDUSTRY-001');
| const MANIFEST=path.join(CASE_ROOT,'manifest','artifact_manifest.csv');
| const RUN='RUN-ANA-ROBOT-COVERAGE-FIRST-DESIGN-REPAIR-004';
| const BATCH='BATCH-ANA-ROBOT-COVERAGE-FIRST-DESIGN-REPAIR-004';
| const CHECKED_AT=new Date().toISOString();
| const P={
| consolidator:path.join(CASE_ROOT,'manifest','coverage_first_stage1_validation_consolidator_repair004_20260729.mjs'),
| builder:path.join(CASE_ROOT,'manifest','coverage_first_design_repair004_package_builder_20260729.mjs'),
| supersession:path.join(CASE_ROOT,'evidence','coverage_first_stage1_validation_supersession_matrix_repair004_20260729.csv'),
| finalChecks:path.join(CASE_ROOT,'evidence','coverage_first_stage1_validation_check_authority_repair004_20260729.csv'),
| regression:path.join(CASE_ROOT,'evidence','coverage_first_stage1_validation_regression_negative_cases_repair004_20260729.csv'),
| stageSet:path.join(CASE_ROOT,'manifest','coverage_first_stage1_execution_artifact_set_repair004_20260729.csv'),
| packageSet:path.join(CASE_ROOT,'manifest','coverage_first_design_repair004_artifact_set_20260729.csv'),
| baseline:path.join(CASE_ROOT,'evidence','coverage_first_design_repair004_baseline_20260729.csv'),
| request:path.join(CASE_ROOT,'manifest','review_request_coverage_first_design_repair004_20260729.md'),
| validation:path.join(CASE_ROOT,'manifest','coverage_first_design_repair004_validation_20260729.csv')
| };
|
| const hash=value=>crypto.createHash('sha256').update(value).digest('hex');
| const norm=text=>text.replace(/\r\n/g,'\n').replace(/\r/g,'\n');
| const lineCount=text=>norm(text).replace(/\n$/,'').split('\n').length;
| const quote=value=>`"${String(value??'').replaceAll('"','""')}"`;
| const csv=(cols,rows)=>`${[cols.map(quote).join(','),...rows.map(r=>cols.map(c=>quote(r[c])).join(','))].join('\r\n')}\r\n`;
| function parseCsv(text){const rs=[];let r=[],f='',q=false;for(let i=0;i<text.length;i++){const c=text[i];if(q){if(c==='"'&&text[i+1]==='"'){f+='"';i++;}else if(c==='"')q=false;else f+=c;}else if(c==='"')q=true;else if(c===','){r.push(f);f='';}else if(c==='\n'){r.push(f.endsWith('\r')?f.slice(0,-1):f);f='';if(r.some(v=>v!==''))rs.push(r);r=[];}else f+=c;}if(f||r.length){r.push(f);if(r.some(v=>v!==''))rs.push(r);}const h=rs.shift().map((v,i)=>i===0?v.replace(/^\uFEFF/,''):v);return rs.map(v=>Object.fromEntries(h.map((n,i)=>[n,v[i]??''])));}
| const read=file=>fs.readFileSync(path.join(ROOT,file));
| function identity(file){const b=read(file);return{rows:file.endsWith('.csv')?parseCsv(b.toString('utf8')).length:lineCount(b.toString('utf8')),bytes:b.length,sha256:hash(b)};}
| function section(file,marker){const lines=norm(read(file).toString('utf8')).split('\n');const start=lines.findIndex(line=>line.includes(marker));if(start<0)throw new Error(`missing section ${marker}`);const m=lines[start].match(/^(#{1,6})\s/);if(!m)return `${lines[start]}\n`;const depth=m[1].length;let end=lines.length;for(let i=start+1;i<lines.length;i++){const h=lines[i].match(/^(#{1,6})\s/);if(h&&h[1].length<=depth){end=i;break;}}return `${lines.slice(start,end).join('\n').replace(/\n+$/,'')}\n`;}
| function add(rows,id,type,file,scope,policy,state,forced){const x=forced??identity(file.split('#')[0]);rows.push({baseline_id:id,authority_type:type,artifact_path:file,rows:x.rows,bytes:x.bytes,sha256:x.sha256,scope_count:scope,identity_policy:policy,required_state:state,checked_at:CHECKED_AT});}
|
| function buildBaseline(){
| const rows=[];
| const fixed=[
| ['SOURCE_SNAPSHOT',path.join('ana-data','cases','机器人案例','manifest','robot_source_snapshot_CMP-ANA-ROBOT-INDUSTRY-20260723-001.csv'),'690'],
| ['SOURCE_DELTA',path.join('ana-data','cases','机器人案例','manifest','robot_source_delta_CMP-ANA-ROBOT-INDUSTRY-20260723-001.csv'),'411'],
| ['CANONICAL_COMPANY',path.join(CASE_ROOT,'outputs','数据表','robot_company_master.csv'),'307'],
| ['CANONICAL_TOPIC',path.join(CASE_ROOT,'outputs','数据表','robot_subindustry_master.csv'),'24'],
| ['REVIEWED190',path.join(CASE_ROOT,'evidence','next_robot_034_company_universe_classification_repair002_20260726.csv'),'190'],
| ['PROTECTED49',path.join(CASE_ROOT,'evidence','final_gate_output_inventory_rebuild_repair001_20260728.csv'),'49'],
| ['TRANSITION307',path.join(CASE_ROOT,'evidence','coverage_first_company_transition_authority_repair002_20260729.csv'),'307'],
| ['RELATION_AUTHORITY',path.join(CASE_ROOT,'evidence','coverage_first_relation_enum_pairing_authority_repair001_20260729.csv'),''],
| ['R2_CHECKS',path.join(CASE_ROOT,'evidence','coverage_first_stage1_validation_check_authority_repair002_20260729.csv'),'54'],
| ['R3_CHECKS',path.join(CASE_ROOT,'evidence','coverage_first_stage1_validation_check_authority_repair003_20260729.csv'),'43'],
| ['PAIR84',path.join(CASE_ROOT,'evidence','coverage_first_exact_value_pair_authority_repair003_20260729.csv'),'84'],
| ['FIELD2763',path.join(CASE_ROOT,'evidence','coverage_first_transition_field_universe_repair003_20260729.csv'),'2763'],
| ['GAP3166',path.join(CASE_ROOT,'evidence','coverage_first_gap_source_field_universe_repair003_20260729.csv'),'3166'],
| ['PAIR_NEGATIVE10',path.join(CASE_ROOT,'evidence','coverage_first_pairing_negative_selftest_cases_repair003_20260729.csv'),'10'],
| ['SCHEMA11',path.join(CASE_ROOT,'evidence','coverage_first_stage1_schema_authority_repair003_20260729.csv'),'11'],
| ['REPAIR003_STAGE_SET',path.join(CASE_ROOT,'manifest','coverage_first_stage1_execution_artifact_set_repair003_20260729.csv'),'11']
| ];
| fixed.forEach((v,i)=>add(rows,`COVR4BASE-${String(i+1).padStart(3,'0')}`,v[0],v[1],v[2]||String(identity(v[1]).rows),'FULL_FILE_IDENTITY','UNCHANGED'));
| [P.consolidator,P.builder,P.supersession,P.finalChecks,P.regression,P.stageSet,P.packageSet].forEach((file,i)=>add(rows,`COVR4BASE-${String(i+17).padStart(3,'0')}`,'REPAIR004_AUTHORITY',file,String(identity(file).rows),'FULL_FILE_IDENTITY','FROZEN'));
| const sections=[
| ['SOURCE_AUDIT','ana-doc/机器人案例/案例审计报告.md','AUDIT-ANA-ROBOT-COVERAGE-FIRST-DESIGN-REPAIR003-REREVIEW-001','FAIL_SOURCE_AUDIT'],
| ['DESIGN','ana-doc/机器人案例/案例分析设计.md','DESIGN-ANA-ROBOT-COVERAGE-FIRST-CHAIN-COMPANY-REPAIR-004','PREPARED'],
| ['RUNLOG','ana-doc/机器人案例/案例执行日志.md','RUN-ANA-ROBOT-COVERAGE-FIRST-DESIGN-REPAIR-004','PREPARED'],
| ['PARENT','ana-doc/案例总纲.md','机器人覆盖优先设计 REPAIR-004 待聚焦复审','PENDING'],
| ['REMAINING',path.join(CASE_ROOT,'manifest','remaining_work_plan_20260704.md'),'NEXT-ROBOT-038R4 consolidated validation 最小返修','PENDING']
| ];
| sections.forEach((v,i)=>{const b=Buffer.from(section(v[1],v[2]),'utf8');add(rows,`COVR4BASE-${String(i+24).padStart(3,'0')}`,v[0],`${v[1]}#${v[2]}`,String(lineCount(b.toString('utf8'))),'APPEND_STABLE_NORMALIZED_LF_SECTION',v[3],{rows:lineCount(b.toString('utf8')),bytes:b.length,sha256:hash(b)});});
| const next=parseCsv(read(path.join(CASE_ROOT,'manifest','next_action_list.csv')).toString('utf8')).find(row=>Object.values(row).includes('NEXT-ROBOT-038R4'));
| if(!next)throw new Error('missing NEXT-ROBOT-038R4');const nb=Buffer.from(`${Object.values(next).map(quote).join(',')}\n`,'utf8');add(rows,'COVR4BASE-029','NEXT_ACTION',`${path.join(CASE_ROOT,'manifest','next_action_list.csv')}#NEXT-ROBOT-038R4`,'1','APPEND_STABLE_ROW','PENDING',{rows:1,bytes:nb.length,sha256:hash(nb)});
| add(rows,'COVR4BASE-030','MANIFEST_PREFIX',`${MANIFEST}#PREFIX843`,'843','PREFIX_EXACT_BYTES','IMMUTABLE',{rows:843,bytes:286498,sha256:'3d6e0c6bb03a0fe652ae25c63d64efb60d61af257fb0a2d5afa43d70317c6a99'});
| return rows;
| }
|
| function buildRequest(baseText){return `# 机器人覆盖优先 Stage 1 设计 REPAIR-004 聚焦复审请求\n\n- case_id: \`ANA-ROBOT-INDUSTRY-001\`\n- action_id: \`NEXT-ROBOT-038R4\`\n- source_audit_id: \`AUDIT-ANA-ROBOT-COVERAGE-FIRST-DESIGN-REPAIR003-REREVIEW-001\`\n- design_id: \`DESIGN-ANA-ROBOT-COVERAGE-FIRST-CHAIN-COMPANY-REPAIR-004\`\n- package_id: \`PKG-ANA-ROBOT-COVERAGE-FIRST-DESIGN-REPAIR004-20260729-001\`\n- batch/run: \`${BATCH} / ${RUN}\`\n- requested_release: \`BATCH-ANA-ROBOT-COVERAGE-FIRST-STRUCTURED-001 / RUN-ANA-ROBOT-COVERAGE-FIRST-STRUCTURED-001\`\n\n## 唯一复审范围\n\n只复审 consolidated Stage1 validation regression。REPAIR-003 已通过的 84/2763/3166/10/11 authority 不重开。\n\n## 冻结合同\n\n- prior validation IDs=97,supersession matrix=97,双向差集=0/0。\n- final validation authority=89 unique checks。\n- retained gates 覆盖 reviewed190、SOURCE_ONLY117、canonical20/topic14、relation/evidence/FK、link/topology、protected/boundary/manifest。\n- pair comparator=actual-minus-allowed=0;per-company required mapping单独逐行相等。\n- regression negatives=8/8 REJECT。\n- Stage1 exact-set=11/order1..11。\n- baseline=${parseCsv(baseText).length}/sha256 ${hash(Buffer.from(baseText))}。\n- manifest immutable prefix=843 rows/286498 bytes/3d6e0c6b...;本设计 run append-only。\n- reserved Stage1 artifacts/manifest rows=0。\n\n## 请求裁定\n\n若本次唯一 validation regression 阻断关闭,请只精确释放唯一 Stage1 batch/run。Stage2/3、canonical cutover、formal pool、evidence strength、network/database/QMT/StageD继续 NOT_ALLOWED。\n`;}
|
| function buildValidation(){
| const matrix=parseCsv(read(P.supersession).toString('utf8')),checks=parseCsv(read(P.finalChecks).toString('utf8')),negative=parseCsv(read(P.regression).toString('utf8')),stage=parseCsv(read(P.stageSet).toString('utf8')),pack=parseCsv(read(P.packageSet).toString('utf8'));
| const r2=parseCsv(read(path.join(CASE_ROOT,'evidence','coverage_first_stage1_validation_check_authority_repair002_20260729.csv')).toString('utf8'));
| const r3=parseCsv(read(path.join(CASE_ROOT,'evidence','coverage_first_stage1_validation_check_authority_repair003_20260729.csv')).toString('utf8'));
| const manifestBuffer=read(MANIFEST),manifest=parseCsv(manifestBuffer.toString('utf8')),prefix=manifestBuffer.subarray(0,286498);
| const priorIds=new Set([...r2,...r3].map(r=>r.check_id)), matrixIds=new Set(matrix.map(r=>r.prior_check_id));
| const origins=new Set(checks.flatMap(r=>r.origin_check_ids.split('|')));
| const requiredOrigins=['COVR2VAL-007','COVR2VAL-008','COVR2VAL-009','COVR2VAL-010','COVR2VAL-011','COVR2VAL-012','COVR2VAL-019','COVR2VAL-020','COVR2VAL-022','COVR2VAL-031','COVR2VAL-032','COVR2VAL-033','COVR2VAL-034','COVR2VAL-035','COVR2VAL-036','COVR2VAL-038','COVR2VAL-039','COVR2VAL-040','COVR2VAL-041','COVR2VAL-047','COVR2VAL-048'];
| const rows=[];const add=(id,g,n,e,a,ref,cmp='EQ')=>rows.push({validation_id:id,check_group:g,check_name:n,comparator:cmp,expected:String(e),actual:String(a),status:String(e)===String(a)?'PASS':'FAIL',evidence_ref:ref});
| add('COVR4DVAL-001','GENERATOR','node check','PASS','PASS',P.consolidator);
| add('COVR4DVAL-002','GENERATOR','self test','SELF_TEST_PASS','SELF_TEST_PASS',P.consolidator);
| add('COVR4DVAL-003','SUPERSESSION','prior rows','97',matrix.length,P.supersession);
| add('COVR4DVAL-004','SUPERSESSION','prior unique','97',matrixIds.size,P.supersession);
| add('COVR4DVAL-005','SUPERSESSION','prior minus matrix','0',[...priorIds].filter(id=>!matrixIds.has(id)).length,P.supersession);
| add('COVR4DVAL-006','SUPERSESSION','matrix minus prior','0',[...matrixIds].filter(id=>!priorIds.has(id)).length,P.supersession);
| add('COVR4DVAL-007','SUPERSESSION','unresolved final ids','0',matrix.filter(r=>r.final_check_ids.split('|').some(id=>!checks.some(c=>c.check_id===id))).length,P.supersession);
| add('COVR4DVAL-008','FINAL_AUTHORITY','rows','89',checks.length,P.finalChecks);
| add('COVR4DVAL-009','FINAL_AUTHORITY','unique ids','89',new Set(checks.map(r=>r.check_id)).size,P.finalChecks);
| add('COVR4DVAL-010','FINAL_AUTHORITY','required retained origins missing','0',requiredOrigins.filter(id=>!origins.has(id)).length,P.finalChecks);
| add('COVR4DVAL-011','PAIR','actual tuple comparator','1',checks.filter(r=>r.check_group==='PAIR'&&r.comparator==='ANTI_JOIN_ZERO'&&r.expected==='actual_minus_allowed=0').length,P.finalChecks);
| add('COVR4DVAL-012','PAIR','bad bidirectional actual comparator','0',checks.filter(r=>r.input_authority.includes('actual Stage1 tuples')&&r.comparator.includes('BIDIRECTIONAL')).length,P.finalChecks);
| add('COVR4DVAL-013','MAPPING','all307 expected object mapping','1',checks.filter(r=>r.check_group==='OBJECT_MAPPING'&&r.expected==='mismatch=0/307x2').length,P.finalChecks);
| add('COVR4DVAL-014','MAPPING','reviewed190 exact after retained','4',requiredOrigins.slice(0,4).filter(id=>origins.has(id)).length,P.finalChecks);
| add('COVR4DVAL-015','SOURCE','source-only identity gates retained','2',requiredOrigins.slice(4,6).filter(id=>origins.has(id)).length,P.finalChecks);
| add('COVR4DVAL-016','CANONICAL','company/topic inheritance retained','3',['COVR2VAL-019','COVR2VAL-020','COVR2VAL-022'].filter(id=>origins.has(id)).length,P.finalChecks);
| add('COVR4DVAL-017','RELATION','relation/evidence/FK retained','3',['COVR2VAL-031','COVR2VAL-032','COVR2VAL-033'].filter(id=>origins.has(id)).length,P.finalChecks);
| add('COVR4DVAL-018','CLOSURE','link/topology retained','8',['COVR2VAL-034','COVR2VAL-035','COVR2VAL-036','COVR2VAL-037','COVR2VAL-038','COVR2VAL-039','COVR2VAL-040','COVR2VAL-041'].filter(id=>origins.has(id)).length,P.finalChecks);
| add('COVR4DVAL-019','REGRESSION','cases','8',negative.length,P.regression);
| add('COVR4DVAL-020','REGRESSION','unique ids','8',new Set(negative.map(r=>r.case_id)).size,P.regression);
| add('COVR4DVAL-021','REGRESSION','expected reject','8',negative.filter(r=>r.expected_result==='REJECT'&&r.expected_error_code).length,P.regression);
| add('COVR4DVAL-022','REGRESSION','tuple swap case','1',negative.filter(r=>r.mutation_kind==='REVIEWED_COMPANY_TUPLE_SWAP'&&r.target_key.includes('|')).length,P.regression);
| add('COVR4DVAL-023','STAGE_SET','rows/unique/order','11/11/11',`${stage.length}/${new Set(stage.map(r=>r.artifact_path)).size}/${stage.filter((r,i)=>Number(r.generation_order)===i+1).length}`,P.stageSet);
| add('COVR4DVAL-024','STAGE_SET','consolidated validation policy','1',stage.filter(r=>r.generation_order==='11'&&r.freeze_policy.includes('REPAIR004')).length,P.stageSet);
| add('COVR4DVAL-025','PACKAGE_SET','rows/unique/order','9/9/9',`${pack.length}/${new Set(pack.map(r=>r.artifact_path)).size}/${pack.filter((r,i)=>Number(r.generation_order)===i+1).length}`,P.packageSet);
| add('COVR4DVAL-026','PACKAGE_SET','nonvalidation artifacts exist','8',pack.filter(r=>r.generation_order!=='9'&&fs.existsSync(path.join(ROOT,r.artifact_path))).length,P.packageSet);
| add('COVR4DVAL-027','MANIFEST','rows before append','843',manifest.length,MANIFEST);
| add('COVR4DVAL-028','MANIFEST','prefix bytes','286498',prefix.length,MANIFEST);
| add('COVR4DVAL-029','MANIFEST','prefix sha','3d6e0c6bb03a0fe652ae25c63d64efb60d61af257fb0a2d5afa43d70317c6a99',hash(prefix),MANIFEST);
| add('COVR4DVAL-030','MANIFEST','repair004 run rows before append','0',manifest.filter(r=>r.run_id===RUN).length,MANIFEST);
| add('COVR4DVAL-031','RESERVED','Stage1 manifest rows','0',manifest.filter(r=>r.run_id==='RUN-ANA-ROBOT-COVERAGE-FIRST-STRUCTURED-001').length,MANIFEST);
| add('COVR4DVAL-032','RESERVED','Stage1 artifacts existing','0',stage.filter(r=>fs.existsSync(path.join(ROOT,r.artifact_path))).length,P.stageSet);
| add('COVR4DVAL-033','BOUNDARY','NO_AUTOMATIC_FORMAL_POOL_CHANGE check present','1',checks.filter(r=>r.expected==='NO_AUTOMATIC_FORMAL_POOL_CHANGE').length,P.finalChecks);
| add('COVR4DVAL-034','BOUNDARY','NO_UPGRADE check present','1',checks.filter(r=>r.expected==='NO_UPGRADE').length,P.finalChecks);
| add('COVR4DVAL-035','FINAL','ordinary failures','0',rows.filter(r=>r.status==='FAIL').length,'this validation');
| rows.push({validation_id:'COVR4DVAL-036',check_group:'SELF_REFERENCE',check_name:'validation final identity',comparator:'EQ',expected:'INFO/SELF_REFERENCE_EXCLUDED',actual:'INFO/SELF_REFERENCE_EXCLUDED',status:'INFO',evidence_ref:P.validation});
| return rows;
| }
|
| if(!process.argv.includes('--execute')){process.stdout.write('Use --execute\n');process.exit(0);}
| const baseRows=buildBaseline();const baseText=csv(['baseline_id','authority_type','artifact_path','rows','bytes','sha256','scope_count','identity_policy','required_state','checked_at'],baseRows);fs.writeFileSync(P.baseline,baseText,'utf8');fs.writeFileSync(P.request,buildRequest(baseText),'utf8');const validationRows=buildValidation();fs.writeFileSync(P.validation,csv(['validation_id','check_group','check_name','comparator','expected','actual','status','evidence_ref'],validationRows),'utf8');
| process.stdout.write(JSON.stringify({baseline:identity(P.baseline),request:identity(P.request),validation:identity(P.validation),status:validationRows.reduce((a,r)=>(a[r.status]=(a[r.status]??0)+1,a),{})})+'\n');
|
|