round-deposition-smoke.js 165 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451
  1. #!/usr/bin/env node
  2. const fs = require('fs');
  3. const os = require('os');
  4. const path = require('path');
  5. const { spawnSync } = require('child_process');
  6. const root = path.resolve(__dirname, '..');
  7. function main() {
  8. const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-round-deposition-'));
  9. const outputs = path.join(tmp, 'outputs');
  10. const statusDir = path.join(outputs, 'optimization-status-latest');
  11. const evidenceDir = path.join(outputs, 'evidence-index-latest');
  12. const handoffDir = path.join(outputs, 'optimization-handoff-latest');
  13. const proofGapDir = path.join(outputs, 'proof-gap-request-latest');
  14. const proofGapClosureDir = path.join(outputs, 'proof-gap-closure-latest');
  15. const feedbackLoopClosureDir = path.join(outputs, 'feedback-loop-closure-latest');
  16. const homepageEvidenceReadinessDir = path.join(outputs, 'homepage-evidence-readiness-latest');
  17. const intakeReadinessDir = path.join(outputs, 'intake-readiness-latest');
  18. const longRunReadinessDir = path.join(outputs, 'long-run-readiness-latest');
  19. const optimizationCompletionDir = path.join(outputs, 'optimization-completion-latest');
  20. const businessProofProgressDir = path.join(outputs, 'business-proof-progress-latest');
  21. const businessProofNextActionsDir = path.join(outputs, 'business-proof-next-actions-latest');
  22. const businessExecutionIndexDir = path.join(outputs, 'business-execution-index-latest');
  23. const realProofIntakeBundleDir = path.join(outputs, 'real-proof-intake-bundle-latest');
  24. const intakeFieldChecklistDir = path.join(outputs, 'intake-field-checklist-latest');
  25. const manualReviewLabelGuideDir = path.join(outputs, 'manual-review-label-guide-latest');
  26. const proofGapOperatorPackDir = path.join(outputs, 'proof-gap-operator-pack-latest');
  27. const proofGapSoftwareFormDir = path.join(outputs, 'tihao-proof-gap-software-form-latest');
  28. const latestFormIndexDir = path.join(outputs, 'latest-form-index-latest');
  29. const localSeedToIntakeWorklistDir = path.join(outputs, 'local-seed-to-intake-worklist-latest');
  30. const realGapMaterialAuditDir = path.join(outputs, 'real-gap-material-audit-latest');
  31. const realProofClosureWorkOrderDir = path.join(outputs, 'real-proof-closure-work-order-latest');
  32. const planExecutionStatusDir = path.join(outputs, 'plan-execution-status-latest');
  33. const outputDir = path.join(outputs, 'round-deposition-latest');
  34. for (const dir of [statusDir, evidenceDir, handoffDir, proofGapDir, proofGapClosureDir, feedbackLoopClosureDir, homepageEvidenceReadinessDir, intakeReadinessDir, longRunReadinessDir, optimizationCompletionDir, businessProofProgressDir, businessProofNextActionsDir, businessExecutionIndexDir, realProofIntakeBundleDir, intakeFieldChecklistDir, manualReviewLabelGuideDir, proofGapOperatorPackDir, proofGapSoftwareFormDir, latestFormIndexDir, localSeedToIntakeWorklistDir, realGapMaterialAuditDir, realProofClosureWorkOrderDir, planExecutionStatusDir]) fs.mkdirSync(dir, { recursive: true });
  35. const implementationLog = path.join(tmp, 'implementation-log.md');
  36. const proofActionOrder = path.join(tmp, 'business-proof-action-order.md');
  37. const videoAbPreflightEvidence = [
  38. 'passed=true',
  39. 'mode=unknown',
  40. 'collectionMode=unknown',
  41. 'generatedBy=unknown',
  42. 'provider=ok',
  43. 'preflight.readyForVideoAb=false',
  44. 'preflight.failureCount=4',
  45. 'preflight.generatedBy=acceptance:video-ab-preflight',
  46. 'preflight.proofLevel=not_business_proof',
  47. 'preflight.canCloseProofGap=false',
  48. 'runtimeCredentialPresent=false',
  49. 'companyResolved=false',
  50. 'vocSocialProviderTokenPresent=false',
  51. 'videoAnalysisTokenPresent=false'
  52. ].join(', ');
  53. const videoAbLiveProofRequirements = [
  54. 'proofContext.mode=live',
  55. 'proofContext.collectionMode=live',
  56. 'proofContext.generatedBy=acceptance:video-ab',
  57. 'proofContext.requiresRuntimeCredential=true',
  58. 'proofContext.requiresVocSocialProvider=true',
  59. 'proofContext.requiresVideoAnalysisProvider=true',
  60. 'videoAbPreflight.readyForVideoAb=true',
  61. 'videoAbPreflight.proofContext.requiresRuntimeCredential=true',
  62. 'videoAbPreflight.proofContext.requiresVocSocialProvider=true',
  63. 'videoAbPreflight.proofContext.requiresVideoAnalysisProvider=true',
  64. 'videoAbPreflight.company resolved for live run'
  65. ];
  66. const discoveredHistorySource = 'outputs/optimization-pipeline-latest/history-audit/historical-dataset-audit.json';
  67. const discoveredCustomerEffectSource = 'outputs/optimization-pipeline-latest/customer-effect-audit/customer-effect-summary.json';
  68. const historicalDatasetConcreteRequirements = [
  69. 'acceptance.readyForCustomerEffectProof=true',
  70. 'briefCount>=5',
  71. 'acceptance.minBriefsMet=true',
  72. 'items.length>=5'
  73. ];
  74. const customerEffectConcreteRequirements = [
  75. 'acceptance.overallPass=true',
  76. 'acceptance.customerSelectedRateMeasured=true',
  77. 'currentHistoryAudit.briefCount>=5'
  78. ];
  79. const historicalDatasetConcreteEvidence = 'briefCount=1, readyForCustomerEffectProof=false';
  80. const customerEffectConcreteEvidence = `overallPass=false, customerSelectedRate=0, referenceCustomerSelectedRate=0, manualSupplementReductionRate=1, historyAuditPath=${discoveredHistorySource}`;
  81. const videoAbLiveProofNextAction = `npm run acceptance:video-ab; missing proof: ${videoAbLiveProofRequirements.join('; ')}`;
  82. fs.writeFileSync(proofActionOrder, [
  83. '# 提号长期优化补证操作顺序',
  84. '',
  85. '- sample、smoke、dry-run 和 provider fallback 不能作为业务证明。',
  86. '- 客户效果不可宣称,除非 customer-effect:audit 通过。',
  87. '- npm run intake:readiness',
  88. '- npm run longrun:readiness',
  89. '- npm run customer-effect:audit',
  90. '- npm run optimization:completion -- --output outputs\\optimization-completion-latest',
  91. '- optimization:completion 必须 readyForClaim=true 后才可进入长期完成判断。'
  92. ].join('\n'), 'utf8');
  93. fs.writeFileSync(implementationLog, [
  94. '# 提号优化实施日志',
  95. '',
  96. '## 2026-06-07 每轮沉淀样例',
  97. '',
  98. '- 命令记录:npm.cmd run optimization:status;npm.cmd run evidence:index;npm.cmd run handoff:summary;npm.cmd run proof-gap:request;npm.cmd run proof-gap:closure;npm.cmd run intake:readiness;npm.cmd run longrun:readiness。',
  99. '- 输出目录:outputs/optimization-status-latest、outputs/evidence-index-latest、outputs/optimization-handoff-latest、outputs/proof-gap-request-latest、outputs/proof-gap-closure-latest、outputs/intake-readiness-latest、outputs/long-run-readiness-latest。',
  100. '- live 标记:liveEnabled=false,本轮不把 sample 当成真实证明。',
  101. '- 严格 provider 门禁:strict provider gates 未开启真实 live,只保留验收入口。',
  102. '- 视频资源真实性:真实视频资源未到位,video A/B 仍是 ready_not_proven。',
  103. '- failureCount=0,failedGateCount=0,overallPass=true 只代表本地门禁样例。',
  104. '- 软件端重复键=0,排名连续=true。',
  105. '- 人工复核指标和客户选中率仍需 review:metrics 与 customer-effect:audit。',
  106. '- 仍未证明边界:ready_not_proven=2,blocked_by_external_data=2。',
  107. '- proof-gap 缺口:真实证明缺口请求包 unresolvedCount=5,proof-gap closure openCount=4,仍需真实历史数据、候选视频和客户选择。'
  108. ].join('\n'), 'utf8');
  109. fs.writeFileSync(path.join(statusDir, 'optimization-status-summary.json'), JSON.stringify({
  110. complete: false,
  111. counts: { passed: 23, ready_not_proven: 2, blocked_by_external_data: 2 },
  112. items: [
  113. { id: 'software-table', status: 'passed' },
  114. { id: 'video-ab-proof', status: 'ready_not_proven' },
  115. { id: 'customer-effect-proof', status: 'blocked_by_external_data' }
  116. ]
  117. }, null, 2), 'utf8');
  118. fs.writeFileSync(path.join(statusDir, 'optimization-status-report.md'), '# 状态审计\n', 'utf8');
  119. fs.writeFileSync(path.join(evidenceDir, 'evidence-index-summary.json'), JSON.stringify({
  120. counts: { real_evidence: 1, smoke_or_local: 2, not_business_proof: 4 },
  121. byType: { 'optimization-status': 1, 'optimization-handoff': 1, 'proof-gap-request': 1, 'proof-gap-closure': 1, 'feedback-loop-closure': 1, 'homepage-evidence-readiness': 1, 'business-execution-index': 1, 'local-seed-to-intake-worklist': 1, 'real-gap-material-audit': 1, 'real-proof-closure-work-order': 1, 'video-ab-runtime-preflight': 1 },
  122. entries: [
  123. {
  124. type: 'video-ab-runtime-preflight',
  125. proofLevel: 'not_business_proof',
  126. status: 'not_ready',
  127. summary: 'readyForVideoAb=false, failureCount=4, generatedBy=acceptance:video-ab-preflight',
  128. next: '补齐运行时凭证后生成 video-hit-rate-summary.json;preflight 失败不证明视频提升。'
  129. }
  130. ]
  131. }, null, 2), 'utf8');
  132. fs.writeFileSync(path.join(evidenceDir, 'evidence-index-report.md'), '# 证据台账\n', 'utf8');
  133. const proofGapOperatorPackFixture = {
  134. passed: true,
  135. complete: false,
  136. directCustomerProof: false,
  137. proofLevel: 'not_business_proof',
  138. openCount: 5,
  139. rowCount: 5,
  140. gapIds: ['historical-dataset', 'video-real-candidate', 'video-ab-live-proof', 'live-provider-overnight-proof', 'manual-review-and-customer-effect'],
  141. fillFileCount: 3,
  142. recheckCommandCount: 7,
  143. ownerGroupCount: 3,
  144. ownerArtifactCount: 3,
  145. evidenceRowCount: 5,
  146. nextActionCount: 5,
  147. missingProofRequirementCount: 23,
  148. files: {
  149. summary: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack-summary.json',
  150. report: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack.md',
  151. csv: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack.csv',
  152. byOwnerDir: 'outputs/proof-gap-operator-pack-latest/by-owner'
  153. },
  154. ownerGroups: [
  155. {
  156. owner: '商务',
  157. actionCount: 2,
  158. topPriority: 1,
  159. fillFiles: ['outputs/data-intake-pack-latest/history-data-template.csv', 'outputs/data-intake-pack-latest/manual-review-template.csv'],
  160. recheckCommands: ['npm run intake:readiness', 'npm run history:audit', 'npm run customer-effect:audit'],
  161. gapIds: ['historical-dataset', 'manual-review-and-customer-effect']
  162. },
  163. {
  164. owner: '商务/投放',
  165. actionCount: 1,
  166. topPriority: 2,
  167. fillFiles: ['outputs/video-intake-pack-latest/video-resource-template.csv'],
  168. recheckCommands: ['npm run video:resource-readiness'],
  169. gapIds: ['video-real-candidate']
  170. },
  171. {
  172. owner: '技术/AI',
  173. actionCount: 2,
  174. topPriority: 3,
  175. fillFiles: ['outputs/video-intake-pack-latest/video-resource-template.csv', 'outputs/data-intake-pack-latest/history-data-template.csv'],
  176. recheckCommands: ['npm run acceptance:video-ab', 'npm run longrun:readiness', 'npm run overnight:quality'],
  177. gapIds: ['video-ab-live-proof', 'live-provider-overnight-proof']
  178. }
  179. ],
  180. ownerArtifacts: [
  181. {
  182. owner: '商务',
  183. markdown: 'outputs/proof-gap-operator-pack-latest/by-owner/business.md',
  184. csv: 'outputs/proof-gap-operator-pack-latest/by-owner/business.csv',
  185. actionCount: 2,
  186. topPriority: 1,
  187. gapIds: ['historical-dataset', 'manual-review-and-customer-effect'],
  188. evidenceRowCount: 2,
  189. nextActionCount: 2
  190. },
  191. {
  192. owner: '商务/投放',
  193. markdown: 'outputs/proof-gap-operator-pack-latest/by-owner/business-media.md',
  194. csv: 'outputs/proof-gap-operator-pack-latest/by-owner/business-media.csv',
  195. actionCount: 1,
  196. topPriority: 2,
  197. gapIds: ['video-real-candidate'],
  198. evidenceRowCount: 1,
  199. nextActionCount: 1
  200. },
  201. {
  202. owner: '技术/AI',
  203. markdown: 'outputs/proof-gap-operator-pack-latest/by-owner/tech-ai.md',
  204. csv: 'outputs/proof-gap-operator-pack-latest/by-owner/tech-ai.csv',
  205. actionCount: 2,
  206. topPriority: 3,
  207. gapIds: ['video-ab-live-proof', 'live-provider-overnight-proof'],
  208. evidenceRowCount: 2,
  209. nextActionCount: 2
  210. }
  211. ],
  212. rows: [
  213. { gapId: 'historical-dataset', owner: '商务', title: '真实历史 Brief 数据集', priority: 1, fillFiles: ['outputs/data-intake-pack-latest/history-data-template.csv'], recheckCommands: ['npm run intake:readiness', 'npm run history:audit'], evidence: historicalDatasetConcreteEvidence, nextAction: '补齐真实历史 Brief 后重跑 history:audit', missingProofRequirements: historicalDatasetConcreteRequirements, acceptance: 'historyReady=true', boundary: '补齐历史材料不证明客户效果。' },
  214. { gapId: 'video-real-candidate', owner: '商务/投放', title: '真实候选视频资源', priority: 2, fillFiles: ['outputs/video-intake-pack-latest/video-resource-template.csv'], recheckCommands: ['npm run video:resource-readiness'], evidence: 'realCandidate=0, failureCount=1', nextAction: '补真实候选视频后重跑 video:resource-readiness', missingProofRequirements: ['acceptance.readyForVideoAbPreflight=true', 'failureCount=0', 'counts.realCandidateRows>=1'], acceptance: 'readyForVideoAbPreflight=true', boundary: '补齐视频资源只证明 A/B 前置资源齐备,不证明客户效果。' },
  215. { gapId: 'video-ab-live-proof', owner: '技术/AI', title: '真实视频 A/B live proof', priority: 3, fillFiles: ['outputs/video-intake-pack-latest/video-resource-template.csv'], recheckCommands: ['npm run acceptance:video-ab'], evidence: 'mode=unknown, collectionMode=unknown', nextAction: '真实 provider 与真实视频到位后重跑 acceptance:video-ab', missingProofRequirements: ['proofContext.mode=live', 'proofContext.collectionMode=live', 'proofContext.generatedBy=acceptance:video-ab', 'proofContext.requiresRuntimeCredential=true', 'proofContext.requiresVocSocialProvider=true', 'proofContext.requiresVideoAnalysisProvider=true'], acceptance: 'proofContext.mode=live', boundary: 'sample 或接口 200 不证明视频分析提升提号率。' },
  216. { gapId: 'live-provider-overnight-proof', owner: '技术/AI', title: '真实 live/provider 长跑证明', priority: 4, fillFiles: ['outputs/data-intake-pack-latest/history-data-template.csv', 'outputs/video-intake-pack-latest/video-resource-template.csv'], recheckCommands: ['npm run longrun:readiness', 'npm run overnight:quality'], evidence: 'liveEnabled=false, overallPass=false', nextAction: 'longrun ready 后运行 overnight:quality', missingProofRequirements: ['manifest.liveEnabled=true', 'acceptance.overallPass=true'], acceptance: 'liveEnabled=true', boundary: '长跑通过只证明 provider/live 流程稳定,不单独证明客户效果。' },
  217. { gapId: 'manual-review-and-customer-effect', owner: '商务', title: '商务复核和客户效果证明', priority: 5, fillFiles: ['outputs/data-intake-pack-latest/manual-review-template.csv'], recheckCommands: ['npm run review:metrics', 'npm run customer-effect:audit'], evidence: customerEffectConcreteEvidence, nextAction: '补客户选择和人工补号量后重跑 customer-effect:audit', missingProofRequirements: customerEffectConcreteRequirements, acceptance: 'customer-effect:audit overallPass=true', boundary: '缺客户选择、历史基线或本轮人工补号量时,不得宣称客户效果。' }
  218. ]
  219. };
  220. Object.assign(proofGapOperatorPackFixture.rows.find(item => item.gapId === 'video-ab-live-proof'), {
  221. status: 'open',
  222. evidence: videoAbPreflightEvidence,
  223. nextAction: videoAbLiveProofNextAction,
  224. missingProofRequirements: videoAbLiveProofRequirements
  225. });
  226. const localSeedToIntakeWorklistFixture = {
  227. proofLevel: 'not_business_proof',
  228. materialType: 'seed_to_intake_worklist',
  229. directCustomerProof: false,
  230. canCloseProofGap: false,
  231. complete: false,
  232. counts: {
  233. historyDraftRows: 1,
  234. referenceSeedRows: 4,
  235. candidateSeedRows: 12,
  236. videoWorklistRows: 5,
  237. videoCandidateNeedsResourceRows: 3
  238. },
  239. targetFiles: [
  240. 'outputs/data-intake-pack-latest/history-data-template.csv',
  241. 'outputs/video-intake-pack-latest/video-resource-template.csv',
  242. 'outputs/data-intake-pack-latest/manual-review-template.csv'
  243. ],
  244. missingProofRequirements: [
  245. '至少 5 个真实历史 Brief',
  246. '真实候选视频 URL',
  247. '客户最终选中/拒绝记录'
  248. ],
  249. nextActions: [
  250. {
  251. owner: '商务',
  252. title: '把 history-intake-draft.csv 扩成真实 Brief',
  253. action: '补齐真实历史 Brief 和客户选择。',
  254. boundary: '补表草稿不证明客户效果'
  255. }
  256. ]
  257. };
  258. const localSeedToIntakeWorklistIndexedFixture = {
  259. ...localSeedToIntakeWorklistFixture,
  260. title: '本地种子转 intake 补表 worklist',
  261. usage: '用于把本地种子转成可转写补表草稿,不写入正式 intake 模板,不等同于客户效果证明。',
  262. exists: true,
  263. markdown: 'outputs/local-seed-to-intake-worklist-latest/local-seed-to-intake-worklist.md',
  264. csv: 'outputs/local-seed-to-intake-worklist-latest/local-seed-to-intake-worklist.csv',
  265. summary: 'outputs/local-seed-to-intake-worklist-latest/local-seed-to-intake-worklist-summary.json',
  266. historyDraft: 'outputs/local-seed-to-intake-worklist-latest/history-intake-draft.csv',
  267. videoWorklist: 'outputs/local-seed-to-intake-worklist-latest/video-resource-worklist.csv',
  268. candidateWorklist: 'outputs/local-seed-to-intake-worklist-latest/candidate-seed-worklist.csv',
  269. historyDraftRows: 1,
  270. referenceSeedRows: 4,
  271. candidateSeedRows: 12,
  272. videoWorklistRows: 5,
  273. videoCandidateNeedsResourceRows: 3,
  274. missingProofRequirementCount: 3,
  275. nextActionCount: 1
  276. };
  277. const realProofClosureWorkOrderOwnerArtifacts = [
  278. {
  279. owner: '商务',
  280. workOrderCount: 8,
  281. topPriority: 1,
  282. markdown: 'outputs/real-proof-closure-work-order-latest/by-owner/business.md',
  283. csv: 'outputs/real-proof-closure-work-order-latest/by-owner/business.csv',
  284. targetFiles: ['outputs/data-intake-pack-latest/history-data-template.csv', 'outputs/data-intake-pack-latest/manual-review-template.csv'],
  285. gapIds: ['historical-dataset', 'manual-review-and-customer-effect']
  286. },
  287. {
  288. owner: '商务/投放',
  289. workOrderCount: 5,
  290. topPriority: 20,
  291. markdown: 'outputs/real-proof-closure-work-order-latest/by-owner/business-media.md',
  292. csv: 'outputs/real-proof-closure-work-order-latest/by-owner/business-media.csv',
  293. targetFiles: ['outputs/video-intake-pack-latest/video-resource-template.csv'],
  294. gapIds: ['video-real-candidate']
  295. },
  296. {
  297. owner: '技术/AI',
  298. workOrderCount: 6,
  299. topPriority: 40,
  300. markdown: 'outputs/real-proof-closure-work-order-latest/by-owner/tech-ai.md',
  301. csv: 'outputs/real-proof-closure-work-order-latest/by-owner/tech-ai.csv',
  302. targetFiles: ['outputs/proof-gap-closure-latest/proof-gap-closure-summary.json', '<overnight输出目录>/aggregate-summary.json'],
  303. gapIds: ['video-ab-live-proof', 'live-provider-overnight-proof', 'optimization-pipeline']
  304. }
  305. ];
  306. const realProofClosureWorkOrders = [
  307. {
  308. id: 'intake-history-min-briefs',
  309. owner: '商务',
  310. targetFile: 'outputs/data-intake-pack-latest/history-data-template.csv',
  311. targetFields: ['brief编号', '客户原始Brief'],
  312. rowSelector: '新增至少 4 行真实历史 Brief。',
  313. requiredAction: '补 5-10 个真实历史 Brief。',
  314. acceptanceCommand: 'npm run intake:readiness -- --data-pack outputs\\data-intake-pack-latest --video-pack outputs\\video-intake-pack-latest --output outputs\\intake-readiness-latest',
  315. acceptance: 'historyReady=true。',
  316. requiresHumanRealMaterial: true,
  317. directCustomerProof: false,
  318. canCloseProofGap: false,
  319. proofLevel: 'not_business_proof'
  320. },
  321. {
  322. id: 'intake-review-customer-decision',
  323. owner: '商务',
  324. targetFile: 'outputs/data-intake-pack-latest/manual-review-template.csv',
  325. targetFields: ['客户选择', '反馈原因', '本轮人工补号量'],
  326. rowSelector: 'manual-review-template.csv 至少一批真实候选行。',
  327. requiredAction: '补客户最终选中/拒绝、负样本归因、反馈原因和本轮人工补号量。',
  328. acceptanceCommand: 'npm run customer-effect:audit -- --review-csv <已标注CSV> --history-audit <historical-dataset-audit.json> --current-manual-supplement-count <本轮人工补号量> --output <客户效果输出目录> --strict',
  329. acceptance: 'customer-effect:audit overallPass=true。',
  330. requiresHumanRealMaterial: true,
  331. directCustomerProof: false,
  332. canCloseProofGap: false,
  333. proofLevel: 'not_business_proof'
  334. },
  335. {
  336. id: 'video-real-candidate',
  337. owner: '商务/投放',
  338. targetFile: 'outputs/video-intake-pack-latest/video-resource-template.csv',
  339. targetFields: ['资源角色', '是否真实资源', '视频链接'],
  340. rowSelector: '新增或更新至少 1 行资源角色=候选视频、是否真实资源=是。',
  341. requiredAction: '为候选账号补真实视频 URL 和至少一种封面/ASR/帧图/正文证据。',
  342. acceptanceCommand: 'npm run video:resource-readiness -- --input outputs\\video-intake-pack-latest\\video-resource-template.csv --output outputs\\video-resource-readiness-latest --strict',
  343. acceptance: 'readyForVideoAbPreflight=true、realCandidateRows>=1。',
  344. requiresHumanRealMaterial: true,
  345. directCustomerProof: false,
  346. canCloseProofGap: false,
  347. proofLevel: 'not_business_proof'
  348. },
  349. {
  350. id: 'gap-video-ab-live-proof',
  351. owner: '技术/AI',
  352. targetFile: 'outputs/video-intake-pack-latest/video-resource-template.csv',
  353. targetFields: ['proofContext.mode', 'proofContext.collectionMode'],
  354. rowSelector: '真实视频 A/B 输出目录。',
  355. requiredAction: '真实视频资源和真实 provider 就绪后运行 acceptance:video-ab。',
  356. acceptanceCommand: 'npm run acceptance:video-ab',
  357. acceptance: 'proofContext.mode=live、collectionMode=live。',
  358. requiresHumanRealMaterial: true,
  359. directCustomerProof: false,
  360. canCloseProofGap: false,
  361. proofLevel: 'not_business_proof'
  362. },
  363. {
  364. id: 'completion-longrun-readiness',
  365. owner: '技术/AI',
  366. targetFile: '<overnight输出目录>/aggregate-summary.json',
  367. targetFields: ['manifest.liveEnabled', 'acceptance.overallPass'],
  368. rowSelector: '真实 live/provider overnight aggregate。',
  369. requiredAction: 'longrun:readiness ready=true 后再跑真实 provider overnight:quality。',
  370. acceptanceCommand: 'npm run longrun:readiness;真实 provider 就绪后运行 npm run overnight:quality',
  371. acceptance: 'liveEnabled=true、overallPass=true。',
  372. requiresHumanRealMaterial: true,
  373. directCustomerProof: false,
  374. canCloseProofGap: false,
  375. proofLevel: 'not_business_proof'
  376. }
  377. ];
  378. Object.assign(realProofClosureWorkOrders.find(item => item.id === 'gap-video-ab-live-proof'), {
  379. gapId: 'video-ab-live-proof',
  380. source: 'proof-gap-closure',
  381. currentEvidence: videoAbPreflightEvidence,
  382. missingProofRequirements: videoAbLiveProofRequirements
  383. });
  384. const realProofClosureWorkOrderFixture = {
  385. passed: true,
  386. complete: false,
  387. proofLevel: 'not_business_proof',
  388. materialType: 'real_proof_closure_work_order',
  389. directCustomerProof: false,
  390. canCloseProofGap: false,
  391. requiresHumanRealMaterial: true,
  392. workOrderCount: 19,
  393. ownerGroupCount: 3,
  394. seedSuggestionCount: 13,
  395. sourceState: {
  396. intakeOverallReady: false,
  397. intakeFailureCount: 9,
  398. videoReadyForAbPreflight: false,
  399. videoFailureCount: 1,
  400. realCandidateRows: 0,
  401. proofGapComplete: false,
  402. proofGapOpenCount: 5,
  403. optimizationReadyForClaim: false
  404. },
  405. workOrders: realProofClosureWorkOrders,
  406. ownerArtifacts: realProofClosureWorkOrderOwnerArtifacts
  407. };
  408. const realProofClosureWorkOrderIndexedFixture = {
  409. ...realProofClosureWorkOrderFixture,
  410. title: '真实证明闭环工单',
  411. usage: '用于把未关闭项拆成负责人、目标模板、字段、行范围、种子线索和复验命令;不写正式模板,不等同于客户效果证明。',
  412. exists: true,
  413. markdown: 'outputs/real-proof-closure-work-order-latest/real-proof-closure-work-order.md',
  414. csv: 'outputs/real-proof-closure-work-order-latest/real-proof-closure-work-order.csv',
  415. summary: 'outputs/real-proof-closure-work-order-latest/real-proof-closure-work-order-summary.json',
  416. proofGapOpenCount: 5,
  417. intakeFailureCount: 9,
  418. videoFailureCount: 1,
  419. realCandidateRows: 0
  420. };
  421. const realGapMaterialAuditFixture = {
  422. generatedAt: new Date().toISOString(),
  423. materialType: 'three_real_gap_material_audit',
  424. proofLevel: 'not_business_proof',
  425. directCustomerProof: false,
  426. canCloseProofGap: false,
  427. complete: false,
  428. gapCount: 3,
  429. materialFoundCount: 3,
  430. openGapCount: 3,
  431. gaps: [
  432. { gapId: 'historical-dataset', projectMaterialFound: true, canCloseNow: false },
  433. { gapId: 'video-ab-live-proof', projectMaterialFound: true, canCloseNow: false },
  434. { gapId: 'manual-review-and-customer-effect', projectMaterialFound: true, canCloseNow: false }
  435. ],
  436. markdown: 'outputs/real-gap-material-audit-latest/real-gap-material-audit.md',
  437. csv: 'outputs/real-gap-material-audit-latest/real-gap-material-audit.csv',
  438. summary: 'outputs/real-gap-material-audit-latest/real-gap-material-audit-summary.json'
  439. };
  440. const realGapMaterialAuditIndexedFixture = {
  441. title: '三缺口材料审计',
  442. usage: '用于确认三个真实缺口已有项目材料入口;不关闭 proof-gap,不证明提号效果。',
  443. exists: true,
  444. ...realGapMaterialAuditFixture
  445. };
  446. fs.writeFileSync(path.join(localSeedToIntakeWorklistDir, 'local-seed-to-intake-worklist-summary.json'), JSON.stringify(localSeedToIntakeWorklistFixture, null, 2), 'utf8');
  447. fs.writeFileSync(path.join(realGapMaterialAuditDir, 'real-gap-material-audit-summary.json'), JSON.stringify(realGapMaterialAuditFixture, null, 2), 'utf8');
  448. fs.writeFileSync(path.join(realGapMaterialAuditDir, 'real-gap-material-audit.md'), '# 三缺口材料审计\n\nmaterialFoundCount=3\ncanCloseProofGap=false\n', 'utf8');
  449. fs.writeFileSync(path.join(realGapMaterialAuditDir, 'real-gap-material-audit.csv'), 'gapId,projectMaterialFound,canCloseNow\nhistorical-dataset,true,false\nvideo-ab-live-proof,true,false\nmanual-review-and-customer-effect,true,false\n', 'utf8');
  450. fs.writeFileSync(path.join(realProofClosureWorkOrderDir, 'real-proof-closure-work-order-summary.json'), JSON.stringify(realProofClosureWorkOrderFixture, null, 2), 'utf8');
  451. fs.writeFileSync(path.join(handoffDir, 'optimization-handoff-summary.json'), JSON.stringify({
  452. complete: false,
  453. readyCapabilities: Array.from({ length: 23 }, (_, index) => ({ id: `cap-${index}` })),
  454. readyNotProven: [{ id: 'video-ab-proof' }],
  455. externalBlockers: [{ id: 'customer-effect-proof' }],
  456. nextCommands: [
  457. { command: 'npm run history:from-csv' },
  458. { command: 'npm run history:audit' },
  459. { command: 'npm run review:metrics' },
  460. { command: 'npm run customer-effect:audit' },
  461. { command: 'npm run proof-gap:request' },
  462. { command: 'npm run proof-gap:closure' },
  463. { command: 'npm run longrun:readiness -- --mode full-matrix' },
  464. { command: 'npm run latest-form:index' },
  465. { command: 'npm run evidence:index' }
  466. ],
  467. supportDocs: [
  468. { doc: 'docs/tihao-experience-optimization-plan.zh-CN.md' },
  469. { doc: 'docs/business-proof-action-order.zh-CN.md' }
  470. ],
  471. localSeedToIntakeWorklist: localSeedToIntakeWorklistIndexedFixture,
  472. realGapMaterialAudit: realGapMaterialAuditIndexedFixture,
  473. realProofClosureWorkOrder: realProofClosureWorkOrderIndexedFixture,
  474. businessProofProgress: {
  475. dir: 'outputs/business-proof-progress-latest',
  476. summary: 'outputs/business-proof-progress-latest/business-proof-progress-summary.json',
  477. report: 'outputs/business-proof-progress-latest/business-proof-progress-report.md',
  478. complete: false,
  479. counts: { pass: 4, fail: 2, pending: 2, blocked_by_external_data: 7 },
  480. operatorPackOwnerArtifactCount: 3,
  481. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  482. proofGapOperatorPackOwnerArtifactCount: 3,
  483. businessExecutionOperatorPackOwnerArtifactCount: 3,
  484. businessExecutionOperatorPackOwnerArtifactRowCount: 3
  485. },
  486. latestFormIndex: {
  487. summary: 'outputs/latest-form-index-latest/latest-form-index-summary.json',
  488. report: 'outputs/latest-form-index-latest/latest-form-index.md',
  489. passed: true,
  490. primaryFormCsv: 'outputs/tihao-proof-gap-software-form-latest/tihao-proof-gap-software-form.csv',
  491. clientListCsv: 'outputs/software-client-latest/software-client-list.final.csv',
  492. complete: false,
  493. actionCount: 5,
  494. proofOpenCount: 5,
  495. ownerGroupCount: 3,
  496. ownerArtifactCount: 3,
  497. sourceState: {
  498. progressComplete: false,
  499. proofGapOpenCount: 5
  500. },
  501. topActions: [
  502. {
  503. id: 'step-03',
  504. priority: 1,
  505. owner: '商务',
  506. title: '填真实历史 Brief',
  507. status: 'blocked_by_external_data',
  508. command: '填写 outputs\\data-intake-pack-latest\\history-data-template.csv',
  509. acceptance: 'historyReady=true'
  510. },
  511. {
  512. id: 'step-04',
  513. priority: 2,
  514. owner: '商务/投放',
  515. title: '填真实视频资源',
  516. status: 'blocked_by_external_data',
  517. command: '填写 outputs\\video-intake-pack-latest\\video-resource-template.csv',
  518. acceptance: 'videoReady=true'
  519. },
  520. {
  521. id: 'step-12',
  522. priority: 4,
  523. owner: '商务',
  524. title: '人工复核标注',
  525. status: 'blocked_by_external_data',
  526. command: '填写 outputs\\data-intake-pack-latest\\manual-review-template.csv',
  527. acceptance: '客户选择齐全'
  528. },
  529. {
  530. id: 'gap-video-ab-live-proof',
  531. priority: 24,
  532. owner: '技术/AI',
  533. title: '真实视频 A/B 验收',
  534. status: 'open',
  535. command: 'npm run acceptance:video-ab',
  536. acceptance: '真实 provider 下通过'
  537. },
  538. {
  539. id: 'gap-live-provider-overnight-proof',
  540. priority: 25,
  541. owner: '技术/AI',
  542. title: '真实 live/provider 长跑证明',
  543. status: 'open',
  544. command: 'npm run longrun:readiness;真实 provider 就绪后运行 npm run overnight:quality',
  545. acceptance: 'liveEnabled=true'
  546. }
  547. ],
  548. businessExecutionIndex: {
  549. markdown: 'outputs/business-execution-index-latest/business-execution-index.md',
  550. csv: 'outputs/business-execution-index-latest/business-execution-index.csv',
  551. summary: 'outputs/business-execution-index-latest/business-execution-index-summary.json',
  552. directCustomerProof: false,
  553. rowCount: 15,
  554. operatorPackOwnerArtifactCount: 3,
  555. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  556. fieldOwnerRowCount: 1,
  557. recheckCommandRowCount: 1
  558. },
  559. planExecutionStatus: {
  560. markdown: 'outputs/plan-execution-status-latest/plan-execution-status.md',
  561. csv: 'outputs/plan-execution-status-latest/plan-execution-status.csv',
  562. summary: 'outputs/plan-execution-status-latest/plan-execution-status-summary.json',
  563. passed: true,
  564. complete: false,
  565. directCustomerProof: false,
  566. rowCount: 8,
  567. proofOpenCount: 5,
  568. operatorPackOwnerArtifactCount: 3,
  569. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  570. businessExecutionOperatorPackOwnerArtifactCount: 3,
  571. businessExecutionOperatorPackOwnerArtifactRowCount: 3
  572. },
  573. proofGapOperatorPack: {
  574. ...proofGapOperatorPackFixture,
  575. markdown: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack.md',
  576. csv: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack.csv',
  577. summary: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack-summary.json'
  578. },
  579. longRunReadiness: {
  580. report: 'outputs/long-run-readiness-latest/long-run-readiness-report.md',
  581. summary: 'outputs/long-run-readiness-latest/long-run-readiness-summary.json',
  582. mode: 'full-matrix',
  583. ready: false,
  584. directCustomerProof: false,
  585. proofLevel: 'not_business_proof',
  586. passCount: 1,
  587. failCount: 5,
  588. warnCount: 0
  589. },
  590. localSeedToIntakeWorklist: localSeedToIntakeWorklistIndexedFixture,
  591. realGapMaterialAudit: realGapMaterialAuditIndexedFixture,
  592. realProofClosureWorkOrder: realProofClosureWorkOrderIndexedFixture,
  593. intakeFieldChecklist: {
  594. markdown: 'outputs/intake-field-checklist-latest/intake-field-checklist.md',
  595. csv: 'outputs/intake-field-checklist-latest/intake-field-checklist.csv',
  596. ownerGroups: [
  597. {
  598. owner: '商务',
  599. section: 'history',
  600. itemCount: 2,
  601. files: ['outputs/data-intake-pack-latest/history-data-template.csv'],
  602. nextAction: '补真实历史 Brief',
  603. acceptance: 'historyReady=true',
  604. boundary: '补齐材料,不证明客户效果'
  605. },
  606. {
  607. owner: '商务/投放',
  608. section: 'video',
  609. itemCount: 2,
  610. files: ['outputs/video-intake-pack-latest/video-resource-template.csv'],
  611. nextAction: '补真实视频 URL',
  612. acceptance: 'videoReady=true',
  613. boundary: '补齐材料,不证明客户效果'
  614. }
  615. ],
  616. recheckCommands: [
  617. {
  618. stage: '真实材料预审',
  619. owner: '技术/AI',
  620. command: 'npm run intake:readiness -- --data-pack outputs\\data-intake-pack-latest --video-pack outputs\\video-intake-pack-latest --output outputs\\intake-readiness-latest',
  621. acceptance: 'overallReady=true',
  622. boundary: '预审通过不证明客户效果'
  623. },
  624. {
  625. stage: '刷新本轮交接',
  626. owner: '技术/AI',
  627. command: 'npm run round:refresh -- --output-root outputs --strict',
  628. acceptance: 'round-deposition.passed=true',
  629. boundary: '刷新交接不证明业务效果'
  630. },
  631. {
  632. stage: '客户效果审计',
  633. owner: '技术/AI',
  634. command: 'npm run customer-effect:audit -- --review-csv <已标注CSV> --history-audit <historical-dataset-audit.json> --current-manual-supplement-count <本轮人工补号量> --output <客户效果输出目录> --strict',
  635. acceptance: 'overallPass=true',
  636. boundary: '缺客户选择不得宣称效果'
  637. },
  638. {
  639. stage: '视频 A/B 验收',
  640. owner: '技术/AI',
  641. command: 'npm run acceptance:video-ab',
  642. acceptance: '真实 provider 下通过',
  643. boundary: 'sample 不证明视频提升提号率'
  644. }
  645. ]
  646. },
  647. repairActions: {
  648. dataIntake: {
  649. csv: 'outputs/intake-readiness-latest/intake-readiness-repair-actions.csv',
  650. repairActionCount: 9
  651. },
  652. videoResource: {
  653. csv: 'outputs/video-resource-readiness-latest/video-resource-repair-actions.csv',
  654. repairActionCount: 1
  655. },
  656. homepageEvidence: {
  657. csv: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-repair-actions.csv',
  658. repairActionCount: 2
  659. }
  660. },
  661. ownerArtifacts: [
  662. {
  663. owner: '商务',
  664. repairArtifacts: [
  665. { csv: 'outputs/intake-readiness-latest/intake-readiness-repair-actions.csv', actionCount: 6 }
  666. ]
  667. },
  668. {
  669. owner: '商务/投放',
  670. repairArtifacts: [
  671. { csv: 'outputs/video-resource-readiness-latest/video-resource-repair-actions.csv', actionCount: 1 },
  672. { csv: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-repair-actions.csv', actionCount: 1 }
  673. ]
  674. },
  675. {
  676. owner: 'tech-ai',
  677. repairArtifacts: [
  678. { csv: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-repair-actions.csv', actionCount: 1 }
  679. ]
  680. }
  681. ],
  682. manualReviewLabelGuide: {
  683. markdown: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.md',
  684. csv: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.csv',
  685. summary: 'outputs/manual-review-label-guide-latest/manual-review-label-guide-summary.json',
  686. passed: true,
  687. directCustomerProof: false,
  688. proofLevel: 'smoke_or_local',
  689. labelCount: 10,
  690. positiveLabelCount: 2,
  691. negativeLabelCount: 6,
  692. attributionTypeCount: 8,
  693. negativeLabelsRequireAttribution: true
  694. },
  695. businessFillGuide: {
  696. title: '商务填表执行视图',
  697. directCustomerProof: false,
  698. proofLevel: 'smoke_or_local',
  699. rowCount: 2,
  700. rows: [
  701. {
  702. order: 1,
  703. owner: '鍟嗗姟',
  704. section: 'history',
  705. file: 'outputs/data-intake-pack-latest/history-data-template.csv',
  706. firstItemIds: ['FIELD-001'],
  707. issueCount: 2,
  708. fillAction: '琛ョ湡瀹炲巻鍙?Brief',
  709. recheckCommand: 'npm run intake:readiness -- --data-pack outputs\\data-intake-pack-latest --video-pack outputs\\video-intake-pack-latest --output outputs\\intake-readiness-latest',
  710. acceptance: 'historyReady=true',
  711. boundary: '补齐材料,不证明客户效果'
  712. },
  713. {
  714. order: 2,
  715. owner: '鍟嗗姟/鎶曟斁',
  716. section: 'video',
  717. file: 'outputs/video-intake-pack-latest/video-resource-template.csv',
  718. firstItemIds: ['FIELD-003'],
  719. issueCount: 2,
  720. fillAction: '琛ョ湡瀹炶棰?URL',
  721. recheckCommand: 'npm run video:resource-readiness -- --input outputs\\video-intake-pack-latest\\video-resource-template.csv --output outputs\\video-resource-readiness-latest --strict',
  722. acceptance: 'videoReady=true',
  723. boundary: '补齐材料,不证明客户效果'
  724. }
  725. ],
  726. guardrail: '本视图只帮助商务按表补齐真实材料,不代表客户效果已达标。'
  727. }
  728. },
  729. planExecutionStatus: {
  730. markdown: 'outputs/plan-execution-status-latest/plan-execution-status.md',
  731. csv: 'outputs/plan-execution-status-latest/plan-execution-status.csv',
  732. summary: 'outputs/plan-execution-status-latest/plan-execution-status-summary.json',
  733. passed: true,
  734. complete: false,
  735. directCustomerProof: false,
  736. rowCount: 8,
  737. proofOpenCount: 5,
  738. operatorPackOwnerArtifactCount: 3,
  739. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  740. businessExecutionOperatorPackOwnerArtifactCount: 3,
  741. businessExecutionOperatorPackOwnerArtifactRowCount: 3
  742. },
  743. longRunReadiness: {
  744. report: 'outputs/long-run-readiness-latest/long-run-readiness-report.md',
  745. summary: 'outputs/long-run-readiness-latest/long-run-readiness-summary.json',
  746. mode: 'full-matrix',
  747. ready: false,
  748. directCustomerProof: false,
  749. proofLevel: 'not_business_proof',
  750. passCount: 1,
  751. failCount: 5,
  752. warnCount: 0
  753. },
  754. businessProofNextActions: {
  755. complete: false,
  756. actionCount: 5,
  757. ownerGroupCount: 3,
  758. ownerArtifactCount: 3,
  759. sourceState: {
  760. progressComplete: false,
  761. proofGapOpenCount: 5
  762. },
  763. topActions: [
  764. {
  765. id: 'step-03',
  766. priority: 1,
  767. owner: '商务',
  768. title: '填真实历史 Brief',
  769. status: 'blocked_by_external_data',
  770. command: '填写 outputs\\data-intake-pack-latest\\history-data-template.csv',
  771. acceptance: 'historyReady=true'
  772. },
  773. {
  774. id: 'step-04',
  775. priority: 2,
  776. owner: '商务/投放',
  777. title: '填真实视频资源',
  778. status: 'blocked_by_external_data',
  779. command: '填写 outputs\\video-intake-pack-latest\\video-resource-template.csv',
  780. acceptance: 'videoReady=true'
  781. },
  782. {
  783. id: 'step-12',
  784. priority: 4,
  785. owner: '商务',
  786. title: '人工复核标注',
  787. status: 'blocked_by_external_data',
  788. command: '填写 outputs\\data-intake-pack-latest\\manual-review-template.csv',
  789. acceptance: '客户选择齐全'
  790. },
  791. {
  792. id: 'gap-video-ab-live-proof',
  793. priority: 24,
  794. owner: '技术/AI',
  795. title: '真实视频 A/B 验收',
  796. status: 'open',
  797. command: 'npm run acceptance:video-ab',
  798. acceptance: '真实 provider 下通过'
  799. },
  800. {
  801. id: 'gap-live-provider-overnight-proof',
  802. priority: 25,
  803. owner: '技术/AI',
  804. title: '真实 live/provider 长跑证明',
  805. status: 'open',
  806. command: 'npm run longrun:readiness;真实 provider 就绪后运行 npm run overnight:quality',
  807. acceptance: 'liveEnabled=true'
  808. }
  809. ],
  810. ownerArtifacts: [
  811. {
  812. owner: '商务',
  813. repairArtifacts: [
  814. { csv: 'outputs/intake-readiness-latest/intake-readiness-repair-actions.csv', actionCount: 6 }
  815. ]
  816. },
  817. {
  818. owner: '商务/投放',
  819. repairArtifacts: [
  820. { csv: 'outputs/video-resource-readiness-latest/video-resource-repair-actions.csv', actionCount: 1 },
  821. { csv: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-repair-actions.csv', actionCount: 1 }
  822. ]
  823. },
  824. {
  825. owner: '技术/AI',
  826. repairArtifacts: [
  827. { csv: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-repair-actions.csv', actionCount: 1 }
  828. ]
  829. }
  830. ]
  831. },
  832. manualReviewLabelGuide: {
  833. markdown: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.md',
  834. csv: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.csv',
  835. summary: 'outputs/manual-review-label-guide-latest/manual-review-label-guide-summary.json',
  836. passed: true,
  837. directCustomerProof: false,
  838. proofLevel: 'smoke_or_local',
  839. labelCount: 10,
  840. positiveLabelCount: 2,
  841. negativeLabelCount: 6,
  842. attributionTypeCount: 8,
  843. negativeLabelsRequireAttribution: true
  844. },
  845. manualReviewLabelGuide: {
  846. markdown: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.md',
  847. csv: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.csv',
  848. summary: 'outputs/manual-review-label-guide-latest/manual-review-label-guide-summary.json',
  849. passed: true,
  850. directCustomerProof: false,
  851. proofLevel: 'smoke_or_local',
  852. labelCount: 10,
  853. positiveLabelCount: 2,
  854. negativeLabelCount: 6,
  855. attributionTypeCount: 8,
  856. negativeLabelsRequireAttribution: true
  857. },
  858. businessFillGuide: {
  859. title: '商务填表执行视图',
  860. directCustomerProof: false,
  861. proofLevel: 'smoke_or_local',
  862. rowCount: 2,
  863. rows: [
  864. {
  865. order: 1,
  866. owner: '鍟嗗姟',
  867. section: 'history',
  868. file: 'outputs/data-intake-pack-latest/history-data-template.csv',
  869. firstItemIds: ['FIELD-001'],
  870. issueCount: 2,
  871. fillAction: '琛ョ湡瀹炲巻鍙?Brief',
  872. recheckCommand: 'npm run intake:readiness -- --data-pack outputs\\data-intake-pack-latest --video-pack outputs\\video-intake-pack-latest --output outputs\\intake-readiness-latest',
  873. acceptance: 'historyReady=true',
  874. boundary: '补齐材料,不证明客户效果'
  875. },
  876. {
  877. order: 2,
  878. owner: '鍟嗗姟/鎶曟斁',
  879. section: 'video',
  880. file: 'outputs/video-intake-pack-latest/video-resource-template.csv',
  881. firstItemIds: ['FIELD-003'],
  882. issueCount: 2,
  883. fillAction: '琛ョ湡瀹炶棰?URL',
  884. recheckCommand: 'npm run acceptance:video-ab',
  885. acceptance: 'videoReady=true',
  886. boundary: '补齐材料,不证明客户效果'
  887. }
  888. ],
  889. guardrail: '本视图只帮助商务按表补齐真实材料,不代表客户效果已达标。'
  890. },
  891. proofGapOperatorPack: {
  892. ...proofGapOperatorPackFixture,
  893. markdown: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack.md',
  894. csv: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack.csv',
  895. summary: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack-summary.json'
  896. },
  897. businessExecutionIndex: {
  898. summary: 'outputs/business-execution-index-latest/business-execution-index-summary.json',
  899. report: 'outputs/business-execution-index-latest/business-execution-index.md',
  900. csv: 'outputs/business-execution-index-latest/business-execution-index.csv',
  901. passed: true,
  902. rowCount: 15,
  903. repairRowCount: 2,
  904. operatorPackOwnerArtifactRowCount: 3,
  905. operatorPackOwnerArtifactCount: 3,
  906. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  907. fieldOwnerRowCount: 1,
  908. recheckCommandRowCount: 1,
  909. proofOpenCount: 5,
  910. directCustomerProof: false,
  911. longRunReadiness: {
  912. report: 'outputs/long-run-readiness-latest/long-run-readiness-report.md',
  913. summary: 'outputs/long-run-readiness-latest/long-run-readiness-summary.json',
  914. status: 'blocked',
  915. actionCount: 5,
  916. ready: false,
  917. failCount: 5,
  918. expectedArtifact: 'outputs/long-run-readiness-latest/long-run-readiness-summary.json',
  919. acceptance: 'ready=false,failCount=5',
  920. boundary: '长跑前置门禁只判断启动条件,不证明客户效果;ready=false 时不能启动或宣称 full-matrix/live 长跑完成。',
  921. directCustomerProof: false,
  922. proofLevel: 'not_business_proof'
  923. },
  924. optimizationCompletion: {
  925. report: 'outputs/optimization-completion-latest/optimization-completion-report.md',
  926. summary: 'outputs/optimization-completion-latest/optimization-completion-summary.json',
  927. status: 'blocked',
  928. actionCount: 3,
  929. complete: false,
  930. readyForClaim: false,
  931. proofGapOpenCount: 5,
  932. blockingReasonCount: 3,
  933. expectedArtifact: 'outputs/optimization-completion-latest/optimization-completion-summary.json',
  934. acceptance: 'complete=false,readyForClaim=false,proofGapOpenCount=5,blockingReasons=3',
  935. boundary: '优化完成度审计只判断能否进入完成声明,不证明客户效果;readyForClaim=false 时不得宣称提号率提升、客户效果达标或人工补号量下降。',
  936. directCustomerProof: false,
  937. proofLevel: 'not_business_proof'
  938. }
  939. },
  940. optimizationCompletion: {
  941. report: 'outputs/optimization-completion-latest/optimization-completion-report.md',
  942. summary: 'outputs/optimization-completion-latest/optimization-completion-summary.json',
  943. complete: false,
  944. readyForClaim: false,
  945. proofGapOpenCount: 5,
  946. blockingReasonCount: 3,
  947. directCustomerProof: false,
  948. proofLevel: 'not_business_proof',
  949. canClaim: {
  950. tihaoRateImproved: false,
  951. customerEffectAchieved: false,
  952. manualSupplementReduced: false
  953. },
  954. nextRequiredCommandCount: 5
  955. },
  956. intakeFieldChecklist: {
  957. summary: 'outputs/intake-field-checklist-latest/intake-field-checklist-summary.json',
  958. report: 'outputs/intake-field-checklist-latest/intake-field-checklist.md',
  959. csv: 'outputs/intake-field-checklist-latest/intake-field-checklist.csv',
  960. passed: true,
  961. itemCount: 4,
  962. missingRequiredCount: 2,
  963. placeholderCount: 2,
  964. ownerGroups: [
  965. {
  966. owner: '商务',
  967. section: 'history',
  968. itemCount: 2,
  969. missingRequiredCount: 1,
  970. placeholderCount: 1,
  971. files: ['outputs/data-intake-pack-latest/history-data-template.csv'],
  972. nextAction: '补真实历史 Brief',
  973. acceptance: 'historyReady=true',
  974. boundary: '补齐材料,不证明客户效果'
  975. },
  976. {
  977. owner: '商务/投放',
  978. section: 'video',
  979. itemCount: 2,
  980. missingRequiredCount: 1,
  981. placeholderCount: 1,
  982. files: ['outputs/video-intake-pack-latest/video-resource-template.csv'],
  983. nextAction: '补真实视频 URL',
  984. acceptance: 'videoReady=true',
  985. boundary: '补齐材料,不证明客户效果'
  986. }
  987. ],
  988. manualReviewLabelGuide: {
  989. markdown: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.md',
  990. csv: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.csv',
  991. summary: 'outputs/manual-review-label-guide-latest/manual-review-label-guide-summary.json',
  992. passed: true,
  993. directCustomerProof: false,
  994. proofLevel: 'smoke_or_local',
  995. labelCount: 10,
  996. positiveLabelCount: 2,
  997. negativeLabelCount: 6,
  998. attributionTypeCount: 8,
  999. negativeLabelsRequireAttribution: true
  1000. },
  1001. recheckCommands: [
  1002. {
  1003. stage: '真实材料预审',
  1004. owner: '技术/AI',
  1005. command: 'npm run intake:readiness -- --data-pack outputs\\data-intake-pack-latest --video-pack outputs\\video-intake-pack-latest --output outputs\\intake-readiness-latest',
  1006. acceptance: 'overallReady=true',
  1007. boundary: '预审通过不证明客户效果'
  1008. },
  1009. {
  1010. stage: '刷新本轮交接',
  1011. owner: '技术/AI',
  1012. command: 'npm run round:refresh -- --output-root outputs --strict',
  1013. acceptance: 'round-deposition.passed=true',
  1014. boundary: '刷新交接不证明业务效果'
  1015. },
  1016. {
  1017. stage: '客户效果审计',
  1018. owner: '技术/AI',
  1019. command: 'npm run customer-effect:audit -- --review-csv <已标注CSV> --history-audit <historical-dataset-audit.json> --current-manual-supplement-count <本轮人工补号量> --output <客户效果输出目录> --strict',
  1020. acceptance: 'overallPass=true',
  1021. boundary: '缺客户选择不得宣称效果'
  1022. },
  1023. {
  1024. stage: '视频 A/B 验收',
  1025. owner: '技术/AI',
  1026. command: 'npm run acceptance:video-ab',
  1027. acceptance: '真实 provider 下通过',
  1028. boundary: 'sample 不证明视频提升提号率'
  1029. }
  1030. ],
  1031. directCustomerProof: false
  1032. },
  1033. proofGapClosure: {
  1034. summary: 'outputs/proof-gap-closure-latest/proof-gap-closure-summary.json',
  1035. report: 'outputs/proof-gap-closure-latest/proof-gap-closure-report.md',
  1036. sourceFiles: {
  1037. history: discoveredHistorySource,
  1038. customerEffect: discoveredCustomerEffectSource
  1039. },
  1040. complete: false,
  1041. intakeReady: false,
  1042. closedCount: 0,
  1043. openCount: 5,
  1044. businessClosedCount: 0,
  1045. businessOpenCount: 5,
  1046. businessGapCount: 5,
  1047. totalRows: 6,
  1048. precheckRowCount: 1,
  1049. precheckClosedCount: 0,
  1050. precheckOpenCount: 1,
  1051. countSemantics: {
  1052. openCount: 'business_gap_open_count_excludes_precheck_rows',
  1053. closedCount: 'business_gap_closed_count_excludes_precheck_rows',
  1054. businessOpenCount: 'same_as_openCount',
  1055. businessClosedCount: 'same_as_closedCount',
  1056. precheckOpenCount: 'precheck_rows_reported_separately'
  1057. },
  1058. rows: [
  1059. { id: 'intake-readiness', status: 'open', missingProofRequirements: ['acceptance.overallReady=true', 'failureCount=0'] },
  1060. { id: 'historical-dataset', status: 'open', evidence: historicalDatasetConcreteEvidence, missingProofRequirements: historicalDatasetConcreteRequirements },
  1061. { id: 'video-real-candidate', status: 'open', missingProofRequirements: ['acceptance.readyForVideoAbPreflight=true', 'failureCount=0', 'counts.realCandidateRows>=1'] },
  1062. {
  1063. id: 'video-ab-live-proof',
  1064. status: 'open',
  1065. missingProofRequirements: [
  1066. 'proofContext.mode=live',
  1067. 'proofContext.collectionMode=live',
  1068. 'proofContext.generatedBy=acceptance:video-ab',
  1069. 'proofContext.requiresRuntimeCredential=true',
  1070. 'proofContext.requiresVocSocialProvider=true',
  1071. 'proofContext.requiresVideoAnalysisProvider=true'
  1072. ]
  1073. },
  1074. { id: 'manual-review-and-customer-effect', status: 'open', evidence: customerEffectConcreteEvidence, missingProofRequirements: customerEffectConcreteRequirements },
  1075. { id: 'live-provider-overnight-proof', status: 'open', missingProofRequirements: ['manifest.liveEnabled=true', 'acceptance.overallPass=true'] }
  1076. ]
  1077. },
  1078. feedbackLoopClosure: {
  1079. summary: 'outputs/feedback-loop-closure-latest/feedback-loop-closure-summary.json',
  1080. report: 'outputs/feedback-loop-closure-latest/feedback-loop-closure-report.md',
  1081. csv: 'outputs/feedback-loop-closure-latest/feedback-loop-closure.csv',
  1082. passed: false,
  1083. complete: false,
  1084. directCustomerProof: false,
  1085. proofLevel: 'not_business_proof',
  1086. negativeFeedbackCount: 0,
  1087. blockedCreatorCount: 0,
  1088. leakedCount: 0,
  1089. teamRuleSuggestionCount: 0,
  1090. missingInputs: ['feedback csv', 'preference memory json', 'second-round sourcing result json']
  1091. },
  1092. homepageEvidenceReadiness: {
  1093. summary: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-readiness-summary.json',
  1094. report: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-readiness-report.md',
  1095. csv: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-repair-actions.csv',
  1096. ready: false,
  1097. complete: false,
  1098. directCustomerProof: false,
  1099. proofLevel: 'not_business_proof',
  1100. failureCount: 2,
  1101. providerEvidenceCreators: 0,
  1102. creatorsWithPosts: 0,
  1103. creatorsWithEnoughRecentPosts: 0,
  1104. repairActionCount: 2
  1105. },
  1106. guardrails: [
  1107. '不能把 sample、smoke、dry-run 当成客户效果证明。',
  1108. '没有客户选择时不能声明客户效果完成。'
  1109. ]
  1110. }, null, 2), 'utf8');
  1111. fs.writeFileSync(path.join(handoffDir, 'optimization-handoff-report.md'), '# 提号优化交接摘要\n', 'utf8');
  1112. fs.writeFileSync(path.join(proofGapDir, 'proof-gap-request-summary.json'), JSON.stringify({
  1113. complete: false,
  1114. unresolvedCount: 5,
  1115. rows: [
  1116. {
  1117. id: 'historical-dataset',
  1118. status: 'missing_real_data',
  1119. templateCommand: 'npm run data:intake-template -- --output outputs\\data-intake-pack-latest',
  1120. templateArtifact: 'outputs\\data-intake-pack-latest\\history-data-template.csv'
  1121. },
  1122. {
  1123. id: 'video-real-candidate',
  1124. status: 'missing_real_data',
  1125. templateCommand: 'npm run video:intake-template -- --output outputs\\video-intake-pack-latest',
  1126. templateArtifact: 'outputs\\video-intake-pack-latest\\video-resource-template.csv'
  1127. }
  1128. ]
  1129. }, null, 2), 'utf8');
  1130. fs.writeFileSync(path.join(proofGapDir, 'proof-gap-request-report.md'), '# 提号真实证明缺口请求包\n\n| ID | 模板命令 | 模板产物 |\n| --- | --- | --- |\n| historical-dataset | `npm run data:intake-template` | history-data-template.csv |\n', 'utf8');
  1131. fs.writeFileSync(path.join(proofGapDir, 'proof-gap-request-table.csv'), '缺口ID,负责人,状态,模板命令,模板产物\nhistorical-dataset,商务,missing_real_data,npm run data:intake-template,history-data-template.csv\n', 'utf8');
  1132. fs.writeFileSync(path.join(proofGapClosureDir, 'proof-gap-closure-summary.json'), JSON.stringify({
  1133. complete: false,
  1134. intakeReady: false,
  1135. sourceFiles: {
  1136. history: discoveredHistorySource,
  1137. customerEffect: discoveredCustomerEffectSource
  1138. },
  1139. closedCount: 0,
  1140. openCount: 5,
  1141. businessClosedCount: 0,
  1142. businessOpenCount: 5,
  1143. businessGapCount: 5,
  1144. totalRows: 6,
  1145. precheckRowCount: 1,
  1146. precheckClosedCount: 0,
  1147. precheckOpenCount: 1,
  1148. videoAbPreflightReadyForVideoAb: false,
  1149. videoAbPreflightFailureCount: 4,
  1150. countSemantics: {
  1151. openCount: 'business_gap_open_count_excludes_precheck_rows',
  1152. closedCount: 'business_gap_closed_count_excludes_precheck_rows',
  1153. businessOpenCount: 'same_as_openCount',
  1154. businessClosedCount: 'same_as_closedCount',
  1155. precheckOpenCount: 'precheck_rows_reported_separately'
  1156. },
  1157. rows: [
  1158. { id: 'intake-readiness', status: 'open', missingProofRequirements: ['acceptance.overallReady=true', 'failureCount=0'] },
  1159. { id: 'historical-dataset', status: 'open', evidence: historicalDatasetConcreteEvidence, missingProofRequirements: historicalDatasetConcreteRequirements },
  1160. { id: 'video-real-candidate', status: 'open', missingProofRequirements: ['acceptance.readyForVideoAbPreflight=true', 'failureCount=0', 'counts.realCandidateRows>=1'] },
  1161. {
  1162. id: 'video-ab-live-proof',
  1163. status: 'open',
  1164. evidence: 'passed=true, mode=unknown, collectionMode=unknown, generatedBy=unknown, provider=ok; preflight.readyForVideoAb=false, preflight.failureCount=4, preflight.generatedBy=acceptance:video-ab-preflight, runtimeCredentialPresent=false',
  1165. missingProofRequirements: [
  1166. 'proofContext.mode=live',
  1167. 'proofContext.collectionMode=live',
  1168. 'proofContext.generatedBy=acceptance:video-ab',
  1169. 'proofContext.requiresRuntimeCredential=true',
  1170. 'proofContext.requiresVocSocialProvider=true',
  1171. 'proofContext.requiresVideoAnalysisProvider=true',
  1172. 'videoAbPreflight.readyForVideoAb=true',
  1173. 'videoAbPreflight.company resolved for live run'
  1174. ]
  1175. },
  1176. { id: 'manual-review-and-customer-effect', status: 'open', evidence: customerEffectConcreteEvidence, missingProofRequirements: customerEffectConcreteRequirements },
  1177. { id: 'live-provider-overnight-proof', status: 'open', missingProofRequirements: ['manifest.liveEnabled=true', 'acceptance.overallPass=true'] }
  1178. ]
  1179. }, null, 2), 'utf8');
  1180. fs.writeFileSync(path.join(proofGapClosureDir, 'proof-gap-closure-report.md'), '# 提号真实证明缺口关闭审计\n', 'utf8');
  1181. fs.writeFileSync(path.join(feedbackLoopClosureDir, 'feedback-loop-closure-summary.json'), JSON.stringify({
  1182. complete: false,
  1183. passed: false,
  1184. directCustomerProof: false,
  1185. proofLevel: 'not_business_proof',
  1186. negativeFeedbackCount: 0,
  1187. blockedCreatorCount: 0,
  1188. blockedInMemoryCount: 0,
  1189. leakedCount: 0,
  1190. teamRuleSuggestionCount: 0,
  1191. missingInputs: ['feedback csv', 'preference memory json', 'second-round sourcing result json']
  1192. }, null, 2), 'utf8');
  1193. fs.writeFileSync(path.join(feedbackLoopClosureDir, 'feedback-loop-closure-report.md'), '# 反馈二轮闭环审计\n', 'utf8');
  1194. fs.writeFileSync(path.join(feedbackLoopClosureDir, 'feedback-loop-closure.csv'), '\uFEFF账号,写入记忆,泄漏进第二轮,泄漏状态,反馈原因\n', 'utf8');
  1195. fs.writeFileSync(path.join(homepageEvidenceReadinessDir, 'homepage-evidence-readiness-summary.json'), JSON.stringify({
  1196. ready: false,
  1197. complete: false,
  1198. directCustomerProof: false,
  1199. proofLevel: 'not_business_proof',
  1200. failureCount: 2,
  1201. counts: {
  1202. candidates: 1,
  1203. providerEvidenceCreators: 0,
  1204. creatorsWithPosts: 0,
  1205. creatorsWithEnoughRecentPosts: 0
  1206. },
  1207. repairActions: [
  1208. { type: 'missing-provider-evidence' },
  1209. { type: 'missing-recent-posts' }
  1210. ]
  1211. }, null, 2), 'utf8');
  1212. fs.writeFileSync(path.join(homepageEvidenceReadinessDir, 'homepage-evidence-readiness-report.md'), '# 主页近期内容证据就绪审计\n', 'utf8');
  1213. fs.writeFileSync(path.join(homepageEvidenceReadinessDir, 'homepage-evidence-repair-actions.csv'), '\uFEFF优先级,负责人,类型\n1,技术/AI,missing-provider-evidence\n2,商务/投放,missing-recent-posts\n', 'utf8');
  1214. fs.writeFileSync(path.join(intakeReadinessDir, 'intake-readiness-summary.json'), JSON.stringify({
  1215. acceptance: {
  1216. overallReady: false,
  1217. historyReady: false,
  1218. videoReady: false,
  1219. reviewMetricsReady: false,
  1220. customerEffectReady: false
  1221. },
  1222. failureCount: 9
  1223. }, null, 2), 'utf8');
  1224. fs.writeFileSync(path.join(intakeReadinessDir, 'intake-readiness-report.md'), '# 真实材料 Intake Readiness 审计\n', 'utf8');
  1225. fs.writeFileSync(path.join(longRunReadinessDir, 'long-run-readiness-summary.json'), JSON.stringify({
  1226. mode: 'full-matrix',
  1227. ready: false,
  1228. counts: { pass: 1, fail: 5, warn: 0 },
  1229. checks: [
  1230. { name: 'local-acceptance-required', status: 'pass' },
  1231. { name: 'intake-readiness-overall-ready', status: 'fail' },
  1232. { name: 'intake-readiness-no-failures', status: 'fail' }
  1233. ]
  1234. }, null, 2), 'utf8');
  1235. fs.writeFileSync(path.join(longRunReadinessDir, 'long-run-readiness-report.md'), '# 提号长跑就绪度审计\n', 'utf8');
  1236. fs.writeFileSync(path.join(optimizationCompletionDir, 'optimization-completion-summary.json'), JSON.stringify({
  1237. complete: false,
  1238. readyForClaim: false,
  1239. sourceFiles: {
  1240. history: discoveredHistorySource,
  1241. customerEffect: discoveredCustomerEffectSource
  1242. },
  1243. proofGapOpenCount: 5,
  1244. videoAbPreflightReadyForVideoAb: false,
  1245. videoAbPreflightFailureCount: 4,
  1246. blockingReasons: [
  1247. { id: 'proof-gap-closure', status: 'blocked', missingProofRequirements: ['proofGapClosure.complete=true', 'proofGapClosure.openCount=0', ...historicalDatasetConcreteRequirements.map(item => `historical-dataset: ${item}`), ...customerEffectConcreteRequirements.map(item => `manual-review-and-customer-effect: ${item}`)] },
  1248. { id: 'longrun-readiness', status: 'blocked', missingProofRequirements: ['longRunReadiness.ready=true', 'longRunReadiness.counts.fail=0'] },
  1249. { id: 'customer-effect-proof', status: 'blocked', missingProofRequirements: customerEffectConcreteRequirements }
  1250. ],
  1251. gates: [
  1252. {
  1253. id: 'video-ab-live-proof',
  1254. status: 'blocked',
  1255. evidence: 'passed=true, mode=unknown, collectionMode=unknown, generatedBy=unknown, provider=ok; preflight.readyForVideoAb=false, preflight.failureCount=4, preflight.generatedBy=acceptance:video-ab-preflight, runtimeCredentialPresent=false',
  1256. missingProofRequirements: [
  1257. 'proofContext.mode=live',
  1258. 'proofContext.collectionMode=live',
  1259. 'proofContext.generatedBy=acceptance:video-ab',
  1260. 'proofContext.requiresRuntimeCredential=true',
  1261. 'proofContext.requiresVocSocialProvider=true',
  1262. 'proofContext.requiresVideoAnalysisProvider=true',
  1263. 'videoAbPreflight.readyForVideoAb=true',
  1264. 'videoAbPreflight.company resolved for live run'
  1265. ]
  1266. }
  1267. ],
  1268. canClaim: {
  1269. tihaoRateImproved: false,
  1270. customerEffectAchieved: false,
  1271. manualSupplementReduced: false
  1272. },
  1273. nextRequiredCommands: [
  1274. 'npm run intake:readiness',
  1275. 'npm run video:resource-readiness',
  1276. 'npm run proof-gap:closure',
  1277. 'npm run optimization:pipeline',
  1278. 'npm run round:refresh'
  1279. ]
  1280. }, null, 2), 'utf8');
  1281. fs.writeFileSync(path.join(optimizationCompletionDir, 'optimization-completion-report.md'), '# 优化完成度审计\n', 'utf8');
  1282. fs.writeFileSync(path.join(businessProofProgressDir, 'business-proof-progress-summary.json'), JSON.stringify({
  1283. complete: false,
  1284. counts: { pass: 4, fail: 2, pending: 2, blocked_by_external_data: 7 },
  1285. operatorPackOwnerArtifactCount: 3,
  1286. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  1287. rows: Array.from({ length: 15 }, (_, index) => ({
  1288. order: index + 1,
  1289. owner: index < 2 ? '商务' : '技术/AI',
  1290. title: `补证步骤 ${index + 1}`,
  1291. status: index < 4 ? 'pass' : index < 11 ? 'blocked_by_external_data' : index < 13 ? 'fail' : 'pending',
  1292. evidence: 'smoke fixture',
  1293. next: '继续每轮刷新。'
  1294. }))
  1295. }, null, 2), 'utf8');
  1296. fs.writeFileSync(path.join(businessProofProgressDir, 'business-proof-progress-report.md'), '# 提号补证 15 步进度表\n', 'utf8');
  1297. fs.writeFileSync(path.join(businessProofNextActionsDir, 'business-proof-next-actions-summary.json'), JSON.stringify({
  1298. complete: false,
  1299. actionCount: 5,
  1300. ownerGroupCount: 3,
  1301. sourceState: { progressComplete: false, proofGapOpenCount: 5 },
  1302. topActions: [
  1303. {
  1304. id: 'step-03',
  1305. priority: 1,
  1306. owner: '商务',
  1307. title: '填真实历史 Brief',
  1308. command: '填写 outputs\\data-intake-pack-latest\\history-data-template.csv',
  1309. acceptance: 'historyReady=true,真实历史 Brief 数 >= 5,且无模板占位。'
  1310. },
  1311. {
  1312. id: 'step-04',
  1313. priority: 2,
  1314. owner: '商务/投放',
  1315. title: '填真实视频资源',
  1316. command: '填写 outputs\\video-intake-pack-latest\\video-resource-template.csv',
  1317. acceptance: 'videoReady=true'
  1318. },
  1319. {
  1320. id: 'step-12',
  1321. priority: 4,
  1322. owner: '商务',
  1323. title: '人工复核标注',
  1324. command: '填写 outputs\\data-intake-pack-latest\\manual-review-template.csv',
  1325. acceptance: '客户选择齐全'
  1326. },
  1327. {
  1328. id: 'gap-video-ab-live-proof',
  1329. priority: 24,
  1330. owner: '技术/AI',
  1331. title: '真实视频 A/B 验收',
  1332. command: 'npm run acceptance:video-ab',
  1333. acceptance: 'proofContext.mode=live'
  1334. },
  1335. {
  1336. id: 'gap-live-provider-overnight-proof',
  1337. priority: 25,
  1338. owner: '技术/AI',
  1339. title: '真实 live/provider 长跑证明',
  1340. command: 'npm run overnight:quality',
  1341. acceptance: 'manifest.liveEnabled=true'
  1342. }
  1343. ],
  1344. actions: [
  1345. {
  1346. id: 'step-03',
  1347. priority: 1,
  1348. owner: '商务',
  1349. title: '填真实历史 Brief',
  1350. command: '填写 outputs\\data-intake-pack-latest\\history-data-template.csv',
  1351. acceptance: 'historyReady=true,真实历史 Brief 数 >= 5,且无模板占位。',
  1352. missingProofRequirements: historicalDatasetConcreteRequirements
  1353. },
  1354. {
  1355. id: 'step-04',
  1356. priority: 2,
  1357. owner: '商务/投放',
  1358. title: '填真实视频资源',
  1359. command: '填写 outputs\\video-intake-pack-latest\\video-resource-template.csv',
  1360. acceptance: 'videoReady=true,至少有真实参考视频和真实候选视频。',
  1361. missingProofRequirements: ['acceptance.readyForVideoAbPreflight=true', 'failureCount=0', 'counts.realCandidateRows>=1']
  1362. },
  1363. {
  1364. id: 'step-12',
  1365. priority: 4,
  1366. owner: '商务',
  1367. title: '人工复核标注',
  1368. command: '填写 outputs\\data-intake-pack-latest\\manual-review-template.csv',
  1369. acceptance: '客户选择、负样本归因和本轮人工补号量齐全。',
  1370. missingProofRequirements: customerEffectConcreteRequirements
  1371. },
  1372. {
  1373. id: 'gap-video-ab-live-proof',
  1374. priority: 24,
  1375. owner: '技术/AI',
  1376. title: '真实视频 A/B 验收',
  1377. command: 'npm run acceptance:video-ab',
  1378. acceptance: 'acceptance:video-ab 必须在真实 provider 和真实视频资源下通过。',
  1379. missingProofRequirements: ['proofContext.mode=live', 'proofContext.collectionMode=live']
  1380. },
  1381. {
  1382. id: 'gap-live-provider-overnight-proof',
  1383. priority: 25,
  1384. owner: '技术/AI',
  1385. title: '真实 live/provider 长跑证明',
  1386. command: 'npm run longrun:readiness;真实 provider 就绪后运行 npm run overnight:quality',
  1387. acceptance: 'overnight aggregate 必须 liveEnabled=true、overallPass=true、failureCount=0、failedGateCount=0。',
  1388. missingProofRequirements: ['manifest.liveEnabled=true', 'acceptance.overallPass=true']
  1389. }
  1390. ]
  1391. }, null, 2), 'utf8');
  1392. fs.writeFileSync(path.join(businessProofNextActionsDir, 'business-proof-next-actions-report.md'), '# 提号补证下一步行动队列\n', 'utf8');
  1393. fs.writeFileSync(path.join(businessProofNextActionsDir, 'business-proof-next-actions.csv'), '优先级,负责人,动作\n1,商务,填真实历史 Brief\n', 'utf8');
  1394. fs.writeFileSync(path.join(businessExecutionIndexDir, 'business-execution-index-summary.json'), JSON.stringify({
  1395. passed: true,
  1396. rowCount: 15,
  1397. actionRowCount: 5,
  1398. repairRowCount: 2,
  1399. operatorPackOwnerArtifactRowCount: 3,
  1400. operatorPackOwnerArtifactCount: 3,
  1401. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  1402. fieldOwnerRowCount: 1,
  1403. recheckCommandRowCount: 1,
  1404. fileRowCount: 2,
  1405. proofOpenCount: 5,
  1406. proofLevel: 'smoke_or_local',
  1407. directCustomerProof: false,
  1408. sourceFiles: {
  1409. longRunReadiness: 'outputs/long-run-readiness-latest/long-run-readiness-summary.json',
  1410. optimizationCompletion: 'outputs/optimization-completion-latest/optimization-completion-summary.json',
  1411. proofGapOperatorPack: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack-summary.json'
  1412. },
  1413. rows: [
  1414. { owner: '商务', type: '负责人行动', title: '填真实历史 Brief', acceptance: 'historyReady=true', boundary: '补证任务,不证明业务效果' },
  1415. { owner: '商务/投放', type: '负责人行动', title: '填真实视频资源', acceptance: 'videoReady=true', boundary: '补证任务,不证明业务效果' },
  1416. { owner: '商务', type: '负责人行动', title: '人工复核标注', acceptance: 'review=true', boundary: '补证任务,不证明业务效果' },
  1417. { owner: '技术/AI', type: '负责人行动', title: '真实视频 A/B 验收', acceptance: 'acceptance:video-ab=true', boundary: '补证任务,不证明业务效果' },
  1418. { owner: '技术/AI', type: '负责人行动', title: '真实 live/provider 长跑证明', acceptance: 'overnight live=true', boundary: '补证任务,不证明业务效果' },
  1419. { owner: '商务', type: '修复清单', title: '历史数据/商务复核修复清单', acceptance: 'failureCount=0', boundary: '修复清单是补证执行材料,不证明客户效果' },
  1420. { owner: '商务/投放', type: '修复清单', title: '视频资源修复清单', acceptance: 'failureCount=0', boundary: '修复清单是补证执行材料,不证明客户效果' },
  1421. { owner: '商务', type: '操作包负责人附件', title: 'proof-gap 操作包负责人附件', mainFile: 'outputs/proof-gap-operator-pack-latest/by-owner/business.md', csv: 'outputs/proof-gap-operator-pack-latest/by-owner/business.csv', actionCount: 2, acceptance: 'actionCount=2;evidenceRowCount=2;nextActionCount=2;gapIds=historical-dataset;manual-review-and-customer-effect', boundary: '负责人附件只用于补证派工,不证明客户效果' },
  1422. { owner: '商务/投放', type: '操作包负责人附件', title: 'proof-gap 操作包负责人附件', mainFile: 'outputs/proof-gap-operator-pack-latest/by-owner/business-media.md', csv: 'outputs/proof-gap-operator-pack-latest/by-owner/business-media.csv', actionCount: 1, acceptance: 'actionCount=1;evidenceRowCount=1;nextActionCount=1;gapIds=video-real-candidate', boundary: '负责人附件只用于补证派工,不证明客户效果' },
  1423. { owner: '技术/AI', type: '操作包负责人附件', title: 'proof-gap 操作包负责人附件', mainFile: 'outputs/proof-gap-operator-pack-latest/by-owner/tech-ai.md', csv: 'outputs/proof-gap-operator-pack-latest/by-owner/tech-ai.csv', actionCount: 2, acceptance: 'actionCount=2;evidenceRowCount=2;nextActionCount=2;gapIds=video-ab-live-proof;live-provider-overnight-proof', boundary: '负责人附件只用于补证派工,不证明客户效果' },
  1424. { owner: '商务', type: '关键文件', title: '最新提号补证表单', acceptance: 'rowCount=5', boundary: '补证表单不证明客户效果' },
  1425. { owner: '技术/AI', type: '关键文件', title: '长跑前置门禁报告', status: 'blocked', mainFile: 'outputs/long-run-readiness-latest/long-run-readiness-report.md', expectedArtifact: 'outputs/long-run-readiness-latest/long-run-readiness-summary.json', actionCount: 5, acceptance: 'ready=false,failCount=5', boundary: '长跑前置门禁只判断启动条件,不证明客户效果;ready=false 时不能启动或宣称 full-matrix/live 长跑完成。' },
  1426. { owner: '技术/AI', type: '关键文件', title: '优化完成度审计报告', status: 'blocked', mainFile: 'outputs/optimization-completion-latest/optimization-completion-report.md', expectedArtifact: 'outputs/optimization-completion-latest/optimization-completion-summary.json', actionCount: 3, acceptance: 'complete=false,readyForClaim=false,proofGapOpenCount=5,blockingReasons=3', boundary: '优化完成度审计只判断能否进入完成声明,不证明客户效果;readyForClaim=false 时不得宣称提号率提升、客户效果达标或人工补号量下降。' },
  1427. { owner: '商务', type: '字段补齐负责人', title: '历史 Brief字段补齐', acceptance: 'historyReady=true', boundary: '补齐材料,不证明客户效果' },
  1428. { owner: '技术/AI', type: '补齐后复验命令', title: '真实材料预审', acceptance: 'overallReady=true', boundary: '预审通过不证明客户效果' },
  1429. ]
  1430. }, null, 2), 'utf8');
  1431. fs.writeFileSync(path.join(businessExecutionIndexDir, 'business-execution-index.md'), '# Business Execution Index\n\n- passed: true\n- directCustomerProof: false\n', 'utf8');
  1432. fs.writeFileSync(path.join(businessExecutionIndexDir, 'business-execution-index.csv'), 'owner,type,title,acceptance,boundary\nbusiness,owner-action,fill real historical Brief,historyReady=true,not customer proof\n', 'utf8');
  1433. fs.writeFileSync(path.join(proofGapOperatorPackDir, 'proof-gap-operator-pack-summary.json'), JSON.stringify(proofGapOperatorPackFixture, null, 2), 'utf8');
  1434. fs.writeFileSync(path.join(proofGapOperatorPackDir, 'proof-gap-operator-pack.md'), [
  1435. '# Proof Gap Operator Pack',
  1436. '',
  1437. '- directCustomerProof: false',
  1438. '- proofLevel: not_business_proof',
  1439. '- gapIds: historical-dataset,video-real-candidate,video-ab-live-proof,live-provider-overnight-proof,manual-review-and-customer-effect',
  1440. '- recheckCommandCount: 7',
  1441. '- evidenceRowCount: 5',
  1442. '- nextActionCount: 5'
  1443. ].join('\n'), 'utf8');
  1444. fs.writeFileSync(path.join(proofGapOperatorPackDir, 'proof-gap-operator-pack.csv'), [
  1445. 'gapId,owner,evidence,primaryFillFile,primaryRecheckCommand,nextAction',
  1446. `historical-dataset,business,"${historicalDatasetConcreteEvidence}",outputs/data-intake-pack-latest/history-data-template.csv,npm run intake:readiness,补齐真实历史 Brief 后重跑 history:audit`,
  1447. `manual-review-and-customer-effect,business,"${customerEffectConcreteEvidence}",outputs/data-intake-pack-latest/manual-review-template.csv,npm run customer-effect:audit,补客户选择和人工补号量后重跑 customer-effect:audit`
  1448. ].join('\n'), 'utf8');
  1449. fs.writeFileSync(path.join(realProofIntakeBundleDir, 'real-proof-intake-bundle-summary.json'), JSON.stringify({
  1450. passed: true,
  1451. complete: false,
  1452. directCustomerProof: false,
  1453. proofLevel: 'not_business_proof',
  1454. proofOpenCount: 5,
  1455. exportRowCount: 37,
  1456. recheckCommandCount: 6,
  1457. operatorPackEvidenceRowCount: 5,
  1458. operatorPackNextActionCount: 5,
  1459. operatorPackMissingProofRequirementCount: 23,
  1460. operatorPackOwnerArtifactCount: 3,
  1461. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  1462. proofGapRows: [
  1463. {
  1464. gapId: 'video-ab-live-proof',
  1465. status: 'open',
  1466. evidence: videoAbPreflightEvidence,
  1467. nextAction: videoAbLiveProofNextAction,
  1468. missingProofRequirements: videoAbLiveProofRequirements,
  1469. recheckCommands: ['npm run acceptance:video-ab']
  1470. }
  1471. ],
  1472. sourceState: {
  1473. operatorPackEvidenceRowCount: 5,
  1474. operatorPackNextActionCount: 5,
  1475. operatorPackMissingProofRequirementCount: 23,
  1476. operatorPackOwnerArtifactCount: 3,
  1477. longRunReadinessReady: false,
  1478. longRunReadinessFailCount: 5,
  1479. longRunReadinessProofLevel: 'not_business_proof',
  1480. longRunReadinessDirectCustomerProof: false
  1481. },
  1482. templateFiles: [
  1483. {
  1484. owner: '技术/AI',
  1485. title: '长跑前置门禁报告',
  1486. path: 'outputs/long-run-readiness-latest/long-run-readiness-report.md',
  1487. status: 'ready=false,failCount=5',
  1488. boundary: '长跑前置门禁入口不证明客户效果;ready=false 时不能启动或宣称 full-matrix/live 长跑完成。'
  1489. }
  1490. ],
  1491. recheckCommands: [
  1492. {
  1493. stage: '长跑前置门禁',
  1494. owner: '技术/AI',
  1495. command: 'npm run longrun:readiness -- --mode full-matrix --output outputs\\long-run-readiness-latest',
  1496. acceptance: 'ready=true 且 failCount=0',
  1497. boundary: 'ready=false 时不能启动或宣称 full-matrix/live 长跑完成。'
  1498. }
  1499. ],
  1500. exportRows: [
  1501. {
  1502. type: '打开文件',
  1503. target: 'outputs/long-run-readiness-latest/long-run-readiness-report.md'
  1504. },
  1505. {
  1506. type: '复验命令',
  1507. target: 'npm run longrun:readiness -- --mode full-matrix --output outputs\\long-run-readiness-latest'
  1508. },
  1509. {
  1510. type: '证明缺口',
  1511. target: 'video-ab-live-proof',
  1512. evidence: videoAbPreflightEvidence,
  1513. nextAction: videoAbLiveProofNextAction
  1514. }
  1515. ]
  1516. }, null, 2), 'utf8');
  1517. fs.writeFileSync(path.join(realProofIntakeBundleDir, 'real-proof-intake-bundle.md'), '# 真实验收材料收集总包\n\nlong-run-readiness-report.md\n', 'utf8');
  1518. fs.writeFileSync(path.join(realProofIntakeBundleDir, 'real-proof-intake-bundle.csv'), '类型,文件或命令\n打开文件,long-run-readiness-report.md\n', 'utf8');
  1519. fs.writeFileSync(path.join(intakeFieldChecklistDir, 'intake-field-checklist-summary.json'), JSON.stringify({
  1520. passed: true,
  1521. proofLevel: 'smoke_or_local',
  1522. directCustomerProof: false,
  1523. itemCount: 4,
  1524. missingRequiredCount: 2,
  1525. placeholderCount: 2,
  1526. ownerGroups: [
  1527. {
  1528. owner: '商务',
  1529. section: 'history',
  1530. itemCount: 2,
  1531. missingRequiredCount: 1,
  1532. placeholderCount: 1,
  1533. files: ['outputs/data-intake-pack-latest/history-data-template.csv'],
  1534. firstItemIds: ['FIELD-001', 'FIELD-002'],
  1535. nextAction: '补真实历史 Brief 和客户选择。',
  1536. acceptance: 'historyReady=true。',
  1537. boundary: '补齐材料,不证明客户效果'
  1538. },
  1539. {
  1540. owner: '商务/投放',
  1541. section: 'video',
  1542. itemCount: 2,
  1543. missingRequiredCount: 1,
  1544. placeholderCount: 1,
  1545. files: ['outputs/video-intake-pack-latest/video-resource-template.csv'],
  1546. firstItemIds: ['FIELD-003', 'FIELD-004'],
  1547. nextAction: '补真实视频 URL。',
  1548. acceptance: 'videoReady=true。',
  1549. boundary: '补齐材料,不证明客户效果'
  1550. }
  1551. ],
  1552. recheckCommands: [
  1553. {
  1554. stage: '真实材料预审',
  1555. owner: '技术/AI',
  1556. command: 'npm run intake:readiness -- --data-pack outputs\\data-intake-pack-latest --video-pack outputs\\video-intake-pack-latest --output outputs\\intake-readiness-latest',
  1557. acceptance: 'overallReady=true',
  1558. boundary: '预审通过不证明客户效果'
  1559. },
  1560. {
  1561. stage: '刷新本轮交接',
  1562. owner: '技术/AI',
  1563. command: 'npm run round:refresh -- --output-root outputs --strict',
  1564. acceptance: 'round-deposition.passed=true',
  1565. boundary: '刷新交接不证明业务效果'
  1566. },
  1567. {
  1568. stage: '客户效果审计',
  1569. owner: '技术/AI',
  1570. command: 'npm run customer-effect:audit -- --review-csv <已标注CSV> --history-audit <historical-dataset-audit.json> --current-manual-supplement-count <本轮人工补号量> --output <客户效果输出目录> --strict',
  1571. acceptance: 'overallPass=true',
  1572. boundary: '缺客户选择不得宣称效果'
  1573. },
  1574. {
  1575. stage: '视频 A/B 验收',
  1576. owner: '技术/AI',
  1577. command: 'npm run acceptance:video-ab',
  1578. acceptance: '真实 provider 下通过',
  1579. boundary: 'sample 不证明视频提升提号率'
  1580. }
  1581. ], items: [
  1582. { owner: '商务', section: 'history', issueType: 'missing_required', field: '客户原始Brief', fixAction: '补真实 Brief', boundary: '补齐材料,不证明客户效果' },
  1583. { owner: '商务', section: 'history', issueType: 'placeholder', field: '参考账号或视频', fixAction: '替换 example.com', boundary: '补齐材料,不证明客户效果' },
  1584. { owner: '商务', section: 'review', issueType: 'missing_required', field: '客户选择', fixAction: '补客户选择', boundary: '补齐材料,不证明客户效果' },
  1585. { owner: '商务/投放', section: 'video', issueType: 'placeholder', field: '视频链接', fixAction: '补真实视频 URL', boundary: '补齐材料,不证明客户效果' }
  1586. ]
  1587. }, null, 2), 'utf8');
  1588. fs.writeFileSync(path.join(intakeFieldChecklistDir, 'intake-field-checklist.md'), '# 真实材料字段级补齐核对表\n\n- directCustomerProof: false\n', 'utf8');
  1589. fs.writeFileSync(path.join(intakeFieldChecklistDir, 'intake-field-checklist.csv'), 'ID,负责人,区域,问题类型\nFIELD-001,商务,history,missing_required\n', 'utf8');
  1590. fs.writeFileSync(path.join(manualReviewLabelGuideDir, 'manual-review-label-guide-summary.json'), JSON.stringify({
  1591. passed: true,
  1592. directCustomerProof: false,
  1593. proofLevel: 'smoke_or_local',
  1594. labelCount: 10,
  1595. positiveLabelCount: 2,
  1596. negativeLabelCount: 6,
  1597. attributionTypeCount: 8,
  1598. negativeLabelsRequireAttribution: true,
  1599. labels: [
  1600. { label: '可直接发客户', category: 'positive' },
  1601. { label: '商务复核', category: 'positive' },
  1602. { label: '跑偏', category: 'negative', requiresAttribution: true },
  1603. { label: '硬性规则违约', category: 'negative', requiresAttribution: true },
  1604. { label: '调性不符', category: 'negative', requiresAttribution: true },
  1605. { label: '主页质感不符', category: 'negative', requiresAttribution: true },
  1606. { label: '参考账号不像', category: 'negative', requiresAttribution: true },
  1607. { label: '客户拒绝', category: 'customer_result', requiresAttribution: true }
  1608. ],
  1609. attributionTypes: [
  1610. { type: '需求解析错' },
  1611. { type: '隐性规则漏' },
  1612. { type: '召回关键词错' },
  1613. { type: '主页证据不足' },
  1614. { type: '视频证据误判' },
  1615. { type: '排序权重错' },
  1616. { type: '输出解释错' },
  1617. { type: '软件端表重复或排名不连续' }
  1618. ]
  1619. }, null, 2), 'utf8');
  1620. fs.writeFileSync(path.join(manualReviewLabelGuideDir, 'manual-review-label-guide.md'), '# 人工复核标签与归因指南\n', 'utf8');
  1621. fs.writeFileSync(path.join(manualReviewLabelGuideDir, 'manual-review-label-guide.csv'), '类型,ID,名称\nlabel,MRL-001,可直接发客户\n', 'utf8');
  1622. fs.writeFileSync(path.join(proofGapSoftwareFormDir, 'tihao-proof-gap-software-form-summary.json'), JSON.stringify({
  1623. passed: true,
  1624. headerMatches: true,
  1625. rowWidthOk: true,
  1626. rowCount: 5,
  1627. duplicateIdCount: 0,
  1628. actualTitles: [
  1629. '真实历史 Brief 数据集',
  1630. '真实视频资源表',
  1631. '真实视频证据 A/B',
  1632. '真实 live/provider 长跑证明',
  1633. '商务复核和客户效果'
  1634. ]
  1635. }, null, 2), 'utf8');
  1636. fs.writeFileSync(path.join(planExecutionStatusDir, 'plan-execution-status-summary.json'), JSON.stringify({
  1637. passed: true,
  1638. complete: false,
  1639. rowCount: 8,
  1640. proofOpenCount: 5,
  1641. roundPassed: true,
  1642. operatorPackOwnerArtifactCount: 3,
  1643. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  1644. businessExecutionOperatorPackOwnerArtifactCount: 3,
  1645. businessExecutionOperatorPackOwnerArtifactRowCount: 3,
  1646. guardrails: [
  1647. 'proofOpenCount 不为 0 时,不得宣称客户效果、命中率提升或人工补号量下降。',
  1648. 'sample/smoke/provider fallback 只能证明流程可用。'
  1649. ]
  1650. }, null, 2), 'utf8');
  1651. fs.writeFileSync(path.join(planExecutionStatusDir, 'plan-execution-status.md'), '# 长期计划执行状态面板\n', 'utf8');
  1652. fs.writeFileSync(path.join(planExecutionStatusDir, 'plan-execution-status.csv'), 'section,status\n', 'utf8');
  1653. fs.writeFileSync(path.join(latestFormIndexDir, 'latest-form-index-summary.json'), JSON.stringify({
  1654. passed: true,
  1655. primaryForm: {
  1656. directCustomerProof: false,
  1657. csv: 'outputs/tihao-proof-gap-software-form-latest/tihao-proof-gap-software-form.csv'
  1658. },
  1659. clientList: {
  1660. directCustomerProof: false,
  1661. csv: 'outputs/software-client-latest/software-client-list.final.csv',
  1662. summary: 'outputs/software-client-latest/software-client-list.final.summary.json',
  1663. rowCount: 28,
  1664. sourceDuplicateRemovedCount: 32,
  1665. finalDuplicateGroupCount: 0,
  1666. duplicateCountMeaning: 'source_duplicate_removed_count',
  1667. rankContinuous: true
  1668. },
  1669. localSeedToIntakeWorklist: localSeedToIntakeWorklistIndexedFixture,
  1670. realGapMaterialAudit: realGapMaterialAuditIndexedFixture,
  1671. realProofClosureWorkOrder: realProofClosureWorkOrderIndexedFixture,
  1672. manualReviewLabelGuide: {
  1673. markdown: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.md',
  1674. csv: 'outputs/manual-review-label-guide-latest/manual-review-label-guide.csv',
  1675. summary: 'outputs/manual-review-label-guide-latest/manual-review-label-guide-summary.json',
  1676. passed: true,
  1677. directCustomerProof: false,
  1678. proofLevel: 'smoke_or_local',
  1679. labelCount: 10,
  1680. positiveLabelCount: 2,
  1681. negativeLabelCount: 6,
  1682. attributionTypeCount: 8,
  1683. negativeLabelsRequireAttribution: true
  1684. },
  1685. intakeFieldChecklist: {
  1686. directCustomerProof: false,
  1687. markdown: 'outputs/intake-field-checklist-latest/intake-field-checklist.md',
  1688. csv: 'outputs/intake-field-checklist-latest/intake-field-checklist.csv',
  1689. summary: 'outputs/intake-field-checklist-latest/intake-field-checklist-summary.json',
  1690. itemCount: 4,
  1691. missingRequiredCount: 2,
  1692. placeholderCount: 2,
  1693. ownerGroups: [
  1694. {
  1695. owner: '商务',
  1696. section: 'history',
  1697. itemCount: 2,
  1698. files: ['outputs/data-intake-pack-latest/history-data-template.csv'],
  1699. nextAction: '补真实历史 Brief',
  1700. acceptance: 'historyReady=true',
  1701. boundary: '补齐材料,不证明客户效果'
  1702. },
  1703. {
  1704. owner: '商务/投放',
  1705. section: 'video',
  1706. itemCount: 2,
  1707. files: ['outputs/video-intake-pack-latest/video-resource-template.csv'],
  1708. nextAction: '补真实视频 URL',
  1709. acceptance: 'videoReady=true',
  1710. boundary: '补齐材料,不证明客户效果'
  1711. }
  1712. ],
  1713. recheckCommands: [
  1714. {
  1715. stage: '真实材料预审',
  1716. owner: '技术/AI',
  1717. command: 'npm run intake:readiness -- --data-pack outputs\\data-intake-pack-latest --video-pack outputs\\video-intake-pack-latest --output outputs\\intake-readiness-latest',
  1718. acceptance: 'overallReady=true',
  1719. boundary: '预审通过不证明客户效果'
  1720. },
  1721. {
  1722. stage: '刷新本轮交接',
  1723. owner: '技术/AI',
  1724. command: 'npm run round:refresh -- --output-root outputs --strict',
  1725. acceptance: 'round-deposition.passed=true',
  1726. boundary: '刷新交接不证明业务效果'
  1727. },
  1728. {
  1729. stage: '客户效果审计',
  1730. owner: '技术/AI',
  1731. command: 'npm run customer-effect:audit -- --review-csv <已标注CSV> --history-audit <historical-dataset-audit.json> --current-manual-supplement-count <本轮人工补号量> --output <客户效果输出目录> --strict',
  1732. acceptance: 'overallPass=true',
  1733. boundary: '缺客户选择不得宣称效果'
  1734. },
  1735. {
  1736. stage: '视频 A/B 验收',
  1737. owner: '技术/AI',
  1738. command: 'npm run acceptance:video-ab',
  1739. acceptance: '真实 provider 下通过',
  1740. boundary: 'sample 不证明视频提升提号率'
  1741. }
  1742. ]
  1743. },
  1744. businessFillGuide: {
  1745. title: '商务填表执行视图',
  1746. directCustomerProof: false,
  1747. proofLevel: 'smoke_or_local',
  1748. rowCount: 2,
  1749. rows: [
  1750. {
  1751. order: 1,
  1752. owner: '鍟嗗姟',
  1753. section: 'history',
  1754. file: 'outputs/data-intake-pack-latest/history-data-template.csv',
  1755. firstItemIds: ['FIELD-001'],
  1756. issueCount: 2,
  1757. fillAction: '琛ョ湡瀹炲巻鍙?Brief',
  1758. recheckCommand: 'npm run intake:readiness -- --data-pack outputs\\data-intake-pack-latest --video-pack outputs\\video-intake-pack-latest --output outputs\\intake-readiness-latest',
  1759. acceptance: 'historyReady=true',
  1760. boundary: '补齐材料,不证明客户效果'
  1761. },
  1762. {
  1763. order: 2,
  1764. owner: '鍟嗗姟/鎶曟斁',
  1765. section: 'video',
  1766. file: 'outputs/video-intake-pack-latest/video-resource-template.csv',
  1767. firstItemIds: ['FIELD-003'],
  1768. issueCount: 2,
  1769. fillAction: '琛ョ湡瀹炶棰?URL',
  1770. recheckCommand: 'npm run acceptance:video-ab',
  1771. acceptance: 'videoReady=true',
  1772. boundary: '补齐材料,不证明客户效果'
  1773. }
  1774. ],
  1775. guardrail: '本视图只帮助商务按表补齐真实材料,不代表客户效果已达标。'
  1776. },
  1777. businessExecutionIndex: {
  1778. directCustomerProof: false,
  1779. markdown: 'outputs/business-execution-index-latest/business-execution-index.md',
  1780. csv: 'outputs/business-execution-index-latest/business-execution-index.csv',
  1781. summary: 'outputs/business-execution-index-latest/business-execution-index-summary.json',
  1782. rowCount: 15,
  1783. operatorPackOwnerArtifactCount: 3,
  1784. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  1785. fieldOwnerRowCount: 1,
  1786. recheckCommandRowCount: 1
  1787. },
  1788. proofGapOperatorPack: {
  1789. ...proofGapOperatorPackFixture,
  1790. markdown: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack.md',
  1791. csv: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack.csv',
  1792. summary: 'outputs/proof-gap-operator-pack-latest/proof-gap-operator-pack-summary.json'
  1793. },
  1794. planExecutionStatus: {
  1795. directCustomerProof: false,
  1796. markdown: 'outputs/plan-execution-status-latest/plan-execution-status.md',
  1797. csv: 'outputs/plan-execution-status-latest/plan-execution-status.csv',
  1798. summary: 'outputs/plan-execution-status-latest/plan-execution-status-summary.json',
  1799. passed: true,
  1800. complete: false,
  1801. rowCount: 8,
  1802. proofOpenCount: 5,
  1803. operatorPackOwnerArtifactCount: 3,
  1804. operatorPackOwnerArtifacts: proofGapOperatorPackFixture.ownerArtifacts,
  1805. businessExecutionOperatorPackOwnerArtifactCount: 3,
  1806. businessExecutionOperatorPackOwnerArtifactRowCount: 3
  1807. },
  1808. longRunReadiness: {
  1809. report: 'outputs/long-run-readiness-latest/long-run-readiness-report.md',
  1810. summary: 'outputs/long-run-readiness-latest/long-run-readiness-summary.json',
  1811. mode: 'full-matrix',
  1812. ready: false,
  1813. directCustomerProof: false,
  1814. proofLevel: 'not_business_proof',
  1815. passCount: 1,
  1816. failCount: 5,
  1817. warnCount: 0
  1818. },
  1819. supportDocs: [
  1820. { path: 'docs/tihao-experience-optimization-plan.zh-CN.md' },
  1821. { path: 'docs/business-proof-action-order.zh-CN.md' }
  1822. ],
  1823. nextActions: {
  1824. complete: false,
  1825. actionCount: 5,
  1826. proofOpenCount: 5,
  1827. ownerGroupCount: 3,
  1828. ownerArtifactCount: 3,
  1829. sourceState: {
  1830. progressComplete: false,
  1831. proofGapOpenCount: 5
  1832. },
  1833. topActions: [
  1834. {
  1835. id: 'step-03',
  1836. priority: 1,
  1837. owner: '商务',
  1838. title: '填真实历史 Brief',
  1839. status: 'blocked_by_external_data',
  1840. command: '填写 outputs\\data-intake-pack-latest\\history-data-template.csv',
  1841. acceptance: 'historyReady=true'
  1842. },
  1843. {
  1844. id: 'step-04',
  1845. priority: 2,
  1846. owner: '商务/投放',
  1847. title: '填真实视频资源',
  1848. status: 'blocked_by_external_data',
  1849. command: '填写 outputs\\video-intake-pack-latest\\video-resource-template.csv',
  1850. acceptance: 'videoReady=true'
  1851. },
  1852. {
  1853. id: 'step-12',
  1854. priority: 4,
  1855. owner: '商务',
  1856. title: '人工复核标注',
  1857. status: 'blocked_by_external_data',
  1858. command: '填写 outputs\\data-intake-pack-latest\\manual-review-template.csv',
  1859. acceptance: '客户选择齐全'
  1860. },
  1861. {
  1862. id: 'gap-video-ab-live-proof',
  1863. priority: 24,
  1864. owner: '技术/AI',
  1865. title: '真实视频 A/B 验收',
  1866. status: 'open',
  1867. command: 'npm run acceptance:video-ab',
  1868. acceptance: '真实 provider 下通过'
  1869. },
  1870. {
  1871. id: 'gap-live-provider-overnight-proof',
  1872. priority: 25,
  1873. owner: '技术/AI',
  1874. title: '真实 live/provider 长跑证明',
  1875. status: 'open',
  1876. command: 'npm run longrun:readiness;真实 provider 就绪后运行 npm run overnight:quality',
  1877. acceptance: 'liveEnabled=true'
  1878. }
  1879. ],
  1880. ownerArtifacts: [
  1881. {
  1882. owner: '商务',
  1883. markdown: 'outputs/business-proof-next-actions-latest/by-owner/business.md',
  1884. csv: 'outputs/business-proof-next-actions-latest/by-owner/business.csv',
  1885. repairArtifacts: [
  1886. { csv: 'outputs/intake-readiness-latest/intake-readiness-repair-actions.csv', actionCount: 6 }
  1887. ]
  1888. },
  1889. {
  1890. owner: '商务/投放',
  1891. markdown: 'outputs/business-proof-next-actions-latest/by-owner/business-media.md',
  1892. csv: 'outputs/business-proof-next-actions-latest/by-owner/business-media.csv',
  1893. repairArtifacts: [
  1894. { csv: 'outputs/video-resource-readiness-latest/video-resource-repair-actions.csv', actionCount: 1 },
  1895. { csv: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-repair-actions.csv', actionCount: 1 }
  1896. ]
  1897. },
  1898. { owner: '技术/AI', markdown: 'outputs/business-proof-next-actions-latest/by-owner/tech-ai.md', csv: 'outputs/business-proof-next-actions-latest/by-owner/tech-ai.csv', repairArtifacts: [] }
  1899. ]
  1900. },
  1901. repairActions: {
  1902. dataIntake: {
  1903. csv: 'outputs/intake-readiness-latest/intake-readiness-repair-actions.csv',
  1904. repairActionCount: 9
  1905. },
  1906. videoResource: {
  1907. csv: 'outputs/video-resource-readiness-latest/video-resource-repair-actions.csv',
  1908. repairActionCount: 1
  1909. },
  1910. homepageEvidence: {
  1911. csv: 'outputs/homepage-evidence-readiness-latest/homepage-evidence-repair-actions.csv',
  1912. repairActionCount: 2
  1913. }
  1914. }
  1915. }, null, 2), 'utf8');
  1916. const result = spawnSync(process.execPath, [
  1917. path.join(root, 'scripts', 'round-deposition-audit.js'),
  1918. '--outputs',
  1919. outputs,
  1920. '--implementation-log',
  1921. implementationLog,
  1922. '--proof-action-order',
  1923. proofActionOrder,
  1924. '--output',
  1925. outputDir,
  1926. '--strict'
  1927. ], { cwd: root, encoding: 'utf8' });
  1928. if (result.status !== 0) {
  1929. process.stderr.write(result.stderr || result.stdout || '');
  1930. throw new Error('round-deposition-audit should pass with complete local deposition artifacts');
  1931. }
  1932. const defaultDocOutputDir = path.join(outputs, 'round-deposition-default-doc');
  1933. const defaultDocResult = spawnSync(process.execPath, [
  1934. path.join(root, 'scripts', 'round-deposition-audit.js'),
  1935. '--outputs',
  1936. outputs,
  1937. '--implementation-log',
  1938. implementationLog,
  1939. '--output',
  1940. defaultDocOutputDir,
  1941. '--strict'
  1942. ], { cwd: root, encoding: 'utf8' });
  1943. if (defaultDocResult.status !== 0) {
  1944. process.stderr.write(defaultDocResult.stderr || defaultDocResult.stdout || '');
  1945. throw new Error('round-deposition-audit should pass with default Chinese proof action order document');
  1946. }
  1947. const defaultDocSummary = JSON.parse(fs.readFileSync(path.join(defaultDocOutputDir, 'round-deposition-summary.json'), 'utf8'));
  1948. assert(defaultDocSummary.sources.proofActionOrder.includes('business-proof-action-order.zh-CN.md'), 'default proof action order should prefer Chinese document');
  1949. const summary = JSON.parse(fs.readFileSync(path.join(outputDir, 'round-deposition-summary.json'), 'utf8'));
  1950. const report = fs.readFileSync(path.join(outputDir, 'round-deposition-report.md'), 'utf8').replace(/^\uFEFF/, '');
  1951. assert(summary.passed === true, 'round deposition summary should pass');
  1952. assert(summary.checks.some(item => item.id === 'proof-boundaries'), 'summary should include proof boundary check');
  1953. assert(summary.checks.some(item => item.id === 'proof-gap-unresolved-recorded'), 'summary should include proof-gap unresolved check');
  1954. assert(summary.checks.some(item => item.id === 'proof-gap-template-entry-recorded'), 'summary should include proof-gap template entry check');
  1955. assert(summary.checks.some(item => item.id === 'proof-gap-template-columns-exported'), 'summary should include proof-gap template column export check');
  1956. assert(summary.checks.some(item => item.id === 'proof-gap-operator-pack-summary'), 'summary should include proof-gap operator pack summary check');
  1957. assert(summary.checks.some(item => item.id === 'proof-gap-operator-pack-actionable'), 'summary should include proof-gap operator pack actionable check');
  1958. assert(summary.checks.some(item => item.id === 'proof-gap-operator-pack-missing-proof-by-gap'), 'summary should include proof-gap operator pack missing proof by gap check');
  1959. assert(summary.checks.some(item => item.id === 'proof-gap-closure-recursive-proof-artifact-discovery'), 'summary should include proof-gap closure recursive proof artifact discovery check');
  1960. assert(summary.checks.some(item => item.id === 'proof-gap-operator-pack-video-ab-preflight-context'), 'summary should include proof-gap operator pack video A/B preflight context check');
  1961. assert(summary.checks.some(item => item.id === 'intake-readiness-summary'), 'summary should include intake readiness summary check');
  1962. assert(summary.checks.some(item => item.id === 'intake-readiness-boundary-recorded'), 'summary should include intake readiness boundary check');
  1963. assert(summary.checks.some(item => item.id === 'longrun-readiness-summary'), 'summary should include longrun readiness summary check');
  1964. assert(summary.checks.some(item => item.id === 'longrun-readiness-intake-gate'), 'summary should include longrun intake gate check');
  1965. assert(summary.checks.some(item => item.id === 'latest-form-index-longrun-readiness'), 'summary should include latest form longrun readiness entry check');
  1966. assert(summary.checks.some(item => item.id === 'handoff-longrun-readiness'), 'summary should include handoff longrun readiness entry check');
  1967. assert(summary.checks.some(item => item.id === 'handoff-latest-form-longrun-readiness'), 'summary should include handoff latest form longrun readiness entry check');
  1968. assert(summary.checks.some(item => item.id === 'business-proof-progress-summary'), 'summary should include business proof progress summary check');
  1969. assert(summary.checks.some(item => item.id === 'business-proof-progress-steps'), 'summary should include business proof progress steps check');
  1970. assert(summary.checks.some(item => item.id === 'business-proof-progress-operator-owner-artifacts'), 'summary should include business proof progress operator owner attachment check');
  1971. assert(summary.checks.some(item => item.id === 'handoff-business-proof-progress-operator-owner-artifacts'), 'summary should include handoff business proof progress operator owner attachment check');
  1972. assert(summary.checks.some(item => item.id === 'business-proof-next-actions-summary'), 'summary should include business proof next actions summary check');
  1973. assert(summary.checks.some(item => item.id === 'business-proof-next-actions-open'), 'summary should include business proof next actions open check');
  1974. assert(summary.checks.some(item => item.id === 'business-proof-next-actions-deduped'), 'summary should include business proof next actions dedupe check');
  1975. assert(summary.checks.some(item => item.id === 'business-proof-next-actions-missing-proof-requirements'), 'summary should include business proof next actions missing proof requirement check');
  1976. assert(summary.checks.some(item => item.id === 'handoff-business-proof-next-actions-top-actions'), 'summary should include handoff business proof next actions top action check');
  1977. assert(summary.checks.some(item => item.id === 'optimization-completion-summary'), 'summary should include optimization completion summary check');
  1978. assert(summary.checks.some(item => item.id === 'optimization-completion-boundary'), 'summary should include optimization completion boundary check');
  1979. assert(summary.checks.some(item => item.id === 'optimization-completion-recursive-proof-artifact-discovery'), 'summary should include optimization completion recursive proof artifact discovery check');
  1980. assert(summary.checks.some(item => item.id === 'business-execution-index-summary'), 'summary should include business execution index summary check');
  1981. assert(summary.checks.some(item => item.id === 'business-execution-index-passed'), 'summary should include business execution index pass check');
  1982. assert(summary.checks.some(item => item.id === 'business-execution-index-longrun-readiness'), 'summary should include business execution longrun readiness check');
  1983. assert(summary.checks.some(item => item.id === 'business-execution-index-optimization-completion'), 'summary should include business execution optimization completion check');
  1984. assert(summary.checks.some(item => item.id === 'real-proof-intake-bundle-summary'), 'summary should include real proof intake bundle summary check');
  1985. assert(summary.checks.some(item => item.id === 'real-proof-intake-bundle-longrun-readiness'), 'summary should include real proof bundle longrun readiness check');
  1986. assert(summary.checks.some(item => item.id === 'real-proof-intake-bundle-video-ab-preflight-context'), 'summary should include real proof bundle video A/B preflight context check');
  1987. assert(summary.checks.some(item => item.id === 'handoff-business-execution-index'), 'summary should include handoff business execution index check');
  1988. assert(summary.checks.some(item => item.id === 'handoff-business-execution-index-longrun-readiness'), 'summary should include handoff business execution longrun readiness check');
  1989. assert(summary.checks.some(item => item.id === 'handoff-optimization-completion'), 'summary should include handoff optimization completion check');
  1990. assert(summary.checks.some(item => item.id === 'handoff-business-execution-index-optimization-completion'), 'summary should include handoff business execution optimization completion check');
  1991. assert(summary.checks.some(item => item.id === 'intake-field-checklist-summary'), 'summary should include intake field checklist summary check');
  1992. assert(summary.checks.some(item => item.id === 'intake-field-checklist-passed'), 'summary should include intake field checklist pass check');
  1993. assert(summary.checks.some(item => item.id === 'handoff-intake-field-checklist'), 'summary should include handoff intake field checklist check');
  1994. assert(summary.checks.some(item => item.id === 'proof-gap-software-form-summary'), 'summary should include proof-gap software form summary check');
  1995. assert(summary.checks.some(item => item.id === 'proof-gap-software-form-passed'), 'summary should include proof-gap software form pass check');
  1996. assert(summary.checks.some(item => item.id === 'latest-form-index-summary'), 'summary should include latest form index summary check');
  1997. assert(summary.checks.some(item => item.id === 'latest-form-index-passed'), 'summary should include latest form index pass check');
  1998. assert(summary.checks.some(item => item.id === 'latest-form-index-client-list-delivery-quality'), 'summary should include latest form client list delivery quality check');
  1999. assert(summary.checks.some(item => item.id === 'latest-form-index-intake-field-checklist'), 'summary should include latest form intake field checklist check');
  2000. assert(summary.checks.some(item => item.id === 'latest-form-index-business-fill-guide'), 'summary should include latest form business fill guide check');
  2001. assert(summary.checks.some(item => item.id === 'latest-form-index-support-docs'), 'summary should include latest form support docs check');
  2002. assert(summary.checks.some(item => item.id === 'latest-form-index-repair-actions'), 'summary should include latest form repair actions check');
  2003. assert(summary.checks.some(item => item.id === 'latest-form-index-owner-repair-actions'), 'summary should include latest form owner repair actions check');
  2004. assert(summary.checks.some(item => item.id === 'latest-form-index-next-actions-top-actions'), 'summary should include latest form next actions top actions check');
  2005. assert(summary.checks.some(item => item.id === 'latest-form-index-proof-gap-operator-pack'), 'summary should include latest form proof-gap operator pack check');
  2006. assert(summary.checks.some(item => item.id === 'local-seed-to-intake-worklist-summary'), 'summary should include local seed to intake worklist summary check');
  2007. assert(summary.checks.some(item => item.id === 'local-seed-to-intake-worklist-boundary'), 'summary should include local seed to intake worklist boundary check');
  2008. assert(summary.checks.some(item => item.id === 'latest-form-index-local-seed-to-intake-worklist'), 'summary should include latest form local seed to intake worklist check');
  2009. assert(summary.checks.some(item => item.id === 'real-proof-closure-work-order-summary'), 'summary should include real proof closure work order summary check');
  2010. assert(summary.checks.some(item => item.id === 'real-proof-closure-work-order-boundary'), 'summary should include real proof closure work order boundary check');
  2011. assert(summary.checks.some(item => item.id === 'real-proof-closure-work-order-actionable'), 'summary should include real proof closure work order actionable check');
  2012. assert(summary.checks.some(item => item.id === 'real-proof-closure-work-order-video-ab-preflight-context'), 'summary should include real proof closure work order video A/B preflight context check');
  2013. assert(summary.checks.some(item => item.id === 'latest-form-index-real-proof-closure-work-order'), 'summary should include latest form real proof closure work order check');
  2014. assert(summary.checks.some(item => item.id === 'handoff-real-proof-closure-work-order'), 'summary should include handoff real proof closure work order check');
  2015. assert(summary.checks.some(item => item.id === 'handoff-latest-form-real-proof-closure-work-order'), 'summary should include handoff latest form real proof closure work order check');
  2016. assert(summary.checks.some(item => item.id === 'evidence-index-real-proof-closure-work-order'), 'summary should include evidence index real proof closure work order check');
  2017. assert(summary.checks.some(item => item.id === 'evidence-index-video-ab-runtime-preflight-boundary'), 'summary should include video A/B runtime preflight boundary check');
  2018. assert(summary.checks.some(item => item.id === 'handoff-local-seed-to-intake-worklist'), 'summary should include handoff local seed to intake worklist check');
  2019. assert(summary.checks.some(item => item.id === 'handoff-latest-form-local-seed-to-intake-worklist'), 'summary should include handoff latest form local seed to intake worklist check');
  2020. assert(summary.checks.some(item => item.id === 'handoff-latest-form-index'), 'summary should include handoff latest form index check');
  2021. assert(summary.checks.some(item => item.id === 'handoff-latest-form-index-next-actions-top-actions'), 'summary should include handoff latest form next actions top actions check');
  2022. assert(summary.checks.some(item => item.id === 'handoff-latest-form-repair-actions'), 'summary should include handoff latest form repair actions check');
  2023. assert(summary.checks.some(item => item.id === 'handoff-proof-gap-operator-pack'), 'summary should include handoff proof-gap operator pack check');
  2024. assert(summary.checks.some(item => item.id === 'handoff-support-docs'), 'summary should include handoff support docs check');
  2025. assert(summary.checks.some(item => item.id === 'handoff-owner-repair-actions'), 'summary should include handoff owner repair actions check');
  2026. assert(summary.checks.some(item => item.id === 'business-proof-action-order'), 'summary should include business proof action order check');
  2027. assert(summary.checks.some(item => item.id === 'proof-gap-closure-open-recorded'), 'summary should include proof-gap closure open check');
  2028. assert(summary.checks.some(item => item.id === 'proof-gap-closure-count-semantics'), 'summary should include proof-gap closure count semantics check');
  2029. assert(summary.checks.some(item => item.id === 'proof-gap-closure-missing-proof-requirements'), 'summary should include proof-gap closure missing proof requirements check');
  2030. assert(summary.checks.some(item => item.id === 'handoff-proof-gap-closure'), 'summary should include handoff proof-gap closure check');
  2031. assert(summary.checks.some(item => item.id === 'feedback-loop-closure-summary'), 'summary should include feedback loop closure summary check');
  2032. assert(summary.checks.some(item => item.id === 'feedback-loop-closure-boundary'), 'summary should include feedback loop closure boundary check');
  2033. assert(summary.checks.some(item => item.id === 'handoff-feedback-loop-closure'), 'summary should include handoff feedback loop closure check');
  2034. assert(summary.checks.some(item => item.id === 'homepage-evidence-readiness-summary'), 'summary should include homepage evidence readiness summary check');
  2035. assert(summary.checks.some(item => item.id === 'homepage-evidence-readiness-boundary'), 'summary should include homepage evidence readiness boundary check');
  2036. assert(summary.checks.some(item => item.id === 'handoff-homepage-evidence-readiness'), 'summary should include handoff homepage evidence readiness check');
  2037. assert(summary.checks.some(item => item.id === 'business-execution-index-operator-owner-artifacts'), 'summary should include business execution operator owner artifacts check');
  2038. assert(summary.checks.some(item => item.id === 'handoff-business-execution-index-operator-owner-artifacts'), 'summary should include handoff business execution operator owner artifacts check');
  2039. assert(summary.checks.some(item => item.id === 'plan-execution-status-operator-owner-artifacts'), 'summary should include plan execution operator owner artifacts check');
  2040. assert(summary.checks.some(item => item.id === 'closure-command-recorded'), 'summary should include proof-gap closure command check');
  2041. assert(summary.observed.proofGapUnresolvedCount === 5, 'summary should record proof-gap unresolved count');
  2042. assert(summary.observed.proofGapTemplateRowsReady === true, 'summary should record proof-gap template row readiness');
  2043. assert(summary.observed.proofGapTemplateColumnsReady === true, 'summary should record proof-gap template column readiness');
  2044. assert(summary.observed.evidenceVideoRuntimePreflightCount === 1, 'summary should record video A/B runtime preflight count');
  2045. assert(summary.observed.proofGapOperatorPackPassed === true, 'summary should record proof-gap operator pack pass state');
  2046. assert(summary.observed.proofGapOperatorPackOpenCount === 5, 'summary should record proof-gap operator pack open count');
  2047. assert(summary.observed.proofGapOperatorPackRowCount === 5, 'summary should record proof-gap operator pack row count');
  2048. assert(summary.observed.proofGapOperatorPackOwnerGroupCount === 3, 'summary should record proof-gap operator pack owner group count');
  2049. assert(summary.observed.proofGapOperatorPackOwnerArtifactCount === 3, 'summary should record proof-gap operator pack owner artifact count');
  2050. assert(summary.observed.proofGapOperatorPackFillFileCount === 3, 'summary should record proof-gap operator pack fill file count');
  2051. assert(summary.observed.proofGapOperatorPackRecheckCommandCount === 7, 'summary should record proof-gap operator pack recheck command count');
  2052. assert(summary.observed.proofGapOperatorPackEvidenceRowCount === 5, 'summary should record proof-gap operator pack evidence row count');
  2053. assert(summary.observed.proofGapOperatorPackNextActionCount === 5, 'summary should record proof-gap operator pack next action count');
  2054. assert(summary.observed.proofGapOperatorPackMissingProofRequirementCount === 23, 'summary should record proof-gap operator pack missing proof requirement count');
  2055. assert(summary.observed.proofGapOperatorPackOpenRowsWithMissingProofRequirements === 5, 'summary should record proof-gap operator pack open rows with missing proof requirements');
  2056. assert(summary.observed.proofGapOperatorPackVideoAbPreflightContext === true, 'summary should record proof-gap operator pack video A/B preflight context');
  2057. assert(summary.observed.proofGapOperatorPackGapIds.includes('historical-dataset'), 'summary should record historical dataset gap ID');
  2058. assert(summary.observed.proofGapOperatorPackGapIds.includes('manual-review-and-customer-effect'), 'summary should record customer effect gap ID');
  2059. assert(summary.observed.proofGapOperatorPackDirectCustomerProof === false, 'summary should record proof-gap operator pack proof boundary');
  2060. assert(summary.observed.intakeReadinessReady === false, 'summary should record intake readiness state');
  2061. assert(summary.observed.intakeReadinessFailureCount === 9, 'summary should record intake readiness failure count');
  2062. assert(summary.observed.longRunReadinessReady === false, 'summary should record longrun readiness state');
  2063. assert(summary.observed.longRunReadinessFailCount === 5, 'summary should record longrun fail count');
  2064. assert(summary.observed.businessProofProgressComplete === false, 'summary should record business proof progress completion state');
  2065. assert(summary.observed.businessProofProgressCounts.blocked_by_external_data === 7, 'summary should record business proof progress blocker count');
  2066. assert(summary.observed.businessProofProgressOperatorPackOwnerArtifactCount === 3, 'summary should record business proof progress operator owner artifact count');
  2067. assert(summary.observed.handoffBusinessProofProgressOperatorPackOwnerArtifactCount === 3, 'summary should record handoff business proof progress operator owner artifact count');
  2068. assert(summary.observed.businessProofNextActionsComplete === false, 'summary should record business proof next actions completion state');
  2069. assert(summary.observed.businessProofNextActionsCount === 5, 'summary should record business proof next actions count');
  2070. assert(summary.observed.businessProofNextActionsTopCount === 5, 'summary should record business proof next actions top action count');
  2071. assert(summary.observed.businessProofNextActionsWithMissingProofRequirements === 5, 'summary should record business proof next actions missing proof requirement count');
  2072. assert(summary.observed.handoffBusinessProofNextActionsCount === 5, 'summary should record handoff business proof next actions count');
  2073. assert(summary.observed.handoffBusinessProofNextActionsTopCount === 5, 'summary should record handoff business proof top action count');
  2074. assert(summary.observed.handoffBusinessProofNextActionsProofGapOpenCount === 5, 'summary should record handoff business proof next action open count');
  2075. assert(summary.observed.optimizationCompletionComplete === false, 'summary should record optimization completion state');
  2076. assert(summary.observed.optimizationCompletionReadyForClaim === false, 'summary should record optimization ready-for-claim state');
  2077. assert(summary.observed.optimizationCompletionProofGapOpenCount === 5, 'summary should record optimization completion proof-gap count');
  2078. assert(summary.observed.optimizationCompletionBlockingReasonCount === 3, 'summary should record optimization completion blocking reason count');
  2079. assert(summary.observed.optimizationCompletionBlockingReasonsWithMissingProofRequirements === 3, 'summary should record optimization completion blocking reasons with missing proof requirements');
  2080. assert(summary.observed.optimizationCompletionMissingProofRequirementCount === 14, 'summary should record optimization completion missing proof requirement count');
  2081. assert(summary.observed.proofGapClosureHistorySource.includes('historical-dataset-audit.json'), 'summary should record proof-gap closure history source');
  2082. assert(summary.observed.proofGapClosureCustomerEffectSource.includes('customer-effect-summary.json'), 'summary should record proof-gap closure customer-effect source');
  2083. assert(summary.observed.proofGapClosureRecursiveProofArtifactDiscovery === true, 'summary should record proof-gap closure recursive discovery state');
  2084. assert(summary.observed.optimizationCompletionHistorySource.includes('historical-dataset-audit.json'), 'summary should record optimization completion history source');
  2085. assert(summary.observed.optimizationCompletionCustomerEffectSource.includes('customer-effect-summary.json'), 'summary should record optimization completion customer-effect source');
  2086. assert(summary.observed.optimizationCompletionRecursiveProofArtifactDiscovery === true, 'summary should record optimization completion recursive discovery state');
  2087. assert(summary.observed.optimizationCompletionCanClaimTihaoRateImproved === false, 'summary should record tihao-rate claim boundary');
  2088. assert(summary.observed.optimizationCompletionCanClaimCustomerEffectAchieved === false, 'summary should record customer-effect claim boundary');
  2089. assert(summary.observed.optimizationCompletionCanClaimManualSupplementReduced === false, 'summary should record manual-supplement claim boundary');
  2090. assert(summary.observed.optimizationCompletionVideoAbPreflightReadyForVideoAb === false, 'summary should record optimization completion video A/B preflight readiness');
  2091. assert(summary.observed.optimizationCompletionVideoAbPreflightFailureCount === 4, 'summary should record optimization completion video A/B preflight failure count');
  2092. assert(summary.observed.businessExecutionIndexPassed === true, 'summary should record business execution index pass state');
  2093. assert(summary.observed.businessExecutionIndexRowCount === 15, 'summary should record business execution index row count');
  2094. assert(summary.observed.businessExecutionIndexActionRowCount === 5, 'summary should record business execution index action row count');
  2095. assert(summary.observed.businessExecutionIndexRepairRowCount === 2, 'summary should record business execution index repair row count');
  2096. assert(summary.observed.businessExecutionIndexOperatorPackOwnerArtifactRowCount === 3, 'summary should record business execution operator owner artifact row count');
  2097. assert(summary.observed.businessExecutionIndexOperatorPackOwnerArtifactCount === 3, 'summary should record business execution operator owner artifact count');
  2098. assert(summary.observed.businessExecutionIndexFieldOwnerRowCount === 1, 'summary should record business execution index field owner row count');
  2099. assert(summary.observed.businessExecutionIndexRecheckCommandRowCount === 1, 'summary should record business execution index recheck command row count');
  2100. assert(summary.observed.businessExecutionIndexProofOpenCount === 5, 'summary should record business execution index proof open count');
  2101. assert(summary.observed.businessExecutionIndexDirectCustomerProof === false, 'summary should record business execution index proof boundary');
  2102. assert(summary.observed.businessExecutionIndexLongRunReadinessSummary.includes('long-run-readiness-summary.json'), 'summary should record business execution longrun readiness source');
  2103. assert(summary.observed.businessExecutionIndexLongRunReadinessReport.includes('long-run-readiness-report.md'), 'summary should record business execution longrun readiness report');
  2104. assert(summary.observed.businessExecutionIndexLongRunReadinessReady === false, 'summary should record business execution longrun ready state');
  2105. assert(summary.observed.businessExecutionIndexLongRunReadinessFailCount === 5, 'summary should record business execution longrun fail count');
  2106. assert(summary.observed.businessExecutionIndexOptimizationCompletionSummary.includes('optimization-completion-summary.json'), 'summary should record business execution optimization completion source');
  2107. assert(summary.observed.businessExecutionIndexOptimizationCompletionReport.includes('optimization-completion-report.md'), 'summary should record business execution optimization completion report');
  2108. assert(summary.observed.businessExecutionIndexOptimizationCompletionReadyForClaim === false, 'summary should record business execution optimization ready-for-claim state');
  2109. assert(summary.observed.businessExecutionIndexOptimizationCompletionBlockingReasonCount === 3, 'summary should record business execution optimization blocking reason count');
  2110. assert(summary.observed.handoffBusinessExecutionIndexLongRunReadinessReport.includes('long-run-readiness-report.md'), 'summary should record handoff business execution longrun readiness report');
  2111. assert(summary.observed.handoffBusinessExecutionIndexLongRunReadinessSummary.includes('long-run-readiness-summary.json'), 'summary should record handoff business execution longrun readiness summary');
  2112. assert(summary.observed.handoffBusinessExecutionIndexLongRunReadinessStatus === 'blocked', 'summary should record handoff business execution longrun status');
  2113. assert(summary.observed.handoffBusinessExecutionIndexLongRunReadinessReady === false, 'summary should record handoff business execution longrun ready state');
  2114. assert(summary.observed.handoffBusinessExecutionIndexLongRunReadinessFailCount === 5, 'summary should record handoff business execution longrun fail count');
  2115. assert(summary.observed.handoffBusinessExecutionIndexOperatorPackOwnerArtifactCount === 3, 'summary should record handoff business execution operator owner artifact count');
  2116. assert(summary.observed.handoffOptimizationCompletionReport.includes('optimization-completion-report.md'), 'summary should record handoff optimization completion report');
  2117. assert(summary.observed.handoffOptimizationCompletionReadyForClaim === false, 'summary should record handoff optimization ready-for-claim state');
  2118. assert(summary.observed.handoffOptimizationCompletionProofGapOpenCount === 5, 'summary should record handoff optimization proof-gap count');
  2119. assert(summary.observed.handoffOptimizationCompletionBlockingReasonCount === 3, 'summary should record handoff optimization blocking reason count');
  2120. assert(summary.observed.handoffBusinessExecutionIndexOptimizationCompletionReport.includes('optimization-completion-report.md'), 'summary should record handoff business execution optimization completion report');
  2121. assert(summary.observed.handoffBusinessExecutionIndexOptimizationCompletionSummary.includes('optimization-completion-summary.json'), 'summary should record handoff business execution optimization completion summary');
  2122. assert(summary.observed.handoffBusinessExecutionIndexOptimizationCompletionStatus === 'blocked', 'summary should record handoff business execution optimization completion status');
  2123. assert(summary.observed.handoffBusinessExecutionIndexOptimizationCompletionReadyForClaim === false, 'summary should record handoff business execution optimization ready-for-claim state');
  2124. assert(summary.observed.handoffBusinessExecutionIndexOptimizationCompletionBlockingReasonCount === 3, 'summary should record handoff business execution optimization blocking reason count');
  2125. assert(summary.observed.realProofIntakeBundlePassed === true, 'summary should record real proof intake bundle pass state');
  2126. assert(summary.observed.realProofIntakeBundleComplete === false, 'summary should record real proof intake bundle incomplete state');
  2127. assert(summary.observed.realProofIntakeBundleProofOpenCount === 5, 'summary should record real proof intake bundle proof open count');
  2128. assert(summary.observed.realProofIntakeBundleExportRowCount === 37, 'summary should record real proof intake bundle export row count');
  2129. assert(summary.observed.realProofIntakeBundleRecheckCommandCount === 6, 'summary should record real proof intake bundle recheck command count');
  2130. assert(summary.observed.realProofIntakeBundleOperatorPackEvidenceRowCount === 5, 'summary should record real proof bundle operator evidence row count');
  2131. assert(summary.observed.realProofIntakeBundleOperatorPackNextActionCount === 5, 'summary should record real proof bundle operator next action count');
  2132. assert(summary.observed.realProofIntakeBundleOperatorPackMissingProofRequirementCount === 23, 'summary should record real proof bundle operator missing proof requirement count');
  2133. assert(summary.observed.realProofIntakeBundleOperatorPackOwnerArtifactCount === 3, 'summary should record real proof bundle operator owner artifact count');
  2134. assert(summary.observed.realProofIntakeBundleLongRunReadinessReport.includes('long-run-readiness-report.md'), 'summary should record real proof bundle longrun readiness report');
  2135. assert(summary.observed.realProofIntakeBundleLongRunReadinessReady === false, 'summary should record real proof bundle longrun ready state');
  2136. assert(summary.observed.realProofIntakeBundleLongRunReadinessFailCount === 5, 'summary should record real proof bundle longrun fail count');
  2137. assert(summary.observed.realProofIntakeBundleLongRunReadinessProofLevel === 'not_business_proof', 'summary should record real proof bundle longrun proof level');
  2138. assert(summary.observed.realProofIntakeBundleLongRunReadinessDirectCustomerProof === false, 'summary should record real proof bundle longrun proof boundary');
  2139. assert(summary.observed.realProofIntakeBundleVideoAbPreflightContext === true, 'summary should record real proof bundle video A/B preflight context');
  2140. assert(summary.observed.intakeFieldChecklistPassed === true, 'summary should record intake field checklist pass state');
  2141. assert(summary.observed.intakeFieldChecklistItemCount === 4, 'summary should record intake field checklist item count');
  2142. assert(summary.observed.intakeFieldChecklistMissingRequiredCount === 2, 'summary should record intake field checklist missing required count');
  2143. assert(summary.observed.intakeFieldChecklistPlaceholderCount === 2, 'summary should record intake field checklist placeholder count');
  2144. assert(summary.observed.intakeFieldChecklistDirectCustomerProof === false, 'summary should record intake field checklist proof boundary');
  2145. assert(summary.observed.intakeFieldChecklistOwnerGroupCount === 2, 'summary should record intake field checklist owner group count');
  2146. assert(summary.observed.intakeFieldChecklistRecheckCommandCount === 4, 'summary should record intake field checklist recheck command count');
  2147. assert(summary.observed.proofGapSoftwareFormPassed === true, 'summary should record proof-gap software form pass state');
  2148. assert(summary.observed.proofGapSoftwareFormRowCount === 5, 'summary should record proof-gap software form row count');
  2149. assert(summary.observed.proofGapSoftwareFormDuplicateIdCount === 0, 'summary should record proof-gap software form duplicate id count');
  2150. assert(summary.observed.latestFormIndexPassed === true, 'summary should record latest form index pass state');
  2151. assert(summary.observed.latestFormIndexPrimaryForm.includes('tihao-proof-gap-software-form.csv'), 'summary should record indexed proof form');
  2152. assert(summary.observed.latestFormIndexClientList.includes('software-client-list.final.csv'), 'summary should record indexed client list');
  2153. assert(summary.observed.latestFormIndexClientListRowCount === 28, 'summary should record indexed client list row count');
  2154. assert(summary.observed.latestFormIndexClientListSourceDuplicateRemovedCount === 32, 'summary should record source duplicate rows removed');
  2155. assert(summary.observed.latestFormIndexClientListFinalDuplicateGroupCount === 0, 'summary should record zero final duplicate groups');
  2156. assert(summary.observed.latestFormIndexClientListDuplicateCountMeaning === 'source_duplicate_removed_count', 'summary should record duplicate count meaning');
  2157. assert(summary.observed.latestFormIndexClientListRankContinuous === true, 'summary should record client list rank continuity');
  2158. assert(summary.observed.latestFormIndexClientListDirectCustomerProof === false, 'summary should record client list proof boundary');
  2159. assert(summary.observed.latestFormIndexBusinessExecutionIndex.includes('business-execution-index.md'), 'summary should record indexed business execution index');
  2160. assert(summary.observed.latestFormIndexBusinessExecutionIndexOperatorPackOwnerArtifactCount === 3, 'summary should record indexed business execution operator owner artifact count');
  2161. assert(summary.observed.latestFormIndexBusinessExecutionIndexFieldOwnerRowCount === 1, 'summary should record indexed business execution index field owner row count');
  2162. assert(summary.observed.latestFormIndexBusinessExecutionIndexRecheckCommandRowCount === 1, 'summary should record indexed business execution index recheck command row count');
  2163. assert(summary.observed.latestFormIndexIntakeFieldChecklist.includes('intake-field-checklist.md'), 'summary should record indexed intake field checklist');
  2164. assert(summary.observed.latestFormIndexIntakeFieldChecklistItemCount === 4, 'summary should record indexed intake field checklist item count');
  2165. assert(summary.observed.latestFormIndexIntakeFieldChecklistOwnerGroupCount === 2, 'summary should record indexed intake field checklist owner group count');
  2166. assert(summary.observed.latestFormIndexIntakeFieldChecklistRecheckCommandCount === 4, 'summary should record indexed intake field checklist recheck command count');
  2167. assert(summary.observed.latestFormIndexChinesePlanDoc.includes('tihao-experience-optimization-plan.zh-CN.md'), 'summary should record indexed Chinese optimization plan');
  2168. assert(summary.observed.latestFormIndexChineseActionOrderDoc.includes('business-proof-action-order.zh-CN.md'), 'summary should record indexed Chinese action order');
  2169. assert(summary.observed.latestFormIndexDataRepairCsv.includes('intake-readiness-repair-actions.csv'), 'summary should record data repair csv');
  2170. assert(summary.observed.latestFormIndexDataRepairActionCount === 9, 'summary should record data repair action count');
  2171. assert(summary.observed.latestFormIndexVideoRepairCsv.includes('video-resource-repair-actions.csv'), 'summary should record video repair csv');
  2172. assert(summary.observed.latestFormIndexVideoRepairActionCount === 1, 'summary should record video repair action count');
  2173. assert(summary.observed.latestFormIndexHomepageRepairCsv.includes('homepage-evidence-repair-actions.csv'), 'summary should record homepage repair csv');
  2174. assert(summary.observed.latestFormIndexHomepageRepairActionCount === 2, 'summary should record homepage repair action count');
  2175. assert(summary.observed.latestFormIndexOwnerRepairSummary.includes('intake-readiness-repair-actions.csv'), 'summary should record latest form owner data repair artifact');
  2176. assert(summary.observed.latestFormIndexOwnerRepairSummary.includes('video-resource-repair-actions.csv'), 'summary should record latest form owner video repair artifact');
  2177. assert(summary.observed.latestFormIndexOwnerRepairSummary.includes('homepage-evidence-repair-actions.csv'), 'summary should record latest form owner homepage repair artifact');
  2178. assert(summary.observed.latestFormIndexProofGapOperatorPack.includes('proof-gap-operator-pack.md'), 'summary should record latest form proof-gap operator pack report');
  2179. assert(summary.observed.latestFormIndexProofGapOperatorPackOpenCount === 5, 'summary should record latest form proof-gap operator pack open count');
  2180. assert(summary.observed.latestFormIndexProofGapOperatorPackOwnerGroupCount === 3, 'summary should record latest form proof-gap operator pack owner group count');
  2181. assert(summary.observed.latestFormIndexProofGapOperatorPackOwnerArtifactCount === 3, 'summary should record latest form proof-gap operator pack owner artifact count');
  2182. assert(summary.observed.latestFormIndexProofGapOperatorPackRecheckCommandCount === 7, 'summary should record latest form proof-gap operator pack recheck command count');
  2183. assert(summary.observed.latestFormIndexProofGapOperatorPackEvidenceRowCount === 5, 'summary should record latest form proof-gap operator pack evidence row count');
  2184. assert(summary.observed.latestFormIndexProofGapOperatorPackNextActionCount === 5, 'summary should record latest form proof-gap operator pack next action count');
  2185. assert(summary.observed.latestFormIndexProofGapOperatorPackGapIds.includes('historical-dataset'), 'summary should record latest form proof-gap operator pack gap IDs');
  2186. assert(summary.observed.latestFormIndexNextActionsTopCount === 5, 'summary should record latest form next actions top action count');
  2187. assert(summary.observed.latestFormIndexNextActionsProofGapOpenCount === 5, 'summary should record latest form next actions proof-gap open count');
  2188. assert(summary.observed.latestFormIndexPlanExecutionStatusOperatorPackOwnerArtifactCount === 3, 'summary should record latest form plan execution operator owner artifact count');
  2189. assert(summary.observed.latestFormIndexLongRunReadinessReport.includes('long-run-readiness-report.md'), 'summary should record latest form longrun readiness report');
  2190. assert(summary.observed.latestFormIndexLongRunReadinessReady === false, 'summary should record latest form longrun ready state');
  2191. assert(summary.observed.latestFormIndexLongRunReadinessFailCount === 5, 'summary should record latest form longrun fail count');
  2192. assert(summary.observed.latestFormIndexLongRunReadinessProofLevel === 'not_business_proof', 'summary should record latest form longrun proof level');
  2193. assert(summary.observed.latestFormIndexLongRunReadinessDirectCustomerProof === false, 'summary should record latest form longrun proof boundary');
  2194. assert(summary.observed.localSeedToIntakeWorklistProofLevel === 'not_business_proof', 'summary should record local seed worklist proof level');
  2195. assert(summary.observed.localSeedToIntakeWorklistDirectCustomerProof === false, 'summary should record local seed worklist proof boundary');
  2196. assert(summary.observed.localSeedToIntakeWorklistCanCloseProofGap === false, 'summary should record local seed worklist proof-gap boundary');
  2197. assert(summary.observed.localSeedToIntakeWorklistHistoryDraftRows === 1, 'summary should record local seed worklist history rows');
  2198. assert(summary.observed.localSeedToIntakeWorklistCandidateSeedRows === 12, 'summary should record local seed worklist candidate rows');
  2199. assert(summary.observed.localSeedToIntakeWorklistVideoCandidateNeedsResourceRows === 3, 'summary should record local seed worklist video candidate needs resource rows');
  2200. assert(summary.observed.latestFormIndexLocalSeedToIntakeWorklistMarkdown.includes('local-seed-to-intake-worklist.md'), 'summary should record latest form local seed worklist markdown');
  2201. assert(summary.observed.latestFormIndexLocalSeedToIntakeWorklistHistoryDraftRows === 1, 'summary should record latest form local seed worklist history rows');
  2202. assert(summary.observed.latestFormIndexLocalSeedToIntakeWorklistCandidateSeedRows === 12, 'summary should record latest form local seed worklist candidate rows');
  2203. assert(summary.observed.latestFormIndexLocalSeedToIntakeWorklistVideoCandidateNeedsResourceRows === 3, 'summary should record latest form local seed worklist video candidate resource rows');
  2204. assert(summary.observed.latestFormIndexLocalSeedToIntakeWorklistCanCloseProofGap === false, 'summary should record latest form local seed worklist proof-gap boundary');
  2205. assert(summary.observed.realProofClosureWorkOrderProofLevel === 'not_business_proof', 'summary should record real proof closure work order proof level');
  2206. assert(summary.observed.realProofClosureWorkOrderDirectCustomerProof === false, 'summary should record real proof closure work order direct proof boundary');
  2207. assert(summary.observed.realProofClosureWorkOrderCanCloseProofGap === false, 'summary should record real proof closure work order proof-gap boundary');
  2208. assert(summary.observed.realProofClosureWorkOrderRequiresHumanRealMaterial === true, 'summary should record real proof closure work order human material requirement');
  2209. assert(summary.observed.realProofClosureWorkOrderWorkOrderCount === 19, 'summary should record real proof closure work order count');
  2210. assert(summary.observed.realProofClosureWorkOrderOwnerArtifactCount === 3, 'summary should record real proof closure work order owner artifact count');
  2211. assert(summary.observed.realProofClosureWorkOrderProofGapOpenCount === 5, 'summary should record real proof closure work order open proof gap count');
  2212. assert(summary.observed.realProofClosureWorkOrderIntakeFailureCount === 9, 'summary should record real proof closure work order intake failure count');
  2213. assert(summary.observed.realProofClosureWorkOrderRealCandidateRows === 0, 'summary should record real proof closure work order real candidate rows');
  2214. assert(summary.observed.realProofClosureWorkOrderVideoAbPreflightContext === true, 'summary should record real proof closure work order video A/B preflight context');
  2215. assert(summary.observed.latestFormIndexRealProofClosureWorkOrderMarkdown.includes('real-proof-closure-work-order.md'), 'summary should record latest form real proof closure work order markdown');
  2216. assert(summary.observed.latestFormIndexRealProofClosureWorkOrderWorkOrderCount === 19, 'summary should record latest form real proof closure work order count');
  2217. assert(summary.observed.latestFormIndexRealProofClosureWorkOrderOwnerArtifactCount === 3, 'summary should record latest form real proof closure work order owner artifact count');
  2218. assert(summary.observed.latestFormIndexRealProofClosureWorkOrderCanCloseProofGap === false, 'summary should record latest form real proof closure work order proof-gap boundary');
  2219. assert(summary.observed.handoffChinesePlanDoc.includes('tihao-experience-optimization-plan.zh-CN.md'), 'summary should record handoff Chinese optimization plan');
  2220. assert(summary.observed.handoffChineseActionOrderDoc.includes('business-proof-action-order.zh-CN.md'), 'summary should record handoff Chinese action order');
  2221. assert(summary.observed.handoffLatestFormIndexOwnerGroupCount === 2, 'summary should record handoff latest form owner group count');
  2222. assert(summary.observed.handoffLatestFormIndexRecheckCommandCount === 4, 'summary should record handoff latest form recheck command count');
  2223. assert(summary.observed.handoffLatestFormIndexNextActionsTopCount === 5, 'summary should record handoff latest form next actions top action count');
  2224. assert(summary.observed.handoffLatestFormIndexNextActionsProofGapOpenCount === 5, 'summary should record handoff latest form next actions proof-gap open count');
  2225. assert(summary.observed.handoffLocalSeedToIntakeWorklistMarkdown.includes('local-seed-to-intake-worklist.md'), 'summary should record handoff local seed worklist markdown');
  2226. assert(summary.observed.handoffLocalSeedToIntakeWorklistHistoryDraftRows === 1, 'summary should record handoff local seed worklist history rows');
  2227. assert(summary.observed.handoffLocalSeedToIntakeWorklistCandidateSeedRows === 12, 'summary should record handoff local seed worklist candidate rows');
  2228. assert(summary.observed.handoffLocalSeedToIntakeWorklistVideoCandidateNeedsResourceRows === 3, 'summary should record handoff local seed worklist video candidate resource rows');
  2229. assert(summary.observed.handoffLocalSeedToIntakeWorklistCanCloseProofGap === false, 'summary should record handoff local seed worklist proof-gap boundary');
  2230. assert(summary.observed.handoffLatestFormIndexLocalSeedToIntakeWorklistMarkdown.includes('local-seed-to-intake-worklist.md'), 'summary should record handoff latest form local seed worklist markdown');
  2231. assert(summary.observed.handoffLatestFormIndexLocalSeedToIntakeWorklistHistoryDraftRows === 1, 'summary should record handoff latest form local seed worklist history rows');
  2232. assert(summary.observed.handoffLatestFormIndexLocalSeedToIntakeWorklistCandidateSeedRows === 12, 'summary should record handoff latest form local seed worklist candidate rows');
  2233. assert(summary.observed.handoffLatestFormIndexLocalSeedToIntakeWorklistVideoCandidateNeedsResourceRows === 3, 'summary should record handoff latest form local seed worklist video candidate resource rows');
  2234. assert(summary.observed.handoffLatestFormIndexLocalSeedToIntakeWorklistCanCloseProofGap === false, 'summary should record handoff latest form local seed worklist proof-gap boundary');
  2235. assert(summary.observed.handoffRealProofClosureWorkOrderMarkdown.includes('real-proof-closure-work-order.md'), 'summary should record handoff real proof closure work order markdown');
  2236. assert(summary.observed.handoffRealProofClosureWorkOrderWorkOrderCount === 19, 'summary should record handoff real proof closure work order count');
  2237. assert(summary.observed.handoffRealProofClosureWorkOrderOwnerArtifactCount === 3, 'summary should record handoff real proof closure work order owner artifact count');
  2238. assert(summary.observed.handoffRealProofClosureWorkOrderCanCloseProofGap === false, 'summary should record handoff real proof closure work order proof-gap boundary');
  2239. assert(summary.observed.handoffLatestFormIndexRealProofClosureWorkOrderMarkdown.includes('real-proof-closure-work-order.md'), 'summary should record handoff latest form real proof closure work order markdown');
  2240. assert(summary.observed.handoffLatestFormIndexRealProofClosureWorkOrderWorkOrderCount === 19, 'summary should record handoff latest form real proof closure work order count');
  2241. assert(summary.observed.handoffLatestFormIndexRealProofClosureWorkOrderOwnerArtifactCount === 3, 'summary should record handoff latest form real proof closure work order owner artifact count');
  2242. assert(summary.observed.handoffLatestFormIndexRealProofClosureWorkOrderCanCloseProofGap === false, 'summary should record handoff latest form real proof closure work order proof-gap boundary');
  2243. assert(summary.observed.handoffLongRunReadinessReport.includes('long-run-readiness-report.md'), 'summary should record handoff longrun readiness report');
  2244. assert(summary.observed.handoffLongRunReadinessReady === false, 'summary should record handoff longrun ready state');
  2245. assert(summary.observed.handoffLongRunReadinessFailCount === 5, 'summary should record handoff longrun fail count');
  2246. assert(summary.observed.handoffLongRunReadinessProofLevel === 'not_business_proof', 'summary should record handoff longrun proof level');
  2247. assert(summary.observed.handoffLongRunReadinessDirectCustomerProof === false, 'summary should record handoff longrun proof boundary');
  2248. assert(summary.observed.handoffLatestFormIndexLongRunReadinessReport.includes('long-run-readiness-report.md'), 'summary should record handoff latest form longrun readiness report');
  2249. assert(summary.observed.handoffLatestFormIndexLongRunReadinessReady === false, 'summary should record handoff latest form longrun ready state');
  2250. assert(summary.observed.handoffLatestFormIndexLongRunReadinessFailCount === 5, 'summary should record handoff latest form longrun fail count');
  2251. assert(summary.observed.handoffPlanExecutionStatusOperatorPackOwnerArtifactCount === 3, 'summary should record handoff plan execution operator owner artifact count');
  2252. assert(summary.observed.handoffOwnerRepairSummary.includes('intake-readiness-repair-actions.csv'), 'summary should record handoff owner data repair artifact');
  2253. assert(summary.observed.handoffOwnerRepairSummary.includes('video-resource-repair-actions.csv'), 'summary should record handoff owner video repair artifact');
  2254. assert(summary.observed.handoffOwnerRepairSummary.includes('homepage-evidence-repair-actions.csv'), 'summary should record handoff owner homepage repair artifact');
  2255. assert(summary.observed.handoffProofGapOperatorPackReport.includes('proof-gap-operator-pack.md'), 'summary should record handoff proof-gap operator pack report');
  2256. assert(summary.observed.handoffProofGapOperatorPackSummary.includes('proof-gap-operator-pack-summary.json'), 'summary should record handoff proof-gap operator pack summary');
  2257. assert(summary.observed.handoffProofGapOperatorPackOpenCount === 5, 'summary should record handoff proof-gap operator pack open count');
  2258. assert(summary.observed.handoffProofGapOperatorPackOwnerGroupCount === 3, 'summary should record handoff proof-gap operator pack owner group count');
  2259. assert(summary.observed.handoffProofGapOperatorPackOwnerArtifactCount === 3, 'summary should record handoff proof-gap operator pack owner artifact count');
  2260. assert(summary.observed.handoffProofGapOperatorPackRecheckCommandCount === 7, 'summary should record handoff proof-gap operator pack recheck command count');
  2261. assert(summary.observed.handoffProofGapOperatorPackEvidenceRowCount === 5, 'summary should record handoff proof-gap operator pack evidence row count');
  2262. assert(summary.observed.handoffProofGapOperatorPackNextActionCount === 5, 'summary should record handoff proof-gap operator pack next action count');
  2263. assert(summary.observed.handoffProofGapOperatorPackGapIds.includes('manual-review-and-customer-effect'), 'summary should record handoff proof-gap operator pack gap IDs');
  2264. assert(summary.observed.proofGapClosureOpenCount === 5, 'summary should record proof-gap closure open count');
  2265. assert(summary.observed.proofGapClosureBusinessOpenCount === 5, 'summary should record proof-gap closure business open count');
  2266. assert(summary.observed.proofGapClosureBusinessClosedCount === 0, 'summary should record proof-gap closure business closed count');
  2267. assert(summary.observed.proofGapClosureBusinessGapCount === 5, 'summary should record proof-gap closure business gap count');
  2268. assert(summary.observed.proofGapClosureTotalRows === 6, 'summary should record proof-gap closure total rows');
  2269. assert(summary.observed.proofGapClosurePrecheckOpenCount === 1, 'summary should record proof-gap closure precheck open count separately');
  2270. assert(summary.observed.proofGapClosureCountSemanticsOpenCount === 'business_gap_open_count_excludes_precheck_rows', 'summary should record proof-gap closure count semantics');
  2271. assert(summary.observed.proofGapClosureVideoAbPreflightReadyForVideoAb === false, 'summary should record proof-gap closure video A/B preflight readiness');
  2272. assert(summary.observed.proofGapClosureVideoAbPreflightFailureCount === 4, 'summary should record proof-gap closure video A/B preflight failure count');
  2273. assert(summary.observed.proofGapClosureOpenRowsWithMissingProofRequirements === 5, 'summary should record proof-gap closure open rows with missing proof requirements');
  2274. assert(summary.observed.handoffProofGapClosureOpenCount === 5, 'summary should record handoff proof-gap closure open count');
  2275. assert(summary.observed.handoffProofGapClosureBusinessOpenCount === 5, 'summary should record handoff proof-gap closure business open count');
  2276. assert(summary.observed.handoffProofGapClosureBusinessClosedCount === 0, 'summary should record handoff proof-gap closure business closed count');
  2277. assert(summary.observed.handoffProofGapClosureBusinessGapCount === 5, 'summary should record handoff proof-gap closure business gap count');
  2278. assert(summary.observed.handoffProofGapClosureTotalRows === 6, 'summary should record handoff proof-gap closure total rows');
  2279. assert(summary.observed.handoffProofGapClosurePrecheckOpenCount === 1, 'summary should record handoff proof-gap closure precheck open count separately');
  2280. assert(summary.observed.handoffProofGapClosureCountSemanticsOpenCount === 'business_gap_open_count_excludes_precheck_rows', 'summary should record handoff proof-gap closure count semantics');
  2281. assert(summary.observed.handoffProofGapClosureRows === 6, 'summary should record handoff proof-gap closure rows');
  2282. assert(summary.observed.handoffVideoAbMissingProofCount === 6, 'summary should record handoff video A/B missing proof requirements');
  2283. assert(summary.observed.handoffProofGapClosureOpenRowsWithMissingProofRequirements === 5, 'summary should record handoff proof-gap closure open rows with missing proof requirements');
  2284. assert(summary.observed.feedbackLoopClosureDirectCustomerProof === false, 'summary should record feedback loop proof boundary');
  2285. assert(summary.observed.feedbackLoopClosureLeakedCount === 0, 'summary should record feedback loop leaked count');
  2286. assert(summary.observed.handoffFeedbackLoopClosureDirectCustomerProof === false, 'summary should record handoff feedback loop proof boundary');
  2287. assert(summary.observed.homepageEvidenceReadinessReady === false, 'summary should record homepage readiness state');
  2288. assert(summary.observed.homepageEvidenceReadinessDirectCustomerProof === false, 'summary should record homepage readiness proof boundary');
  2289. assert(summary.observed.homepageEvidenceReadinessProofLevel === 'not_business_proof', 'summary should record homepage readiness proof level');
  2290. assert(summary.observed.homepageEvidenceReadinessFailureCount === 2, 'summary should record homepage readiness failure count');
  2291. assert(summary.observed.homepageEvidenceReadinessRepairActionCount === 2, 'summary should record homepage readiness repair action count');
  2292. assert(summary.observed.handoffHomepageEvidenceReadinessDirectCustomerProof === false, 'summary should record handoff homepage readiness proof boundary');
  2293. assert(summary.observed.planExecutionStatusOperatorPackOwnerArtifactCount === 3, 'summary should record plan execution operator owner artifact count');
  2294. assert(summary.observed.planExecutionStatusBusinessExecutionOperatorPackOwnerArtifactRowCount === 3, 'summary should record plan execution business execution operator owner artifact row count');
  2295. assert(summary.checks.some(item => item.id.startsWith('log-')), 'summary should include implementation-log hint checks');
  2296. assert(report.includes('# 每轮沉淀审计'), 'report should be Chinese');
  2297. assert(report.includes('proofGap.unresolvedCount'), 'report should show proof-gap unresolved count');
  2298. assert(report.includes('proofGap.templateRowsReady'), 'report should show proof-gap template row readiness');
  2299. assert(report.includes('proofGap.templateColumnsReady'), 'report should show proof-gap template column readiness');
  2300. assert(report.includes('proofGapOperatorPack.gapIds'), 'report should show proof-gap operator pack gap IDs');
  2301. assert(report.includes('proofGapOperatorPack.ownerArtifactCount'), 'report should show proof-gap operator pack owner artifact count');
  2302. assert(report.includes('proofGapOperatorPack.recheckCommandCount'), 'report should show proof-gap operator pack recheck command count');
  2303. assert(report.includes('proofGapOperatorPack.evidenceRowCount'), 'report should show proof-gap operator pack evidence row count');
  2304. assert(report.includes('proofGapOperatorPack.nextActionCount'), 'report should show proof-gap operator pack next action count');
  2305. assert(report.includes('proofGapOperatorPack.openRowsWithMissingProofRequirements'), 'report should show proof-gap operator pack missing proof row count');
  2306. assert(report.includes('proofGapOperatorPack.videoAbPreflightContext'), 'report should show proof-gap operator pack video A/B preflight context');
  2307. assert(report.includes('intakeReadiness.ready'), 'report should show intake readiness state');
  2308. assert(report.includes('longRunReadiness.ready'), 'report should show longrun readiness state');
  2309. assert(report.includes('businessProofProgress.blocked_by_external_data'), 'report should show business proof progress blocked count');
  2310. assert(report.includes('businessProofProgress.operatorPackOwnerArtifactCount'), 'report should show business proof progress operator owner artifact count');
  2311. assert(report.includes('handoff.businessProofProgressOperatorPackOwnerArtifactCount'), 'report should show handoff business proof progress operator owner artifact count');
  2312. assert(report.includes('businessProofNextActions.count'), 'report should show business proof next actions count');
  2313. assert(report.includes('businessProofNextActions.topActionCount'), 'report should show business proof next actions top action count');
  2314. assert(report.includes('businessProofNextActions.withMissingProofRequirements'), 'report should show business proof next actions missing proof requirement count');
  2315. assert(report.includes('handoff.businessProofNextActions.count'), 'report should show handoff business proof next actions count');
  2316. assert(report.includes('handoff.businessProofNextActions.topActionCount'), 'report should show handoff business proof next top action count');
  2317. assert(report.includes('handoff.businessProofNextActions.proofGapOpenCount'), 'report should show handoff business proof next proof gap open count');
  2318. assert(report.includes('optimizationCompletion.readyForClaim'), 'report should show optimization ready-for-claim state');
  2319. assert(report.includes('optimizationCompletion.blockingReasonsWithMissingProofRequirements'), 'report should show optimization completion missing proof row count');
  2320. assert(report.includes('optimizationCompletion.canClaim.tihaoRateImproved'), 'report should show tihao-rate claim boundary');
  2321. assert(report.includes('optimizationCompletion.sourceFiles.history'), 'report should show optimization completion history source');
  2322. assert(report.includes('optimizationCompletion.sourceFiles.customerEffect'), 'report should show optimization completion customer-effect source');
  2323. assert(report.includes('optimizationCompletion.recursiveProofArtifactDiscovery'), 'report should show optimization completion recursive proof artifact discovery');
  2324. assert(report.includes('optimizationCompletion.videoAbPreflightFailureCount'), 'report should show optimization completion video A/B preflight failure count');
  2325. assert(report.includes('businessExecutionIndex.rowCount'), 'report should show business execution index row count');
  2326. assert(report.includes('businessExecutionIndex.operatorPackOwnerArtifactCount'), 'report should show business execution operator owner artifact count');
  2327. assert(report.includes('businessExecutionIndex.fieldOwnerRowCount'), 'report should show business execution index field owner row count');
  2328. assert(report.includes('businessExecutionIndex.recheckCommandRowCount'), 'report should show business execution index recheck command row count');
  2329. assert(report.includes('businessExecutionIndex.directCustomerProof'), 'report should show business execution index proof boundary');
  2330. assert(report.includes('businessExecutionIndex.longRunReadinessReport'), 'report should show business execution longrun readiness report');
  2331. assert(report.includes('businessExecutionIndex.longRunReadinessReady'), 'report should show business execution longrun ready state');
  2332. assert(report.includes('businessExecutionIndex.optimizationCompletionReport'), 'report should show business execution optimization completion report');
  2333. assert(report.includes('businessExecutionIndex.optimizationCompletionReadyForClaim'), 'report should show business execution optimization ready-for-claim state');
  2334. assert(report.includes('handoff.businessExecutionIndex.longRunReadinessReport'), 'report should show handoff business execution longrun readiness report');
  2335. assert(report.includes('handoff.businessExecutionIndex.longRunReadinessStatus'), 'report should show handoff business execution longrun readiness status');
  2336. assert(report.includes('handoff.businessExecutionIndex.operatorPackOwnerArtifactCount'), 'report should show handoff business execution operator owner artifact count');
  2337. assert(report.includes('handoff.optimizationCompletionReport'), 'report should show handoff optimization completion report');
  2338. assert(report.includes('handoff.businessExecutionIndex.optimizationCompletionReport'), 'report should show handoff business execution optimization completion report');
  2339. assert(report.includes('handoff.businessExecutionIndex.optimizationCompletionStatus'), 'report should show handoff business execution optimization completion status');
  2340. assert(report.includes('realProofIntakeBundle.exportRowCount'), 'report should show real proof intake bundle export row count');
  2341. assert(report.includes('realProofIntakeBundle.operatorPackEvidenceRowCount'), 'report should show real proof bundle operator evidence row count');
  2342. assert(report.includes('realProofIntakeBundle.operatorPackNextActionCount'), 'report should show real proof bundle operator next action count');
  2343. assert(report.includes('realProofIntakeBundle.operatorPackOwnerArtifactCount'), 'report should show real proof bundle operator owner artifact count');
  2344. assert(report.includes('realProofIntakeBundle.longRunReadinessReport'), 'report should show real proof bundle longrun readiness report');
  2345. assert(report.includes('realProofIntakeBundle.longRunReadinessReady'), 'report should show real proof bundle longrun ready state');
  2346. assert(report.includes('realProofIntakeBundle.videoAbPreflightContext'), 'report should show real proof bundle video A/B preflight context');
  2347. assert(report.includes('intakeFieldChecklist.itemCount'), 'report should show intake field checklist item count');
  2348. assert(report.includes('intakeFieldChecklist.directCustomerProof'), 'report should show intake field checklist proof boundary');
  2349. assert(report.includes('intakeFieldChecklist.ownerGroupCount'), 'report should show intake field checklist owner group count');
  2350. assert(report.includes('intakeFieldChecklist.recheckCommandCount'), 'report should show intake field checklist recheck command count');
  2351. assert(report.includes('proofGapSoftwareForm.passed'), 'report should show proof-gap software form pass state');
  2352. assert(report.includes('proofGapSoftwareForm.rowCount'), 'report should show proof-gap software form row count');
  2353. assert(report.includes('latestFormIndex.passed'), 'report should show latest form index pass state');
  2354. assert(report.includes('latestFormIndex.primaryForm'), 'report should show indexed proof form');
  2355. assert(report.includes('latestFormIndex.clientListFinalDuplicateGroupCount'), 'report should show client list final duplicate group count');
  2356. assert(report.includes('latestFormIndex.clientListDuplicateCountMeaning'), 'report should show client list duplicate count meaning');
  2357. assert(report.includes('latestFormIndex.businessExecutionIndex'), 'report should show indexed business execution index');
  2358. assert(report.includes('latestFormIndex.businessExecutionIndexOperatorPackOwnerArtifactCount'), 'report should show indexed business execution operator owner artifact count');
  2359. assert(report.includes('latestFormIndex.businessExecutionIndexFieldOwnerRowCount'), 'report should show indexed business execution index field owner row count');
  2360. assert(report.includes('latestFormIndex.businessExecutionIndexRecheckCommandRowCount'), 'report should show indexed business execution index recheck command row count');
  2361. assert(report.includes('latestFormIndex.intakeFieldChecklist'), 'report should show indexed intake field checklist');
  2362. assert(report.includes('latestFormIndex.intakeFieldChecklistOwnerGroupCount'), 'report should show indexed intake field checklist owner group count');
  2363. assert(report.includes('latestFormIndex.intakeFieldChecklistRecheckCommandCount'), 'report should show indexed intake field checklist recheck command count');
  2364. assert(report.includes('latestFormIndex.chinesePlanDoc'), 'report should show indexed Chinese optimization plan');
  2365. assert(report.includes('latestFormIndex.chineseActionOrderDoc'), 'report should show indexed Chinese action order');
  2366. assert(report.includes('latestFormIndex.nextActionsTopCount'), 'report should show latest form next actions top action count');
  2367. assert(report.includes('latestFormIndex.nextActionsProofGapOpenCount'), 'report should show latest form next actions proof-gap open count');
  2368. assert(report.includes('latestFormIndex.dataRepairCsv'), 'report should show data repair csv');
  2369. assert(report.includes('latestFormIndex.videoRepairCsv'), 'report should show video repair csv');
  2370. assert(report.includes('latestFormIndex.homepageRepairCsv'), 'report should show homepage repair csv');
  2371. assert(report.includes('latestFormIndex.ownerRepairSummary'), 'report should show latest form owner repair summary');
  2372. assert(report.includes('latestFormIndex.proofGapOperatorPack'), 'report should show latest form proof-gap operator pack');
  2373. assert(report.includes('latestFormIndex.proofGapOperatorPackOwnerArtifactCount'), 'report should show latest form proof-gap operator pack owner artifact count');
  2374. assert(report.includes('latestFormIndex.planExecutionStatusOperatorPackOwnerArtifactCount'), 'report should show latest form plan execution operator owner artifact count');
  2375. assert(report.includes('latestFormIndex.longRunReadinessReport'), 'report should show latest form longrun readiness report');
  2376. assert(report.includes('latestFormIndex.longRunReadinessReady'), 'report should show latest form longrun ready state');
  2377. assert(report.includes('localSeedToIntakeWorklist.historyDraftRows'), 'report should show local seed worklist history rows');
  2378. assert(report.includes('localSeedToIntakeWorklist.candidateSeedRows'), 'report should show local seed worklist candidate rows');
  2379. assert(report.includes('latestFormIndex.localSeedToIntakeWorklist'), 'report should show latest form local seed worklist');
  2380. assert(report.includes('latestFormIndex.localSeedToIntakeWorklistCanCloseProofGap'), 'report should show latest form local seed worklist proof-gap boundary');
  2381. assert(report.includes('realProofClosureWorkOrder.workOrderCount'), 'report should show real proof closure work order count');
  2382. assert(report.includes('realProofClosureWorkOrder.canCloseProofGap'), 'report should show real proof closure work order proof-gap boundary');
  2383. assert(report.includes('realProofClosureWorkOrder.videoAbPreflightContext'), 'report should show real proof closure work order video A/B preflight context');
  2384. assert(report.includes('latestFormIndex.realProofClosureWorkOrder'), 'report should show latest form real proof closure work order');
  2385. assert(report.includes('handoff.realProofClosureWorkOrder'), 'report should show handoff real proof closure work order');
  2386. assert(report.includes('handoff.latestFormIndex.realProofClosureWorkOrder'), 'report should show handoff latest form real proof closure work order');
  2387. assert(report.includes('handoff.chinesePlanDoc'), 'report should show handoff Chinese optimization plan');
  2388. assert(report.includes('handoff.chineseActionOrderDoc'), 'report should show handoff Chinese action order');
  2389. assert(report.includes('handoff.latestFormIndex.ownerGroupCount'), 'report should show handoff latest form owner group count');
  2390. assert(report.includes('handoff.latestFormIndex.recheckCommandCount'), 'report should show handoff latest form recheck command count');
  2391. assert(report.includes('handoff.latestFormIndex.nextActionsTopCount'), 'report should show handoff latest form next actions top action count');
  2392. assert(report.includes('handoff.latestFormIndex.nextActionsProofGapOpenCount'), 'report should show handoff latest form next actions proof-gap open count');
  2393. assert(report.includes('handoff.localSeedToIntakeWorklist'), 'report should show handoff local seed worklist');
  2394. assert(report.includes('handoff.latestFormIndex.localSeedToIntakeWorklist'), 'report should show handoff latest form local seed worklist');
  2395. assert(report.includes('handoff.longRunReadinessReport'), 'report should show handoff longrun readiness report');
  2396. assert(report.includes('handoff.latestFormIndex.longRunReadinessReport'), 'report should show handoff latest form longrun readiness report');
  2397. assert(report.includes('handoff.planExecutionStatusOperatorPackOwnerArtifactCount'), 'report should show handoff plan execution operator owner artifact count');
  2398. assert(report.includes('handoff.ownerRepairSummary'), 'report should show handoff owner repair summary');
  2399. assert(report.includes('handoff.proofGapOperatorPackReport'), 'report should show handoff proof-gap operator pack report');
  2400. assert(report.includes('handoff.proofGapOperatorPackOwnerArtifactCount'), 'report should show handoff proof-gap operator pack owner artifact count');
  2401. assert(report.includes('handoffProofGapClosure.openCount'), 'report should show handoff proof-gap closure open count');
  2402. assert(report.includes('handoffProofGapClosure.businessOpenCount'), 'report should show handoff proof-gap closure business open count');
  2403. assert(report.includes('handoffProofGapClosure.precheckOpenCount'), 'report should show handoff proof-gap closure precheck open count');
  2404. assert(report.includes('handoffProofGapClosure.countSemantics.openCount'), 'report should show handoff proof-gap closure count semantics');
  2405. assert(report.includes('handoffProofGapClosure.videoAbMissingProofCount'), 'report should show handoff video A/B missing proof count');
  2406. assert(report.includes('handoffProofGapClosure.openRowsWithMissingProofRequirements'), 'report should show handoff proof-gap closure missing proof row count');
  2407. assert(report.includes('feedbackLoopClosure.directCustomerProof'), 'report should show feedback loop proof boundary');
  2408. assert(report.includes('feedbackLoopClosure.leakedCount'), 'report should show feedback loop leaked count');
  2409. assert(report.includes('homepageEvidenceReadiness.ready'), 'report should show homepage readiness state');
  2410. assert(report.includes('homepageEvidenceReadiness.directCustomerProof'), 'report should show homepage readiness proof boundary');
  2411. assert(report.includes('homepageEvidenceReadiness.failureCount'), 'report should show homepage readiness failure count');
  2412. assert(report.includes('planExecutionStatus.operatorPackOwnerArtifactCount'), 'report should show plan execution operator owner artifact count');
  2413. assert(report.includes('planExecutionStatus.businessExecutionOperatorPackOwnerArtifactRowCount'), 'report should show plan execution business execution operator owner artifact row count');
  2414. assert(report.includes('proofGapClosure.openCount'), 'report should show proof-gap closure open count');
  2415. assert(report.includes('proofGapClosure.businessOpenCount'), 'report should show proof-gap closure business open count');
  2416. assert(report.includes('proofGapClosure.precheckOpenCount'), 'report should show proof-gap closure precheck open count');
  2417. assert(report.includes('proofGapClosure.countSemantics.openCount'), 'report should show proof-gap closure count semantics');
  2418. assert(report.includes('proofGapClosure.sourceFiles.history'), 'report should show proof-gap closure history source');
  2419. assert(report.includes('proofGapClosure.sourceFiles.customerEffect'), 'report should show proof-gap closure customer-effect source');
  2420. assert(report.includes('proofGapClosure.recursiveProofArtifactDiscovery'), 'report should show proof-gap closure recursive proof artifact discovery');
  2421. assert(report.includes('proofGapClosure.videoAbPreflightFailureCount'), 'report should show proof-gap closure video A/B preflight failure count');
  2422. assert(report.includes('proofGapClosure.openRowsWithMissingProofRequirements'), 'report should show proof-gap closure missing proof row count');
  2423. assert(report.includes('evidence.video-ab-runtime-preflight'), 'report should show video A/B runtime preflight evidence count');
  2424. assert(report.includes('补证操作顺序'), 'report should show proof action order source');
  2425. assert(!/sk-[A-Za-z0-9_-]{10,}/.test(report), 'report should not contain model token patterns');
  2426. assert(!/r:[A-Za-z0-9]{20,}/.test(report), 'report should not contain Parse sessionToken patterns');
  2427. console.log(JSON.stringify({
  2428. ok: true,
  2429. outputDir,
  2430. passCount: summary.counts.pass,
  2431. failCount: summary.counts.fail,
  2432. proofGapUnresolvedCount: summary.observed.proofGapUnresolvedCount,
  2433. latestFormIndexNextActionsTopCount: summary.observed.latestFormIndexNextActionsTopCount,
  2434. handoffLatestFormIndexNextActionsTopCount: summary.observed.handoffLatestFormIndexNextActionsTopCount
  2435. }, null, 2));
  2436. }
  2437. function assert(condition, message) {
  2438. if (!condition) throw new Error(message);
  2439. }
  2440. main();