Cai
2026-08-12 b32704d90d4ab7963e924d7a8d12c18eee4f6d0e
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
 
const ROOT = process.cwd();
const CASE_ROOT = path.join(ROOT, 'ana-data', 'cases', '机器人案例', 'ANA-ROBOT-INDUSTRY-001');
const AS_OF = '2026-08-06';
const BOUNDARY = 'OPEN_RETAINED_GAP_PARTIALLY_NARROWED';
 
const PATHS = {
  v4: path.join(CASE_ROOT, 'outputs', '数据表', 'robot_company_information_v04_20260806.csv'),
  gapRegister: path.join(CASE_ROOT, 'evidence', 'next_robot_075_high_value_gap_register_20260805.csv'),
  targetPriority: path.join(CASE_ROOT, 'evidence', 'next_robot_077_p0_target_priority_20260806.csv'),
  sourceBacktrace: path.join(CASE_ROOT, 'evidence', 'next_robot_077_primary_source_backtrace_20260806.csv'),
  gapEffect: path.join(CASE_ROOT, 'evidence', 'next_robot_077_gap_effect_register_20260806.csv'),
  v5: path.join(CASE_ROOT, 'outputs', '数据表', 'robot_company_information_v05_20260806.csv'),
  summary: path.join(CASE_ROOT, 'outputs', '核心文档', '机器人企业高价值缺口集中回源_第三轮_20260806.md'),
  validation: path.join(CASE_ROOT, 'manifest', 'next_robot_077_high_value_gap_content_sprint_validation_20260806.csv')
};
 
function readText(filePath) {
  return fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, '');
}
 
function parseCsv(text) {
  const records = [];
  let record = [];
  let value = '';
  let quoted = false;
  for (let index = 0; index < text.length; index += 1) {
    const char = text[index];
    if (quoted) {
      if (char === '"') {
        if (text[index + 1] === '"') {
          value += '"';
          index += 1;
        } else quoted = false;
      } else value += char;
    } else if (char === '"') quoted = true;
    else if (char === ',') {
      record.push(value);
      value = '';
    } else if (char === '\n') {
      record.push(value.replace(/\r$/, ''));
      records.push(record);
      record = [];
      value = '';
    } else value += char;
  }
  if (value.length || record.length) {
    record.push(value.replace(/\r$/, ''));
    records.push(record);
  }
  if (!records.length) return [];
  const columns = records[0];
  return records.slice(1).filter((row) => row.some(Boolean)).map((row) =>
    Object.fromEntries(columns.map((column, index) => [column, row[index] || '']))
  );
}
 
function readCsv(filePath) {
  return parseCsv(readText(filePath));
}
 
function csvCell(value) {
  return `"${String(value ?? '').replace(/"/g, '""')}"`;
}
 
function writeCsv(filePath, rows, columns) {
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
  const lines = [columns.map(csvCell).join(',')];
  for (const row of rows) lines.push(columns.map((column) => csvCell(row[column])).join(','));
  fs.writeFileSync(filePath, `${lines.join('\n')}\n`, 'utf8');
}
 
function writeText(filePath, text) {
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
  fs.writeFileSync(filePath, text.replace(/\r\n/g, '\n').replace(/\r/g, '\n'), 'utf8');
}
 
function shaFile(filePath) {
  return crypto.createHash('sha256').update(fs.readFileSync(filePath)).digest('hex');
}
 
function normalize(value) {
  return String(value || '').replace(/\s+/g, ' ').trim();
}
 
function unique(values) {
  return [...new Set(values.filter(Boolean))];
}
 
function md(value) {
  return normalize(value).replace(/\|/g, '/');
}
 
const companies = readCsv(PATHS.v4);
const gaps = readCsv(PATHS.gapRegister);
const companyByName = new Map(companies.map((row) => [row.canonical_name, row]));
const companyById = new Map(companies.map((row) => [row.company_id, row]));
const v4IdentityBefore = { bytes: fs.statSync(PATHS.v4).size, sha256: shaFile(PATHS.v4) };
 
function companyId(name) {
  const row = companyByName.get(name);
  if (!row) throw new Error(`UNRESOLVED_COMPANY:${name}`);
  return row.company_id;
}
 
const targetNames = ['云深处科技', '魔法原子', '银河通用', '擎朗智能', '艾利特机器人', '微亿智造'];
 
const sourceBacktrace = [
  {
    source_update_id: 'N077-SRC-001', canonical_name: '云深处科技', target_field: 'customer_and_commercial_relationship', gap_types_addressed: 'CUSTOMER',
    source_class: 'REGULATOR_IPO_PROSPECTUS_DRAFT', publisher: '云深处科技 / 上交所申报材料', source_title: '首次公开发行股票并在科创板上市招股说明书(申报稿)', publication_date: '2026-05-18', canonical_url: 'https://dataclouds.cninfo.com.cn/sjother2/documents/2026/2026-05-18/3ef52e260c1cc31a8c57ab5e0abf2c14.pdf', source_locator: 'P4 L80-L82; P130 L4325-L4355',
    content_update_text: '申报稿披露公司行业级应用客户超过500家、产品进入45个以上国家或地区;2025年前五大客户销售收入合计6354.86万元、占营业收入18.83%,其中具名客户包括四川具身人形机器人科技、闹奇机器人和Inmotion Robotic。',
    limitation: '招股书仍为申报稿;部分客户以A/C代称,前五大客户销售额不等于在手订单、独供关系或未来收入。'
  },
  {
    source_update_id: 'N077-SRC-002', canonical_name: '云深处科技', target_field: 'capacity_delivery_and_procurement', gap_types_addressed: 'MASS_PRODUCTION|CAPACITY',
    source_class: 'REGULATOR_IPO_PROSPECTUS_DRAFT', publisher: '云深处科技 / 上交所申报材料', source_title: '首次公开发行股票并在科创板上市招股说明书(申报稿)', publication_date: '2026-05-18', canonical_url: 'https://dataclouds.cninfo.com.cn/sjother2/documents/2026/2026-05-18/3ef52e260c1cc31a8c57ab5e0abf2c14.pdf', source_locator: 'P128 L4286-L4288; P129 L4306-L4320',
    content_update_text: '报告期内绝影X、绝影Lite及山猫M累计产量超过5500台;2025年四足及轮足机器人产量3936台、销量2908台、产销率73.88%。公司采用柔性生产,明确说明不存在固定设计产能或最大产能口径。',
    limitation: '产量与销量均为四足及轮足合计,不能拆作人形机器人数据;库存增加且产销率低于100%,不能把产量全部写成客户交付。'
  },
  {
    source_update_id: 'N077-SRC-003', canonical_name: '云深处科技', target_field: 'revenue_and_operational_metric', gap_types_addressed: 'REVENUE_PROFIT|ASP',
    source_class: 'REGULATOR_IPO_PROSPECTUS_DRAFT', publisher: '云深处科技 / 上交所申报材料', source_title: '首次公开发行股票并在科创板上市招股说明书(申报稿)', publication_date: '2026-05-18', canonical_url: 'https://dataclouds.cninfo.com.cn/sjother2/documents/2026/2026-05-18/3ef52e260c1cc31a8c57ab5e0abf2c14.pdf', source_locator: 'P27 L805-L816; P180-P181 L6188-L6215; P188-P190 L6414-L6472',
    content_update_text: '2025年营业收入33749.06万元、净利润2868.40万元、经营现金流净额6375.22万元、综合毛利率52.83%;具身智能机器人收入32237.73万元。绝影X系列2025年销售单价28.75万元/台、毛利率54.35%。',
    limitation: '财务数据来自申报稿;绝影X单价不能代表Lite、山猫M或DR,也不能外推公司整体ASP与未来利润率。'
  },
  {
    source_update_id: 'N077-SRC-004', canonical_name: '魔法原子', target_field: 'customer_and_commercial_relationship', gap_types_addressed: 'CUSTOMER|ORDER',
    source_class: 'COMPANY_OFFICIAL_ORDER_ANNOUNCEMENT', publisher: '魔法原子', source_title: '新行业记录!魔法原子成功斩获大健康行业1.5亿元大单', publication_date: '2026-04-21', canonical_url: 'https://www.magiclab.top/news/63', source_locator: 'L41-L52',
    content_update_text: '公司宣布正式签订1.5亿元机器人采购订单,面向家庭健康管理与智能陪护,并称合作将连接1万名高净值家庭用户。',
    limitation: '客户未具名,未披露台数、单价、付款、验收、交付周期和收入确认;连接1万家庭为合作规划,不是已服务客户数。'
  },
  {
    source_update_id: 'N077-SRC-005', canonical_name: '魔法原子', target_field: 'capacity_delivery_and_procurement', gap_types_addressed: 'MASS_PRODUCTION',
    source_class: 'COMPANY_OFFICIAL_APPLICATION_UPDATE', publisher: '魔法原子', source_title: '新行业记录!魔法原子成功斩获大健康行业1.5亿元大单', publication_date: '2026-04-21', canonical_url: 'https://www.magiclab.top/news/63', source_locator: 'L52-L56',
    content_update_text: '公司称工业方案已在汽车零部件、3C电子和智能制造装备等用户场景完成测试,并进入标杆工厂交付和规模化落地阶段。',
    limitation: '未披露具名工厂、机器人台数、验收指标或实际交付量;“规模化落地阶段”仍按供应商口径保留待客户侧复核。'
  },
  {
    source_update_id: 'N077-SRC-006', canonical_name: '魔法原子', target_field: 'capacity_delivery_and_procurement', gap_types_addressed: 'MASS_PRODUCTION|CAPACITY',
    source_class: 'COMPANY_OFFICIAL_FINANCING_AND_PRODUCTION_PLAN', publisher: '魔法原子', source_title: '魔法原子完成1.5亿元天使轮融资,2025开启量产交付', publication_date: '2024-12-25', canonical_url: 'https://www.magiclab.top/news/29', source_locator: 'L41-L56',
    content_update_text: '公司在2024年末称已具备整机大规模量产能力,并预计2025年交付数百台MagicBot、2026年达到千台级。',
    limitation: '这是历史预测与能力自述,不是截至2026年的实际交付结果;融资1.5亿元也不等于收入或订单。'
  },
  {
    source_update_id: 'N077-SRC-007', canonical_name: '银河通用', target_field: 'customer_and_commercial_relationship', gap_types_addressed: 'CUSTOMER',
    source_class: 'CUSTOMER_OFFICIAL_STRATEGIC_COOPERATION', publisher: '延锋国际', source_title: '延锋国际与银河通用机器人签署战略合作协议', publication_date: '2026-04-13', canonical_url: 'https://www.yanfeng.com/cn/yanfengguojiyuyinhetongyongjiqirenqianshuzhanehezuoxieyi', source_locator: 'L36-L52',
    content_update_text: '延锋官方披露双方签署战略合作,银河通用上海子公司将参与延锋智造能力中心训练场景建设,面向汽车零部件制造探索可复制的工业应用模式。',
    limitation: '战略合作不等于采购订单或已部署;未披露台数、金额、验收、排他性及量产时间。'
  },
  {
    source_update_id: 'N077-SRC-008', canonical_name: '银河通用', target_field: 'capacity_delivery_and_procurement', gap_types_addressed: 'ORDER|MASS_PRODUCTION',
    source_class: 'COMPANY_PRESS_RELEASE_DISTRIBUTION', publisher: '银河通用 / 美通社', source_title: '银河通用机器人拿下1000台机器人订单,推进具身智能工业场景深度应用', publication_date: '2025-12-23', canonical_url: 'https://www.prnasia.com/story/517052-1.shtml', source_locator: 'L112-L126; L145-L159',
    content_update_text: '银河通用新闻稿称与百达精工签署战略合作,计划在百达及其生态内部署超过1000台具身智能机器人,并将其称为“一千台订单”。',
    limitation: '这是企业发布稿,未见合同全文;未披露单价、付款、交付批次、验收或截至目前已交付数量,不能将计划部署直接记作完成出货。'
  },
  {
    source_update_id: 'N077-SRC-009', canonical_name: '擎朗智能', target_field: 'capacity_delivery_and_procurement', gap_types_addressed: 'CUSTOMER|MASS_PRODUCTION',
    source_class: 'COMPANY_OFFICIAL_SHIPMENT_UPDATE', publisher: 'KEENON Robotics', source_title: 'KEENON Showcased its General-Purpose + Specialized Robot Ecosystem at LEAP East 2026', publication_date: '2026-07-23', canonical_url: 'https://www.keenon.com/en/news/ksigpsreale2', source_locator: 'L132-L137',
    content_update_text: '擎朗称全球累计出货超过10万台机器人,部署覆盖70多个国家和地区,并援引IDC称全球出货份额为22.7%。',
    limitation: '均为公司新闻稿口径,未按产品、人形/专用机器人、年度、客户或收入拆分;IDC份额需报告原文复核。'
  },
  {
    source_update_id: 'N077-SRC-010', canonical_name: '艾利特机器人', target_field: 'capacity_delivery_and_procurement', gap_types_addressed: 'CUSTOMER|MASS_PRODUCTION',
    source_class: 'COMPANY_OFFICIAL_PROFILE', publisher: '艾利特机器人', source_title: '关于艾利特', publication_date: 'CURRENT_AS_OF_2026-08-06', canonical_url: 'https://www.elibot.com/about/profile', source_locator: 'L345-L382',
    content_update_text: '公司当前简介称全球累计销售近2万台协作机器人,覆盖50多个国家,拥有500多家经销商和系统集成商及110余家生态伙伴。',
    limitation: '这是公司累计宽口径,未给出年度、产品系列、终端客户、退换货或收入拆分,也不等于人形/复合机器人销量。'
  },
  {
    source_update_id: 'N077-SRC-011', canonical_name: '艾利特机器人', target_field: 'customer_and_commercial_relationship', gap_types_addressed: 'ORDER|MASS_PRODUCTION',
    source_class: 'COMPANY_OFFICIAL_PARTNER_DEPLOYMENT_REPORT', publisher: '艾利特机器人 / 迈幸机器人', source_title: '艾利特×迈幸机器人:开启大模型驱动下的复合机器人新纪元', publication_date: '2025-12-30', canonical_url: 'https://www.elibot.com/about/news/162', source_locator: 'L420-L429',
    content_update_text: '合作方称其复合机器人在某全球科技公司供应链CNC产线落地近200台,并实现单笔订单百台级;在光模块测试场景也完成批量部署。',
    limitation: '数据来自合作方在艾利特官网的发言,终端客户未具名;近200台为复合设备口径,不能全部等同艾利特机械臂销量或收入。'
  },
  {
    source_update_id: 'N077-SRC-012', canonical_name: '艾利特机器人', target_field: 'revenue_and_operational_metric', gap_types_addressed: 'LIFETIME',
    source_class: 'COMPANY_OFFICIAL_CERTIFICATION_RECORD', publisher: '艾利特机器人', source_title: '关于艾利特 / MTBF可靠性证书记录', publication_date: '2023-12-29', canonical_url: 'https://www.elibot.com/about/profile', source_locator: 'L453-L465',
    content_update_text: '公司荣誉页记录2023年12月29日取得10万小时MTBF可靠性证书;官网另称该测试由上海机器人研发与转化功能型平台实施。',
    limitation: 'MTBF为统计可靠性指标,不等于单台连续实跑10万小时、质保期或现场寿命;本轮未取得完整测试报告与适用型号清单。'
  },
  {
    source_update_id: 'N077-SRC-013', canonical_name: '微亿智造', target_field: 'customer_and_commercial_relationship', gap_types_addressed: 'CUSTOMER|MASS_PRODUCTION',
    source_class: 'COMPANY_OFFICIAL_PROFILE', publisher: '微亿智造', source_title: '关于微亿智造', publication_date: 'CURRENT_AS_OF_2026-08-06', canonical_url: 'https://www.micro-i.com.cn/us', source_locator: 'L0-L5; L106-L120',
    content_update_text: '公司称工业具身智能产品已实现规模商业化,并向世界领先的3C消费电子及新能源汽车品牌客户批量部署AI表面缺陷检测设备;同时称MIM行业AI视觉质检方案市场占有率70%。',
    limitation: '客户未具名,未披露设备数量、合同金额、收入或利润;70%为公司引用口径,需IDC/行业报告原文复核,且不等于全部具身智能产品份额。'
  }
].map((row) => ({
  ...row,
  company_id: companyId(row.canonical_name),
  source_fact_status: 'PRIMARY_SOURCE_CONTENT_CAPTURED_PENDING_VERIFICATION_NO_UPGRADE',
  gap_effect: BOUNDARY,
  claim_strength_after: 'PENDING_VERIFICATION_MAX_NO_UPGRADE',
  formal_pool_effect: 'NO_AUTOMATIC_FORMAL_POOL_CHANGE',
  evidence_strength_effect: 'NO_UPGRADE',
  captured_at: `${AS_OF}T18:30:00+08:00`
}));
 
const updatesByCompany = new Map();
for (const update of sourceBacktrace) {
  if (!updatesByCompany.has(update.company_id)) updatesByCompany.set(update.company_id, []);
  updatesByCompany.get(update.company_id).push(update);
}
 
const targetPriority = targetNames.map((name, index) => {
  const company = companyByName.get(name);
  const companyGaps = gaps.filter((row) => row.company_id === company.company_id && row.priority === 'P0');
  const updates = updatesByCompany.get(company.company_id) || [];
  return {
    priority_order: String(index + 1),
    company_id: company.company_id,
    canonical_name: name,
    original_p0_gap_count: String(companyGaps.length),
    original_p0_gap_types: companyGaps.map((row) => row.gap_type).sort().join('|'),
    official_source_update_count: String(updates.length),
    addressed_gap_types: unique(updates.flatMap((row) => row.gap_types_addressed.split('|'))).sort().join('|'),
    selection_reason: 'HIGH_YIELD_MULTI_GAP_PRIMARY_SOURCE_AVAILABLE',
    execution_mode: 'CONTENT_STRENGTHENING_NO_MICRO_REVIEW',
    boundary: 'PENDING_VERIFICATION_MAX_NO_UPGRADE|NO_AUTOMATIC_FORMAL_POOL_CHANGE|NO_UPGRADE'
  };
});
 
const gapEffect = [];
for (const target of targetPriority) {
  const companyUpdates = updatesByCompany.get(target.company_id) || [];
  const companyGaps = gaps.filter((row) => row.company_id === target.company_id && row.priority === 'P0');
  for (const gap of companyGaps) {
    const matched = companyUpdates.filter((row) => row.gap_types_addressed.split('|').includes(gap.gap_type));
    gapEffect.push({
      gap_effect_id: `N077-GFX-${String(gapEffect.length + 1).padStart(3, '0')}`,
      source_gap_id: gap.gap_id,
      company_id: gap.company_id,
      canonical_name: gap.canonical_name,
      gap_type: gap.gap_type,
      source_update_ids: matched.map((row) => row.source_update_id).join('|'),
      evidence_added_count: String(matched.length),
      status_after: matched.length ? BOUNDARY : 'OPEN_RETAINED_GAP_NOT_ADDRESSED_THIS_SPRINT',
      closure_effect: 'NO_GAP_CLOSURE',
      claim_strength_after: 'PENDING_VERIFICATION_MAX_NO_UPGRADE',
      formal_pool_effect: 'NO_AUTOMATIC_FORMAL_POOL_CHANGE',
      evidence_strength_effect: 'NO_UPGRADE'
    });
  }
}
 
const contentFields = ['product_and_technical_capability', 'customer_and_commercial_relationship', 'revenue_and_operational_metric', 'capacity_delivery_and_procurement', 'market_position_and_chain_role', 'high_value_gap_and_risk'];
const v5 = companies.map((row) => {
  const next = { ...row };
  const updates = updatesByCompany.get(row.company_id) || [];
  for (const field of contentFields) {
    const additions = updates.filter((update) => update.target_field === field);
    if (!additions.length) continue;
    const appended = additions.map((update) => `〔${update.source_update_id}〕${update.content_update_text}(边界:${update.limitation})`).join(';');
    next[field] = [normalize(row[field]), `【N077主源回补】${appended}`].filter(Boolean).join(';');
  }
  const target = targetPriority.find((item) => item.company_id === row.company_id);
  next.n077_target_status = target ? 'P0_HIGH_YIELD_TARGET_COMPLETED' : 'NOT_IN_N077_TARGET_BATCH';
  next.n077_original_p0_gap_count = target?.original_p0_gap_count || '0';
  next.n077_addressed_gap_types = target?.addressed_gap_types || '';
  next.n077_primary_source_update_ids = updates.map((update) => update.source_update_id).join('|');
  next.n077_content_update_status = updates.length ? 'PRIMARY_SOURCE_CONTENT_ENRICHED_GAPS_REMAIN_OPEN_NO_UPGRADE' : 'NO_N077_PRIMARY_SOURCE_UPDATE';
  next.content_update_batch = updates.length ? unique(String(row.content_update_batch || '').split('|').concat('NEXT-ROBOT-077')).join('|') : row.content_update_batch;
  next.as_of = AS_OF;
  return next;
});
 
const targetColumns = ['priority_order','company_id','canonical_name','original_p0_gap_count','original_p0_gap_types','official_source_update_count','addressed_gap_types','selection_reason','execution_mode','boundary'];
const sourceColumns = ['source_update_id','company_id','canonical_name','target_field','gap_types_addressed','source_class','publisher','source_title','publication_date','canonical_url','source_locator','content_update_text','limitation','source_fact_status','gap_effect','claim_strength_after','formal_pool_effect','evidence_strength_effect','captured_at'];
const gapEffectColumns = ['gap_effect_id','source_gap_id','company_id','canonical_name','gap_type','source_update_ids','evidence_added_count','status_after','closure_effect','claim_strength_after','formal_pool_effect','evidence_strength_effect'];
const v5Columns = unique(Object.keys(companies[0]).concat(['n077_target_status','n077_original_p0_gap_count','n077_addressed_gap_types','n077_primary_source_update_ids','n077_content_update_status']));
 
writeCsv(PATHS.targetPriority, targetPriority, targetColumns);
writeCsv(PATHS.sourceBacktrace, sourceBacktrace, sourceColumns);
writeCsv(PATHS.gapEffect, gapEffect, gapEffectColumns);
writeCsv(PATHS.v5, v5, v5Columns);
 
const affectedCompanies = new Set(sourceBacktrace.map((row) => row.company_id));
const addressedGapTypes = unique(sourceBacktrace.flatMap((row) => row.gap_types_addressed.split('|'))).sort();
const partiallyNarrowed = gapEffect.filter((row) => row.status_after === BOUNDARY).length;
const remainingUnaddressed = gapEffect.length - partiallyNarrowed;
const summary = [
  '# 机器人企业高价值缺口集中回源(第三轮)',
  '',
  `> 更新日期:${AS_OF}`,
  '> 执行方式:内容优先;把监管披露、客户公告和公司主源直接纳入统一企业表,不新增逐企业审核链。',
  '> 证据边界:新增信息只缩窄缺口,不自动入正式池、不提升证据强度、不宣称缺口关闭。',
  '',
  '## 1. 本轮产出',
  '',
  `- 处理企业:${affectedCompanies.size}家。`,
  `- 新增监管/客户/公司主源字段更新:${sourceBacktrace.length}条。`,
  `- 覆盖原始P0公司×缺口:${gapEffect.length}项,其中${partiallyNarrowed}项获得直接增量证据,${remainingUnaddressed}项继续保留。`,
  `- 涉及缺口类型:${addressedGapTypes.join('、')}。`,
  '',
  '## 2. 企业与增量事实',
  '',
  '| 企业 | 原P0缺口 | 新增主源数 | 本轮补充重点 |',
  '|---|---|---:|---|',
  ...targetPriority.map((row) => `| ${md(row.canonical_name)} | ${md(row.original_p0_gap_types)} | ${row.official_source_update_count} | ${md(row.addressed_gap_types)} |`),
  '',
  '## 3. 主源事实与边界',
  '',
  '| 企业 | 字段 | 新增事实 | 保留边界 |',
  '|---|---|---|---|',
  ...sourceBacktrace.map((row) => `| ${md(row.canonical_name)} | ${row.target_field} | ${md(row.content_update_text)} | ${md(row.limitation)} |`),
  '',
  '## 4. 实用结论',
  '',
  '- 云深处已形成当前企业库中较完整的财务、产销、客户与ASP主源剖面:2025年收入3.37亿元、净利润2868万元、四/轮足产量3936台、销量2908台;但招股书仍为申报稿且人形数据不可从四足口径外推。',
  '- 魔法原子的1.5亿元大健康订单可作为订单事实保留;客户、台数、验收与收入确认未披露。2024年提出的数百/千台交付只能记为历史计划,不能当成实际完成。',
  '- 银河通用与延锋的合作由客户侧确认;百达精工千台项目来自银河通用发布稿,当前只能写成签约/计划部署,不能写成已交付千台。',
  '- 擎朗、艾利特和微亿补入累计出货、批量部署与可靠性信息;相关数据仍按公司口径保留,未拆出的机器人单品收入、ASP和利润继续列缺口。',
  '- 下一轮继续优先处理一份监管/客户/公司主源能同时补两类以上商业缺口的P0企业。',
  '',
  '## 5. 数据入口',
  '',
  '- 目标优先级:`evidence/next_robot_077_p0_target_priority_20260806.csv`',
  '- 主源回溯:`evidence/next_robot_077_primary_source_backtrace_20260806.csv`',
  '- 缺口效果表:`evidence/next_robot_077_gap_effect_register_20260806.csv`',
  '- 307家公司统一信息表v05:`outputs/数据表/robot_company_information_v05_20260806.csv`'
];
writeText(PATHS.summary, `${summary.join('\n')}\n`);
 
const validation = [];
function check(id, description, expected, actual) {
  validation.push({ check_id: id, check_description: description, expected: String(expected), actual: String(actual), status: String(expected) === String(actual) ? 'PASS' : 'FAIL' });
}
 
const immutable = ['company_id','canonical_name','aliases','company_type','region','listed_status','primary_track','detail_track','source_profile_status','formal_output_status','evidence_ceiling','formal_pool_effect'];
let immutableMismatch = 0;
let unauthorizedBaseFieldMismatch = 0;
for (const row of v5) {
  const before = companyById.get(row.company_id);
  for (const column of immutable) if ((before?.[column] || '') !== (row[column] || '')) immutableMismatch += 1;
  const allowedChanged = new Set(['as_of']);
  if (targetNames.includes(row.canonical_name)) {
    for (const column of [...contentFields, 'content_update_batch']) allowedChanged.add(column);
  }
  for (const column of Object.keys(companies[0])) {
    if (!allowedChanged.has(column) && (before?.[column] || '') !== (row[column] || '')) unauthorizedBaseFieldMismatch += 1;
  }
}
 
const v4IdentityAfter = { bytes: fs.statSync(PATHS.v4).size, sha256: shaFile(PATHS.v4) };
const sourceText = readText(PATHS.sourceBacktrace);
check('N077-VAL-001', 'company v04 row count', 307, companies.length);
check('N077-VAL-002', 'company v04 id uniqueness', 307, new Set(companies.map((row) => row.company_id)).size);
check('N077-VAL-003', 'P0 target company count', 6, targetPriority.length);
check('N077-VAL-004', 'P0 target id uniqueness', 6, new Set(targetPriority.map((row) => row.company_id)).size);
check('N077-VAL-005', 'primary source update count', 13, sourceBacktrace.length);
check('N077-VAL-006', 'source update id uniqueness', 13, new Set(sourceBacktrace.map((row) => row.source_update_id)).size);
check('N077-VAL-007', 'source company ids unresolved', 0, sourceBacktrace.filter((row) => !companyById.has(row.company_id)).length);
check('N077-VAL-008', 'source rows missing URL/locator/content/boundary', 0, sourceBacktrace.filter((row) => !/^https:\/\//.test(row.canonical_url) || !row.source_locator || !row.content_update_text || !row.limitation).length);
check('N077-VAL-009', 'source rows outside target set', 0, sourceBacktrace.filter((row) => !targetNames.includes(row.canonical_name)).length);
check('N077-VAL-010', 'P0 gap effect rows', 38, gapEffect.length);
check('N077-VAL-011', 'P0 gap effect id uniqueness', 38, new Set(gapEffect.map((row) => row.gap_effect_id)).size);
check('N077-VAL-012', 'P0 gaps with direct increment', 20, partiallyNarrowed);
check('N077-VAL-013', 'P0 gaps retained unaddressed', 18, remainingUnaddressed);
check('N077-VAL-014', 'company v05 row count', 307, v5.length);
check('N077-VAL-015', 'company v05 id uniqueness', 307, new Set(v5.map((row) => row.company_id)).size);
check('N077-VAL-016', 'immutable company field mismatch', 0, immutableMismatch);
check('N077-VAL-017', 'v05 enriched company count', 6, v5.filter((row) => row.n077_content_update_status === 'PRIMARY_SOURCE_CONTENT_ENRICHED_GAPS_REMAIN_OPEN_NO_UPGRADE').length);
check('N077-VAL-018', 'source update ids missing from v05', 0, sourceBacktrace.filter((update) => !v5.find((row) => row.company_id === update.company_id)?.n077_primary_source_update_ids.includes(update.source_update_id)).length);
check('N077-VAL-019', 'formal pool boundary drift', 0, v5.filter((row) => row.formal_pool_effect !== 'NO_AUTOMATIC_FORMAL_POOL_CHANGE').length);
check('N077-VAL-020', 'source backtrace forbidden upgrade literal count', 0, (sourceText.match(/FORMAL_POOL_APPROVED|EVIDENCE_UPGRADED|GAP_CLOSED/g) || []).length);
check('N077-VAL-021', 'v04 bytes unchanged', v4IdentityBefore.bytes, v4IdentityAfter.bytes);
check('N077-VAL-022', 'v04 sha256 unchanged', v4IdentityBefore.sha256, v4IdentityAfter.sha256);
check('N077-VAL-023', 'target original P0 gaps nonzero', 0, targetPriority.filter((row) => Number(row.original_p0_gap_count) < 1).length);
check('N077-VAL-024', 'gap closure count', 0, gapEffect.filter((row) => row.closure_effect !== 'NO_GAP_CLOSURE').length);
check('N077-VAL-025', 'evidence strength upgrade count', 0, sourceBacktrace.filter((row) => row.evidence_strength_effect !== 'NO_UPGRADE').length);
check('N077-VAL-026', 'automatic formal-pool change count', 0, sourceBacktrace.filter((row) => row.formal_pool_effect !== 'NO_AUTOMATIC_FORMAL_POOL_CHANGE').length);
check('N077-VAL-027', 'unauthorized inherited base-field mismatch', 0, unauthorizedBaseFieldMismatch);
check('N077-VAL-028', 'source update tags missing from v05 content fields', 0, sourceBacktrace.filter((update) => !Object.values(v5.find((row) => row.company_id === update.company_id) || {}).some((value) => String(value).includes(`〔${update.source_update_id}〕`))).length);
 
writeCsv(PATHS.validation, validation, ['check_id','check_description','expected','actual','status']);
const failed = validation.filter((row) => row.status === 'FAIL');
console.log(JSON.stringify({
  status: failed.length ? 'FAIL' : 'PASS',
  targetCompanies: targetPriority.length,
  primarySourceUpdates: sourceBacktrace.length,
  p0GapEffects: gapEffect.length,
  partiallyNarrowed,
  remainingUnaddressed,
  v5Companies: v5.length,
  validationPass: validation.filter((row) => row.status === 'PASS').length,
  validationFail: failed.length,
  outputs: Object.values(PATHS).filter((value) => ![PATHS.v4, PATHS.gapRegister].includes(value))
}, null, 2));
if (failed.length) process.exitCode = 1;