import fs from 'node:fs';
|
import path from 'node:path';
|
import crypto from 'node:crypto';
|
|
const ROOT = process.cwd();
|
const CASE = 'ANA-ROBOT-INDUSTRY-001';
|
const PACKAGE = 'PKG-ANA-ROBOT-FINAL-GATE-REBUILD-20260728-001';
|
const BATCH = 'BATCH-ANA-ROBOT-FINAL-GATE-REBUILD-001';
|
const RUN = 'RUN-ANA-ROBOT-FINAL-GATE-PACKAGE-REBUILD-001';
|
const BASE = 'ana-data/cases/机器人案例/ANA-ROBOT-INDUSTRY-001';
|
const EVIDENCE = `${BASE}/evidence`;
|
const MANIFEST = `${BASE}/manifest`;
|
const AUDIT_REPORT = 'ana-doc/机器人案例/案例审计报告.md';
|
const OLD_INVENTORY = `${EVIDENCE}/final_gate_output_inventory_repair_20260725.csv`;
|
const ARTIFACT_MANIFEST = `${MANIFEST}/artifact_manifest.csv`;
|
|
const OUTPUTS = {
|
auditAuthority: `${EVIDENCE}/final_gate_rebuild_audit_entry_authority_20260728.csv`,
|
inventory: `${EVIDENCE}/final_gate_output_inventory_rebuild_20260728.csv`,
|
baseline: `${EVIDENCE}/final_gate_rebuild_baseline_20260728.csv`,
|
readiness: `${EVIDENCE}/final_gate_readiness_matrix_rebuild_20260728.csv`,
|
sharedAuthority: `${EVIDENCE}/final_gate_rebuild_shared_record_authority_20260728.csv`,
|
artifactSet: `${MANIFEST}/final_gate_rebuild_artifact_set_20260728.csv`,
|
request: `${MANIFEST}/review_request_final_gate_rebuild_20260728.md`,
|
validation: `${MANIFEST}/final_gate_rebuild_validation_20260728.csv`,
|
};
|
const GENERATOR_PATH = `${MANIFEST}/final_gate_rebuild_generator_20260728.mjs`;
|
|
function abs(rel) { return path.join(ROOT, ...rel.split('/')); }
|
function bytes(rel) { return fs.readFileSync(abs(rel)); }
|
function text(rel) { return bytes(rel).toString('utf8'); }
|
function sha(buf) { return crypto.createHash('sha256').update(buf).digest('hex'); }
|
function fileIdentity(rel) {
|
const b = bytes(rel);
|
const t = b.toString('utf8');
|
const lines = t.length === 0 ? 0 : t.split(/\r?\n/).length - (/(?:\r?\n)$/.test(t) ? 1 : 0);
|
return { sha256: sha(b), bytes: b.length, lines };
|
}
|
function q(v) { return `"${String(v ?? '').replaceAll('"', '""')}"`; }
|
function csv(headers, rows) {
|
return [headers.map(q).join(','), ...rows.map(row => headers.map(h => q(row[h])).join(','))].join('\n') + '\n';
|
}
|
function parseCsv(raw) {
|
const rows = []; let row = []; let field = ''; let quoted = false;
|
for (let i = 0; i < raw.length; i++) {
|
const c = raw[i];
|
if (quoted) {
|
if (c === '"' && raw[i + 1] === '"') { field += '"'; i++; }
|
else if (c === '"') quoted = false;
|
else field += c;
|
} else if (c === '"') quoted = true;
|
else if (c === ',') { row.push(field); field = ''; }
|
else if (c === '\n') { row.push(field.replace(/\r$/, '')); rows.push(row); row = []; field = ''; }
|
else field += c;
|
}
|
if (field.length || row.length) { row.push(field); rows.push(row); }
|
const headers = rows.shift();
|
return rows.filter(r => r.some(v => v !== '')).map(r => Object.fromEntries(headers.map((h, i) => [h, r[i] ?? ''])));
|
}
|
function write(rel, content) {
|
fs.mkdirSync(path.dirname(abs(rel)), { recursive: true });
|
fs.writeFileSync(abs(rel), content, { encoding: 'utf8' });
|
}
|
function ensureAbsent() {
|
for (const rel of Object.values(OUTPUTS)) {
|
if (fs.existsSync(abs(rel))) throw new Error(`REFUSE_OVERWRITE:${rel}`);
|
}
|
}
|
|
const auditSpecs = [
|
['AUDIT-ANA-ROBOT-RESEARCH-SYSTEM-AB-EXEC-001','PASS','EXECUTION_REVIEW_PASSED_WITH_INFO_GAPS'],
|
['AUDIT-ANA-ROBOT-RESEARCH-SYSTEM-STAGE-C-REPAIR-REREVIEW-001','PASS','EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_CANDIDATE_LAYER'],
|
['AUDIT-ANA-ROBOT-RESEARCH-SYSTEM-STAGE-C-OEM-EXPANSION-EXEC-OUTPUT-001','PASS','EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_CANDIDATE_LAYER'],
|
['AUDIT-ANA-ROBOT-HUMAN-READABLE-SAMPLE-REREVIEW-001','PASS','PASS_WITH_RETAINED_GAPS'],
|
['AUDIT-ANA-ROBOT-THREEPIECE-INDEX-HUMAN-REPAIR-REREVIEW-001','PASS','THREEPIECE_OUTPUT_REVIEW_PASSED_WITH_RETAINED_GAPS'],
|
['AUDIT-ANA-ROBOT-FINAL-OUTPUT-HUMAN-LAYER-COMPANY16-REPAIR003-REREVIEW-001','PASS','EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS'],
|
['AUDIT-ANA-ROBOT-FINAL-OUTPUT-HUMAN-LAYER-SUBINDUSTRY13-LEDGER-REPAIR-REREVIEW-001','PASS','EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS'],
|
['AUDIT-ANA-ROBOT-COMPANY-UNIVERSE-NEXT034-EXACT-ROW-REPAIR002-REREVIEW-001','PASS','EXECUTION_REVIEW_PASSED_WITH_FROZEN_CLASSIFICATION_NO_FORMAL_POOL_CHANGE'],
|
['AUDIT-ANA-ROBOT-DATABASE-SCOPE-NEXT036-CURRENTITY-EXECUTION-RETRY-REVIEW-001','PASS','EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_MARKET_OBSERVATION_BOUNDARY'],
|
['AUDIT-ANA-ROBOT-LEGACY-OUTPUT-DISPOSITION-EXEC-OUTPUT-001','PASS','EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED'],
|
['AUDIT-ANA-ROBOT-FORMAL-EVIDENCE-MAP-ALIGNMENT-EXECUTION-REPAIR001-TIMING-REHANDOFF-001','PASS','EVIDENCE_MAP_STATE_CLOSED_NO_UPGRADE'],
|
];
|
|
function extractAuditEntries() {
|
const lines = text(AUDIT_REPORT).replaceAll('\r\n', '\n').split('\n');
|
return auditSpecs.map(([audit_id, literal, boundary], index) => {
|
const start = lines.findIndex(line => line.startsWith('### ') && line.includes(audit_id));
|
if (start < 0) throw new Error(`AUDIT_HEADING_NOT_FOUND:${audit_id}`);
|
let end = lines.length;
|
for (let i = start + 1; i < lines.length; i++) if (lines[i].startsWith('### ')) { end = i; break; }
|
const normalized = `${lines.slice(start, end).join('\n').replace(/\n+$/, '')}\n`;
|
return {
|
authority_id: `FGRAUD-${String(index + 1).padStart(3, '0')}`,
|
audit_id,
|
audit_report_path: AUDIT_REPORT,
|
heading_line: start + 1,
|
end_line: end,
|
normalization: 'UTF8_NO_BOM_LF_JOIN_LINES_WITH_TERMINAL_LF_V1',
|
entry_bytes: Buffer.byteLength(normalized),
|
entry_sha256: sha(Buffer.from(normalized, 'utf8')),
|
formal_audit_conclusion_literal: literal,
|
applicable_status_boundary: boundary,
|
latest_applicable: 'YES',
|
};
|
});
|
}
|
|
const statusByPath = (row) => {
|
const p = row.artifact_path;
|
if (row.artifact_group === 'OEM_TRACKING') return ['EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_CANDIDATE_LAYER','PASS_CANDIDATE_LAYER_WITH_EXPLICIT_GAPS','AUDIT-ANA-ROBOT-RESEARCH-SYSTEM-STAGE-C-OEM-EXPANSION-EXEC-OUTPUT-001','候选研究层;三侧缺口保留'];
|
if (row.artifact_group === 'DYNAMIC_TIMELINE') return ['EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_CANDIDATE_LAYER','PASS_CANDIDATE_LAYER_WITH_EXPLICIT_GAPS','AUDIT-ANA-ROBOT-RESEARCH-SYSTEM-STAGE-C-REPAIR-REREVIEW-001','event/freshness仍为候选层'];
|
if (row.artifact_group === 'THREEPIECE') return ['THREEPIECE_OUTPUT_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','AUDIT-ANA-ROBOT-THREEPIECE-INDEX-HUMAN-REPAIR-REREVIEW-001','三件套人读输出通过;持续缺口不升级'];
|
if (row.artifact_group === 'COMPANY_COMPARISON') return ['EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','AUDIT-ANA-ROBOT-FINAL-OUTPUT-HUMAN-LAYER-COMPANY16-REPAIR003-REREVIEW-001','公司横向表作为company16已审核页面'];
|
if (row.artifact_group.includes('COMPANY')) {
|
if (p.endsWith('/双环传动.md')) return ['EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','AUDIT-ANA-ROBOT-HUMAN-READABLE-SAMPLE-REREVIEW-001','八项候选数字继续待复核'];
|
return ['EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','AUDIT-ANA-ROBOT-FINAL-OUTPUT-HUMAN-LAYER-COMPANY16-REPAIR003-REREVIEW-001','公司人读层与证据状态已审核;不构成正式扩池'];
|
}
|
if (row.artifact_group === 'SUBINDUSTRY14') {
|
if (p.endsWith('/电机_市场分析.md')) return ['EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','AUDIT-ANA-ROBOT-HUMAN-READABLE-SAMPLE-REREVIEW-001','样板复审通过;强字段缺口保留'];
|
return ['EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','AUDIT-ANA-ROBOT-FINAL-OUTPUT-HUMAN-LAYER-SUBINDUSTRY13-LEDGER-REPAIR-REREVIEW-001','子行业人读层与ledger已审核;持续缺口保留'];
|
}
|
if (row.artifact_group === 'STRUCTURED_TABLE') return ['A_B_EXECUTION_REVIEW_PASSED_WITH_UNCLASSIFIED_AND_CANDIDATE_GAPS','PASS_WITH_GAPS_NOT_DATABASE_EXPORT','AUDIT-ANA-ROBOT-RESEARCH-SYSTEM-AB-EXEC-001','A/B候选与待分类状态不升级'];
|
if (row.artifact_group === 'LEGACY_READOUT') return ['EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_AS_COMPATIBILITY_REDIRECT','PASS_AS_LEGACY_COMPATIBILITY_REDIRECT_NOT_CANONICAL_DELIVERY','AUDIT-ANA-ROBOT-LEGACY-OUTPUT-DISPOSITION-EXEC-OUTPUT-001','保留原路径但仅重定向至canonical输出'];
|
throw new Error(`UNMAPPED_INVENTORY:${row.inventory_id}:${row.artifact_group}`);
|
};
|
|
function buildInventory() {
|
const source = parseCsv(text(OLD_INVENTORY));
|
if (source.length !== 49 || new Set(source.map(r => r.artifact_path)).size !== 49) throw new Error('OLD_INVENTORY_SET_INVALID');
|
return source.map(row => {
|
if (!fs.existsSync(abs(row.artifact_path))) throw new Error(`MISSING_OUTPUT:${row.artifact_path}`);
|
const id = fileIdentity(row.artifact_path);
|
const [review_state, final_gate_disposition, evidence_ref, note] = statusByPath(row);
|
return { ...row, sha256: id.sha256, bytes: id.bytes, lines: id.lines, review_state, final_gate_disposition, evidence_ref, note };
|
});
|
}
|
|
function buildBaseline(inventory) {
|
const critical = [
|
[`${EVIDENCE}/case_evidence_map.csv`,'FORMAL_EVIDENCE_MAP','PROTECTED_ALIGNED_NO_UPGRADE'],
|
[`${EVIDENCE}/formal_evidence_map_alignment_change_ledger_20260728.csv`,'FORMAL_EVIDENCE_MAP_CHANGE_LEDGER','PROTECTED_ALIGNMENT_TRACE'],
|
[`${MANIFEST}/migration_manifest.csv`,'MIGRATION_MANIFEST','PROTECTED_UNCHANGED'],
|
[`${EVIDENCE}/final_output_human_layer_protected_identity_20260725.csv`,'PROTECTED_IDENTITY_AUTHORITY','PROTECTED_AUTHORITY'],
|
[`${EVIDENCE}/next_robot_036_currentity_company_summary_20260727.csv`,'DATABASE_MARKET_OBSERVATION_SUMMARY','AS_OF_2026_07_24_NOT_INVESTMENT_CONCLUSION'],
|
[`${EVIDENCE}/next_robot_034_company_universe_classification_repair002_20260726.csv`,'COMPANY_UNIVERSE_CLASSIFICATION','NO_AUTOMATIC_FORMAL_POOL_CHANGE'],
|
];
|
const rows = inventory.map((r, i) => ({ baseline_id: `FGRBASE-${String(i + 1).padStart(3,'0')}`, object_type: 'CANONICAL_OUTPUT_INVENTORY', artifact_path: r.artifact_path, sha256: r.sha256, bytes: r.bytes, lines: r.lines, boundary: r.final_gate_disposition }));
|
critical.forEach(([artifact_path, object_type, boundary], i) => {
|
const id = fileIdentity(artifact_path);
|
rows.push({ baseline_id: `FGRBASE-${String(50 + i).padStart(3,'0')}`, object_type, artifact_path, sha256: id.sha256, bytes: id.bytes, lines: id.lines, boundary });
|
});
|
return rows;
|
}
|
|
function buildReadiness() {
|
const A = 'AUDIT-ANA-ROBOT-';
|
return [
|
['FG-001','SCOPE','冻结全部canonical输出身份','49 current files','COMPLETE_CURRENT_IDENTITY','PASS','none','独立复算49项身份与唯一集合'],
|
['FG-002','THREEPIECE','三件套输出审核',`${A}THREEPIECE-INDEX-HUMAN-REPAIR-REREVIEW-001`,'THREEPIECE_OUTPUT_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','retained source/strong-field gaps','保持降读;正文变化则重审'],
|
['FG-003','CORE7','核心7剩余公司页最终输出状态',`${A}FINAL-OUTPUT-HUMAN-LAYER-COMPANY16-REPAIR003-REREVIEW-001`,'EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','double-ring candidate numbers retained','复用双环样板PASS并保留数字缺口'],
|
['FG-004','FIRST9','首批9公司页最终输出状态',`${A}FINAL-OUTPUT-HUMAN-LAYER-COMPANY16-REPAIR003-REREVIEW-001`,'EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','company strong fields retained','不升级经营与供应关系强字段'],
|
['FG-005','SUBINDUSTRY14','14个子行业页面最终输出状态',`${A}FINAL-OUTPUT-HUMAN-LAYER-SUBINDUSTRY13-LEDGER-REPAIR-REREVIEW-001`,'EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','subindustry retained gaps','电机市场复用样板PASS'],
|
['FG-005A','COMPANY_COMPARISON','公司横向同步总表最终输出状态',`${A}FINAL-OUTPUT-HUMAN-LAYER-COMPANY16-REPAIR003-REREVIEW-001`,'EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_RETAINED_GAPS','PASS_WITH_RETAINED_GAPS','no ranking/formal pool inference','作为company16已审核页面'],
|
['FG-006','STAGE_C','本体厂与时间线候选研究层',`${A}RESEARCH-SYSTEM-STAGE-C-OEM-EXPANSION-EXEC-OUTPUT-001`,'EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_CANDIDATE_LAYER','PASS_WITH_CANDIDATE_BOUNDARY','supplier/customer/third-party gaps','仅候选研究层'],
|
['FG-007','COMPANY_UNIVERSE','NEXT033/034公司全集分类与正式池边界',`${A}COMPANY-UNIVERSE-NEXT034-EXACT-ROW-REPAIR002-REREVIEW-001`,'EXECUTION_REVIEW_PASSED_WITH_FROZEN_CLASSIFICATION_NO_FORMAL_POOL_CHANGE','PASS_WITH_NO_FORMAL_POOL_CHANGE','candidate classifications retained','不自动正式扩池'],
|
['FG-008','DATABASE','NEXT036行情currentity只读输出',`${A}DATABASE-SCOPE-NEXT036-CURRENTITY-EXECUTION-RETRY-REVIEW-001`,'EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED_WITH_MARKET_OBSERVATION_BOUNDARY','PASS_WITH_MARKET_OBSERVATION_BOUNDARY','as_of=2026-07-24','不是投资结论;database_write=0'],
|
['FG-009','STRUCTURED_TABLES','A/B结构表与候选状态',`${A}RESEARCH-SYSTEM-AB-EXEC-001`,'EXECUTION_REVIEW_PASSED_WITH_INFO_GAPS','PASS_WITH_GAPS','unclassified and candidate-only fields','保持候选/缺口'],
|
['FG-010','LEGACY_OUTPUT','summary/readout canonical处置',`${A}LEGACY-OUTPUT-DISPOSITION-EXEC-OUTPUT-001`,'EXECUTION_AND_OUTPUT_QUALITY_REVIEW_PASSED','PASS_AS_COMPATIBILITY_REDIRECT','not canonical delivery','旧路径只作受控重定向'],
|
['FG-011','EVIDENCE_MAP','正式case_evidence_map最新状态对齐',`${A}FORMAL-EVIDENCE-MAP-ALIGNMENT-EXECUTION-REPAIR001-TIMING-REHANDOFF-001`,'EVIDENCE_MAP_STATE_CLOSED_NO_UPGRADE','PASS_NO_UPGRADE','retained gaps preserved','45/45 NO_UPGRADE'],
|
['FG-012','MANIFEST','artifact manifest append-only七字段','artifact_manifest.csv 781-row frozen prefix','APPEND_ONLY_PREFIX_VALID','PASS','none','新run仅append最终身份'],
|
['FG-013','RETAINED_GAPS','IFR/MIR/Omdia/AMR/ASP/BOM/经营/合同/利润池','latest applicable audits','EXPLICITLY_RETAINED_AND_DOWNGRADED','PASS_AS_DISCLOSED_GAPS','strong fields unavailable','不得升级'],
|
['FG-014','DOUBLE_RING','双环八项候选数字',`${A}HUMAN-READABLE-SAMPLE-REREVIEW-001`,'DOWNGRADED_AND_UNVERIFIED','PASS_AS_DISCLOSED_GAP','eight candidate numbers','维持待复核线索'],
|
['FG-015','CASE_STATUS','案例完成状态','this rebuilt package','PENDING_INDEPENDENT_FINAL_GATE_REVIEW','PENDING_REVIEW','final gate decision pending','reviewer明确PASS后方可回写'],
|
['FG-016','DELIVERY','对外交付状态','this rebuilt package','NOT_RELEASED_PENDING_INDEPENDENT_FINAL_GATE_REVIEW','PENDING_REVIEW','final gate decision pending','reviewer明确放行前禁止交付'],
|
['FG-017','DEV_ISSUE','dev target dir drift','management closure','CLOSED_DO_NOT_REACTIVATE','PASS','none','旧文本不重新激活'],
|
['FG-018','SKILL_GAP','fp availability','current skill catalog','fp_not_available','INFO','none','只记录不扩权'],
|
].map(([gate_id,gate_group,requirement,frozen_evidence,current_state,analyst_precheck,blocking_scope,required_next_action]) => ({gate_id,gate_group,requirement,frozen_evidence,current_state,analyst_precheck,blocking_scope,required_next_action}));
|
}
|
|
function normalizeSectionByMarker(rel, marker, headingPrefix) {
|
const lines = text(rel).replaceAll('\r\n','\n').split('\n');
|
const start = lines.findIndex(line => line.startsWith(headingPrefix) && line.includes(marker));
|
if (start < 0) throw new Error(`SHARED_MARKER_NOT_FOUND:${rel}:${marker}`);
|
let end = lines.length;
|
for (let i = start + 1; i < lines.length; i++) if (lines[i].startsWith(headingPrefix)) { end = i; break; }
|
const normalized = `${lines.slice(start,end).join('\n').replace(/\n+$/,'')}\n`;
|
return { start_line: start + 1, end_line: end, normalized_bytes: Buffer.byteLength(normalized), normalized_sha256: sha(Buffer.from(normalized,'utf8')) };
|
}
|
function buildSharedAuthority() {
|
const specs = [
|
['EXECUTION_LOG','ana-doc/机器人案例/案例执行日志.md',RUN,'### '],
|
['PARENT_STATUS','ana-doc/案例总纲.md','机器人案例 NEXT-ROBOT-037 最终门禁包重建待独立审核','### '],
|
['REMAINING_WORK',`${MANIFEST}/remaining_work_plan_20260704.md`,'NEXT-ROBOT-037 最终门禁包重建待独立审核','## '],
|
['RESULT_INDEX','ana-data/result/机器人案例/ANA-ROBOT-INDUSTRY-001/result_index.md','NEXT-ROBOT-037 最终门禁包重建待独立审核','## '],
|
];
|
const rows = specs.map(([record_type,artifact_path,marker,prefix], i) => ({ authority_id:`FGRSHARED-${String(i+1).padStart(3,'0')}`,record_type,artifact_path,marker,normalization:'UTF8_NO_BOM_LF_JOIN_LINES_WITH_TERMINAL_LF_V1',...normalizeSectionByMarker(artifact_path,marker,prefix) }));
|
const nextRows = text(`${MANIFEST}/next_action_list.csv`).replaceAll('\r\n','\n').split('\n');
|
const idx = nextRows.findIndex(line => line.includes('"NEXT-ROBOT-037"') && line.includes(PACKAGE));
|
if (idx < 0) throw new Error('NEXT_ACTION_REBUILD_ROW_NOT_FOUND');
|
const normalized = `${nextRows[idx]}\n`;
|
rows.push({authority_id:'FGRSHARED-005',record_type:'NEXT_ACTION_ROW',artifact_path:`${MANIFEST}/next_action_list.csv`,marker:PACKAGE,normalization:'UTF8_NO_BOM_SINGLE_LINE_WITH_TERMINAL_LF_V1',start_line:idx+1,end_line:idx+1,normalized_bytes:Buffer.byteLength(normalized),normalized_sha256:sha(Buffer.from(normalized,'utf8'))});
|
return rows;
|
}
|
|
function buildArtifactSet() {
|
const paths = [GENERATOR_PATH,OUTPUTS.auditAuthority,OUTPUTS.inventory,OUTPUTS.baseline,OUTPUTS.readiness,OUTPUTS.sharedAuthority,OUTPUTS.artifactSet,OUTPUTS.request,OUTPUTS.validation];
|
const types = ['GENERATOR','AUDIT_ENTRY_AUTHORITY','CURRENT_OUTPUT_INVENTORY','REBUILD_BASELINE','READINESS_MATRIX','SHARED_RECORD_AUTHORITY','EXACT_ARTIFACT_SET','FINAL_GATE_REVIEW_REQUEST','VALIDATION_LAST'];
|
return paths.map((artifact_path,i)=>({artifact_set_id:`FGRART-${String(i+1).padStart(3,'0')}`,generation_order:i+1,artifact_type:types[i],artifact_path,validation_scope:i===8?'SELF_REFERENCE_EXCLUDED':'VALIDATE_FINAL_IDENTITY',manifest_policy:i===8?'APPEND_FINAL_IDENTITY_EXTERNALLY':'APPEND_FINAL_IDENTITY'}));
|
}
|
|
function buildRequest(audits, inventory, readiness) {
|
return `# ANA-ROBOT-INDUSTRY-001 NEXT-ROBOT-037 最终门禁重建包独立审核请求\n\n`+
|
`project_id=project-info \ncase_id=${CASE} \naction_id=NEXT-ROBOT-037 \npackage_id=${PACKAGE} \nbatch_id=${BATCH} \nexecution_run_id=${RUN} \nsource_role=case_analysis.analyst.cai \ntarget_role=case_analysis.reviewer.cai \npredecessor_audit_id=AUDIT-ANA-ROBOT-FORMAL-EVIDENCE-MAP-ALIGNMENT-EXECUTION-REPAIR001-TIMING-REHANDOFF-001 \nrequested_review=case_analysis_final_gate_rebuilt_package_independent_review \nanalyst_precheck=PACKAGE_REBUILT_PENDING_INDEPENDENT_FINAL_GATE_REVIEW \ncase_completion_release=NOT_RELEASED \nexternal_delivery_release=NOT_RELEASED\n\n`+
|
`## 1. 审核范围\n\n本包只冻结现状并请求独立总门禁判断:${inventory.length} 项 canonical 输出当前身份、${audits.length} 个 append-stable 最新适用审计条目、${readiness.length} 项门禁矩阵及持续缺口。未修改输出正文、A/B、migration manifest、公司池、正式 evidence map 或证据强度。\n\n`+
|
`## 2. 前置终态\n\n- company16 与 subindustry13:独立执行/输出质量 PASS_WITH_RETAINED_GAPS。\n- company universe NEXT033/034:独立审核通过,NO_AUTOMATIC_FORMAL_POOL_CHANGE。\n- database NEXT036:截至 2026-07-24 的只读市场观察审核通过,database_write=0。\n- legacy output:两个旧路径已成为受控兼容重定向,不属于 canonical delivery。\n- formal evidence map:45 行受控对齐及 timing-only rehandoff 独立 PASS,45/45 NO_UPGRADE。\n\n`+
|
`## 3. 持续边界\n\nIFR PDF 页码级抽取、MIR/Omdia、AMR、ASP/BOM、公司经营字段、客户/合同侧关系、利润池、双环候选数字、A/B candidate/unclassified、本体厂三侧 gap 与 event/freshness 候选状态继续显式保留;不得解释为正式数字、供应关系、定点、订单、主供/独供、量产、产能、收入、利润、正式公司池或投资结论。\n\n`+
|
`## 4. 请求 reviewer 独立判断\n\n1. 49 项输出身份与最新适用审计是否一一匹配;\n2. 所有旧 final-gate 前置 blocker 是否已有正式独立终态;\n3. retained gaps、candidate boundary、market observation boundary 与 NO_UPGRADE 是否足以在有限范围内放行;\n4. 是否可明确登记 NEXT-ROBOT-037 final gate PASS,并分别给出 case completion 与 external delivery 的 release 状态。\n\n本请求本身不宣称 final gate、案例完成或对外交付通过。\n`;
|
}
|
|
function buildValidation(audits, inventory, baseline, readiness, shared, artifactSet) {
|
const rows=[]; let n=1;
|
const add=(g,o,e,a,s='PASS',ref='')=>rows.push({validation_id:`FGRVAL-${String(n++).padStart(3,'0')}`,check_group:g,object:o,expected:e,actual:a,result:s,evidence_ref:ref});
|
add('IDENTITY','package',`${PACKAGE}/${BATCH}/${RUN}`,`${PACKAGE}/${BATCH}/${RUN}`);
|
add('INVENTORY','rows','49',inventory.length,inventory.length===49?'PASS':'FAIL',OUTPUTS.inventory);
|
add('INVENTORY','unique_paths','49',new Set(inventory.map(r=>r.artifact_path)).size);
|
add('INVENTORY','missing_outputs','0',inventory.filter(r=>!fs.existsSync(abs(r.artifact_path))).length);
|
add('INVENTORY','held_dispositions','0',inventory.filter(r=>r.final_gate_disposition.startsWith('HELD')).length);
|
add('INVENTORY','company16_latest_audit_rows','15',inventory.filter(r=>r.evidence_ref.includes('COMPANY16-REPAIR003')).length);
|
add('INVENTORY','subindustry13_latest_audit_rows','13',inventory.filter(r=>r.evidence_ref.includes('SUBINDUSTRY13-LEDGER')).length);
|
add('INVENTORY','legacy_redirect_rows','2',inventory.filter(r=>r.final_gate_disposition.includes('LEGACY_COMPATIBILITY_REDIRECT')).length);
|
add('AUDIT','authority_rows',auditSpecs.length,audits.length);
|
add('AUDIT','unique_audit_ids',auditSpecs.length,new Set(audits.map(r=>r.audit_id)).size);
|
add('AUDIT','heading_or_entry_identity_errors','0',audits.filter(r=>!r.entry_sha256||!r.heading_line||!r.end_line).length);
|
add('READINESS','matrix_rows','19',readiness.length);
|
add('READINESS','open_prerequisite_blockers','0',readiness.filter(r=>['FG-001','FG-002','FG-003','FG-004','FG-005','FG-005A','FG-006','FG-007','FG-008','FG-009','FG-010','FG-011','FG-012','FG-013','FG-014','FG-017'].includes(r.gate_id)&&String(r.analyst_precheck).startsWith('HELD')).length);
|
add('READINESS','case_status','PENDING_INDEPENDENT_FINAL_GATE_REVIEW',readiness.find(r=>r.gate_id==='FG-015').current_state);
|
add('READINESS','delivery_status','NOT_RELEASED_PENDING_INDEPENDENT_FINAL_GATE_REVIEW',readiness.find(r=>r.gate_id==='FG-016').current_state);
|
add('BASELINE','rows','55',baseline.length);
|
add('BASELINE','unique_paths','55',new Set(baseline.map(r=>r.artifact_path)).size);
|
const mapRows=parseCsv(text(`${EVIDENCE}/case_evidence_map.csv`));
|
add('EVIDENCE_MAP','rows','45',mapRows.length);
|
add('EVIDENCE_MAP','no_upgrade_rows','45',mapRows.filter(r=>String(r.evidence_entry).includes('NO_UPGRADE')).length);
|
const ledgerRows=parseCsv(text(`${EVIDENCE}/formal_evidence_map_alignment_change_ledger_20260728.csv`));
|
add('EVIDENCE_MAP','change_ledger_rows','45',ledgerRows.length);
|
add('DATABASE','summary_rows','100',parseCsv(text(`${EVIDENCE}/next_robot_036_currentity_company_summary_20260727.csv`)).length);
|
add('DATABASE','market_observation_boundary','4_DATABASE_ROWS_WITH_MARKET_OBSERVATION_ONLY_STATUS',mapRows.filter(r=>String(r.review_status).includes('MARKET_OBSERVATION_ONLY')).length,mapRows.filter(r=>String(r.review_status).includes('MARKET_OBSERVATION_ONLY')).length===4?'PASS':'FAIL');
|
add('SHARED_RECORD','authority_rows','5',shared.length);
|
add('SHARED_RECORD','unique_markers','5',new Set(shared.map(r=>r.marker)).size);
|
const manifestBuf=bytes(ARTIFACT_MANIFEST); const manifestRows=parseCsv(manifestBuf.toString('utf8'));
|
add('MANIFEST','formal_header','case_id,run_id,batch_id,artifact_path,sha256,bytes,mtime',Object.keys(manifestRows[0]).join(','));
|
add('MANIFEST','frozen_prefix_rows','781',manifestRows.length);
|
add('MANIFEST','frozen_prefix_bytes','264643',manifestBuf.length);
|
add('MANIFEST','frozen_prefix_sha256','316df7c4d90f04dbc8e74ba59f703a5352728b21d564ce7c83e8cc614012a16b',sha(manifestBuf));
|
add('ARTIFACT_SET','rows','9',artifactSet.length);
|
add('ARTIFACT_SET','unique_paths','9',new Set(artifactSet.map(r=>r.artifact_path)).size);
|
add('BOUNDARY','case_completion_release','NOT_RELEASED','NOT_RELEASED');
|
add('BOUNDARY','external_delivery_release','NOT_RELEASED','NOT_RELEASED');
|
add('PROTECTED','migration_manifest','UNCHANGED_FROZEN_IDENTITY',fileIdentity(`${MANIFEST}/migration_manifest.csv`).sha256);
|
add('VALIDATION_SELF_REFERENCE',OUTPUTS.validation,'SELF_REFERENCE_EXCLUDED','SELF_REFERENCE_EXCLUDED','INFO',OUTPUTS.validation);
|
return rows;
|
}
|
|
function main() {
|
if (process.argv[2] !== '--execute') throw new Error('USE_--execute');
|
ensureAbsent();
|
const audits=extractAuditEntries();
|
const inventory=buildInventory();
|
const baseline=buildBaseline(inventory);
|
const readiness=buildReadiness();
|
const shared=buildSharedAuthority();
|
const artifactSet=buildArtifactSet();
|
write(OUTPUTS.auditAuthority,csv(['authority_id','audit_id','audit_report_path','heading_line','end_line','normalization','entry_bytes','entry_sha256','formal_audit_conclusion_literal','applicable_status_boundary','latest_applicable'],audits));
|
write(OUTPUTS.inventory,csv(['inventory_id','artifact_group','artifact_path','file_type','sha256','bytes','lines','review_state','final_gate_disposition','evidence_ref','note'],inventory));
|
write(OUTPUTS.baseline,csv(['baseline_id','object_type','artifact_path','sha256','bytes','lines','boundary'],baseline));
|
write(OUTPUTS.readiness,csv(['gate_id','gate_group','requirement','frozen_evidence','current_state','analyst_precheck','blocking_scope','required_next_action'],readiness));
|
write(OUTPUTS.sharedAuthority,csv(['authority_id','record_type','artifact_path','marker','normalization','start_line','end_line','normalized_bytes','normalized_sha256'],shared));
|
write(OUTPUTS.artifactSet,csv(['artifact_set_id','generation_order','artifact_type','artifact_path','validation_scope','manifest_policy'],artifactSet));
|
write(OUTPUTS.request,buildRequest(audits,inventory,readiness));
|
const validation=buildValidation(audits,inventory,baseline,readiness,shared,artifactSet);
|
write(OUTPUTS.validation,csv(['validation_id','check_group','object','expected','actual','result','evidence_ref'],validation));
|
const failures=validation.filter(r=>r.result==='FAIL');
|
if (failures.length) throw new Error(`VALIDATION_FAIL:${failures.map(r=>r.validation_id).join(',')}`);
|
console.log(JSON.stringify({package_id:PACKAGE,batch_id:BATCH,run_id:RUN,audits:audits.length,inventory:inventory.length,baseline:baseline.length,readiness:readiness.length,shared:shared.length,artifacts:artifactSet.length,validation:validation.length,failures:0}));
|
}
|
|
main();
|