update-S5-completion-acceptance.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. """Write local final acceptance and progress; no production mutations."""
  2. from pathlib import Path
  3. from datetime import datetime, timezone
  4. from hashlib import sha256
  5. import json
  6. ROOT = Path('F:/kangshifu-board')
  7. DOCS = Path('F:/文档/工作坊当前资料')
  8. WORK = ROOT / 'work'
  9. BACKUP = WORK / 'S5-progress-before-completion-acceptance-20261103'
  10. RECEIPT = WORK / 'live-S5-completion-independent-acceptance-20261103.json'
  11. REPORT = DOCS / '59-课堂完成独立验收与偏差补记.md'
  12. data_file = WORK / 'live-S5-completion-readback-20261103-02.json'
  13. browser_file = WORK / 'live-S5-completion-browser-verified-20261103.json'
  14. data = json.loads(data_file.read_text(encoding='utf-8'))
  15. browser = json.loads(browser_file.read_text(encoding='utf-8'))
  16. assert data['ok'] and browser['ok']
  17. assert data['checksPassed'] == 9 and len(browser['checks']) == 77
  18. assert all(c['passed'] for c in browser['checks']) and not browser['errors']
  19. assert data['progressState'] == browser['progressState'] == 'completed'
  20. assert data['eventId'] == 'MV6JyC6Jcx' and data['pendingQuestionCount'] == 13
  21. assert not REPORT.exists() and not RECEIPT.exists() and not BACKUP.exists()
  22. digest = lambda path: sha256(path.read_bytes()).hexdigest()
  23. old_names = ['52-S5桌面方案审阅与定稿.md', '53-发给运维001-S5方案与报告准备.txt', '54-发给王刚001-S5方案与课堂报告保存.txt', '55-S5方案与课堂报告独立验收结果.md', '56-课堂总结与完成条件.md', '57-发给运维001-课堂完成准备.txt', '58-发给王刚001-课堂完成与回读.txt', 'ksf-S5-classroom-next-20261103.zip', 'ksf-S5-classroom-completion-20261103.zip']
  24. old_hashes = {name: digest(DOCS / name) for name in old_names}
  25. originals = {name: (DOCS / name).read_bytes() for name in ['01-工作进展汇报.txt', '02-后续待补资料.md', 'README.md']}
  26. visual = [path for path in browser['screenshots'] if any(k in path for k in ['project-desktop', 'project-mobile', 'report-mobile', 'pending-mobile'])]
  27. assert len(visual) == 4
  28. receipt = {
  29. 'ok': True, 'at': datetime.now(timezone.utc).isoformat(),
  30. 'operation': 'live-S5-classroom-completion-independent-acceptance',
  31. 'classroomCompletionAccepted': True, 'stageCode': 'S5', 'progressState': 'completed',
  32. 'status': 'workshop', 'dataMode': 'live', 'projectId': data['projectId'],
  33. 'sessionId': data['sessionId'], 'opportunityId': data['opportunityId'],
  34. 'conceptId': data['conceptId'], 'artifactId': data['artifactId'],
  35. 'outputSourceId': data['outputSourceId'], 'completionEventId': data['eventId'],
  36. 'projectArtifactIds': data['projectArtifactIds'], 'projectEventCount': 8,
  37. 'projectEvents': data['projectEvents'], 'conceptCount': 1, 'conceptVersion': 1,
  38. 'pendingQuestionCount': 13, 'completionRequestId': data['completionRequestId'],
  39. 'committedCompletionAuditCount': 1, 'completionWriteKeyMatchesRunbook': True,
  40. 'dataChecks': 9, 'browserChecks': 77, 'browserVerified': True,
  41. 'browserVerificationStoredLocallyOnly': True, 'viewports': [1440, 390],
  42. 'readOnly': True, 'businessWrites': 0, 'oldReportsPreserved': True,
  43. 'historicalS5RequestIdDeviations': data['historicalS5RequestIdDeviations'],
  44. 'historicalExecutionFullyConformsToRunbook': False,
  45. 'formalReportPublished': False, 'employeeConfirmed': False, 'enterpriseApproval': False,
  46. 'physicalMarketOrProductionValidationPerformed': False,
  47. 'remoteFilesInvocationIdsExitcodesAndIdentityBasis': 'Operator reports only; Codex has not independently read the remote filesystem or original CLI receipts.',
  48. 'timestampCheckCorrection': data['timestampCheckCorrection'],
  49. 'visualReview': {'performed': True, 'screenshots': visual},
  50. 'evidenceFiles': [{'path': str(p), 'sha256': digest(p)} for p in [data_file, browser_file, WORK / 'live-S5-completion-readback-20261103.json']],
  51. 'screenshots': [{'path': str(ROOT / p), 'sha256': digest(ROOT / p)} for p in browser['screenshots']],
  52. 'retainedHistoricalDocuments': old_hashes, 'documentationBackup': str(BACKUP),
  53. }
  54. report = '''# 课堂完成独立验收与偏差补记
  55. 2026年11月3日。Codex独立读取生产项目、完成事件、成功写入审计及成果,并使用新的匿名生产浏览器核对电脑/手机页面。确认本次课堂收尾成功,项目为S5 / completed;历史执行偏差另行保留。本轮Codex没有业务写入。
  56. | 项目 | 独立核实结果 |
  57. |---|---|
  58. | 项目 | S_CikxZeBs;stageCode=S5、progressState=completed、status=workshop、dataMode=live |
  59. | 会话 / 机会卡 | btrFqkz0yw / QE9hjtCj8E;归属与互链保持一致,机会仍为hypothesis |
  60. | 当前概念 | QO0uo8nisk,第1版,reviewState=pending |
  61. | 项目成果 | 恰3份:XF4h-Z7l5o(S3)、U3_W7WDliP(S4)、tLkz2MAoIw(S5) |
  62. | 完成事件 | MV6JyC6Jcx,sequence=8,eventType=completed,fromStage/toStage均S5 |
  63. | 完成写键 | KSF-真实资料-20261102-01:portion-fit-project:complete:v1;成功审计恰1条,与58号一致 |
  64. | 未决问题 | 13条逐字保留;旧报告各自的问题集未覆盖 |
  65. | 数据检查 | 9项通过;最终一轮13次生产只读调用(含匿名公开投影) |
  66. | 生产浏览器 | 1440px电脑及390px手机,77项检查通过;8张截图,4张代表截图目视复核 |
  67. | 确认 / 发布 / 企业批准 | 均未发生;enterpriseApproval=false |
  68. | 实物 / 市场 / 量产验证 | 均未发生 |
  69. [S5方案报告](https://kangshifu.fmode.cn/report/tLkz2MAoIw) · [项目进度页](https://kangshifu.fmode.cn/members)。
  70. ## 完成状态与留存
  71. 本次完成成功审计的operation=workshop-transition,receipt准确对应项目S_CikxZeBs、事件MV6JyC6Jcx、S5/completed及enterpriseApproval=false。完成事件的note逐字等于510字节固定模板,projectRef/sessionRef准确,未关联新artifact;原7条事件的编号与顺序不变。会话step=completed,项目status仍为workshop,不能要求其变成completed。
  72. | 序号 | eventId | eventType |
  73. |---|---|---|
  74. | 1 | GGDTcg5YTy | project_created |
  75. | 2 | RkkTTE_xeb | task_submitted(S3) |
  76. | 3 | hOFghbcMsY | stage_changed(S4) |
  77. | 4 | VlGFu_jv4b | task_submitted(S4) |
  78. | 5 | 0ya0a03U9G | stage_changed(S5) |
  79. | 6 | qKnPnVkZA8 | concept_saved |
  80. | 7 | iUs3JwZ9Kf | task_submitted(S5) |
  81. | 8 | MV6JyC6Jcx | completed |
  82. 同会话机会卡和项目各1个,同项目概念1个;同工作坊报告仍9份,S5只有第1版。S5正文3655码点、5章15节5张表、4来源/4引文、13问题和固定模板相同;正文来源5zsPtYFL1u没有变化。既有S1—S4相应版本正文/章节/引文/问题集仍与各原模板一致。概念未知规格四项null、空配方/工艺、pending审阅状态保持原样。当前概念指针在status响应的project.currentConceptRef,概念记录在响应顶层concept对象;不能从响应顶层取currentConceptRef。
  83. 本次58号三个CLI命令为1写2读,完整调用编号、12文件/权限、stderr和退出码依据王刚001回报;Codex没有独立读取远端文件或原始CLI回执。独立数据核实了完成写键及成功审计,不用写审计表证明读命令的历史调用次数。
  84. ## 补记两处S5历史请求键偏差
  85. | 54号步骤 | 规定requestId | 实际requestId | 核查依据 |
  86. |---|---|---|---|
  87. | 06 workshop-save | KSF-真实资料-20261102-01:S5:save:v1 | KSF-真实资料-20261102-01:portion-fit-project:S5:save:v1 | Codex独立核成功写入审计;55号已记录 |
  88. | 07 workshop-read | KSF-真实资料-20261102-01:S5:read:v1 | KSF-真实资料-20261102-01:portion-fit-project:S5:read:v1 | 据运维001对远端回执的核查回报;Codex未独立取得该回执 |
  89. 55号当时独立核查覆盖写入审计,不能据此覆盖读请求键。本次按运维回报补记第07步,并保留证据等级;“两步共同使用项目前缀”是所报回执呈现的形态,变化原因仍未知。不得写成8步全部按规定键执行,也不将运维的原始回执核查升级为Codex独立读取。
  90. 两处偏差不通过重跑来修复:不补存、不补跑旧读命令、不删记录、不换键,不回改54/55/56号、原模板或包。58号本次完成写键独立核实与规定一致;课堂完成不抹去历史偏差。
  91. ## 页面和字段口径
  92. 两种屏宽的匿名生产成员页均显示该项目“S5 · 课堂完成”;电脑显示3份成果和方案已保存,手机折叠行可见项目名和课堂完成。公开数据模型指向同一概念、同一3报告。阶段页、报告列表、S5正文/13问题可见表、原来源引文抽屉及旧S4仍可打开,无运行/网络错误或页面级横向溢出;浏览器只调用匿名公开看板读取,无私表扫描或服务凭据。
  93. S5报告中“S5/in_progress”“本轮不包含completed”保留提交当时的描述,报告生成于完成事件之前;当前项目状态另由进度页显示completed。本次不为追改历史描述新存报告。
  94. browserVerified=true仅存本地独立验收证据,未回写生产。正式发布/员工确认布尔值由S5成功保存回执核为false;dashboardPublishedAt是记录上的发布时间字段,目前为null,不能把它说成“只存在保存响应”。完成操作不调用正式确认/发布流程。
  95. 保留三项显示改进:手机四列表格较窄;商品页引文沿用“—人独立提到”的人数未知标签;手机长出处需抽屉内横滚。本轮没有改前端,不能说这些已修复。
  96. 首次完成验收脚本误将旧回报的generatedAt=2026-11-03T04:36:12.012Z作为固定值,检查在此停止。实际现网为2026-11-03T05:19:50.402Z,浏览器显示相应本地时间13:19。此前独立验收未留存该字段原值,因此本次不能证明它何时变化,也不能用旧回报断言生产被改写。已改为校验实际时间有效、正文/章节等对固定模板逐字比较,首次结果保留;未因此执行任何业务重试。
  97. ## 完成范围和后续
  98. S1至S5公开资料课堂流程已走完并留档,包含个体历史线索、待验证假设、桌面评估和待验证方案。13项研究/设计问题继续保留,需求普遍性、支付意愿、当前SKU、实物效果和企业落地依据仍未解决。
  99. 本轮可以结束课堂链;无需再转阶段、重复保存或再次完成。后续若开展真实验证,可从信息理解或份量行为研究另定目标、对象、资源和预先判据;正式报告确认/发布另走真人流程。员工实名绑定、新数字人接入及旧机器人密钥轮换仍是独立待办。
  100. 本地证据:
  101. - F:/kangshifu-board/work/live-S5-completion-independent-acceptance-20261103.json
  102. - F:/kangshifu-board/work/live-S5-completion-readback-20261103.json(首次时间假设检查失败,保留)
  103. - F:/kangshifu-board/work/live-S5-completion-readback-20261103-02.json(最终9项核对)
  104. - F:/kangshifu-board/work/live-S5-completion-browser-verified-20261103.json(77项及8张截图索引)
  105. 01、02及README本轮更新前完整快照:F:/kangshifu-board/work/S5-progress-before-completion-acceptance-20261103/。52—58号和两个S5固定包原字节保留,未覆盖历史结论或回执。
  106. '''
  107. progress = '''工作坊进展(截至2026年11月3日,最终课堂验收见59号)
  108. 真实资料课堂链已完成:项目S_CikxZeBs为S5 / completed、status=workshop、dataMode=live。选定方向“燃魂份量与用餐目的适配”。Codex独立核对完成状态9项、电脑/手机生产浏览器77项通过,并目视复核完成态截图。本轮Codex只读,没有业务写入。
  109. 会话btrFqkz0yw;课堂机会卡QE9hjtCj8E;当前概念QO0uo8nisk第1版。项目仍恰3份报告:XF4h-Z7l5o(S3)、U3_W7WDliP(S4)、tLkz2MAoIw(S5)。事件恰8条,新增末条MV6JyC6Jcx为completed;完成写键KSF-真实资料-20261102-01:portion-fit-project:complete:v1与58号一致,成功审计恰1条。旧报告和13项研究/设计未决问题全部保留。
  110. 课堂完成不表示需求已验证、产品可量产、企业批准、员工确认或正式发布。实物、市场、量产验证均未做;规格未知值null、配方和工艺数组为空仍是资料缺口。历史帖子只证明个体这样说,商品图片页只证明页面展示,不合并同SKU或推定当前在售。
  111. S5历史执行有两处请求键偏差:第06保存实际为…:portion-fit-project:S5:save:v1,规定为…:S5:save:v1(Codex独立核成功审计);第07读取实际为…:portion-fit-project:S5:read:v1,规定为…:S5:read:v1(据运维对远端回执的核查回报,Codex未取得原回执)。变化原因未知,已在59号补记;不补跑、不补存、不删记录,不回改54/55号及原包。课堂收尾不声称全程完全符合执行单。
  112. 本次58号按回报执行1写2读,退出码、调用编号及远端12文件权限依据王刚001回报;独立验收证实生产终态、事件/审计及匿名页面。首次独立检查用了旧回报生成时间而停止,已更正检查口径,原结果保留;当前report.generatedAt为2026-11-03T05:19:50.402Z,不推断历史变化。
  113. 公开看板电脑/手机均显示课堂完成,S5原报告仍保留提交时的in_progress描述,不追改历史。手机窄表、人数未知标签与长出处横滚问题未修复。browserVerified=true只为本地本轮证据,未回写生产。
  114. 课堂链可结束,无需再转阶段或保存。后续是真实研究与正式确认/发布的各自流程;13个未决问题见02/56/59号。员工实名绑定、新数字人接入和旧机器人密钥轮换仍为独立待办。
  115. 项目进度:https://kangshifu.fmode.cn/members
  116. S5报告:https://kangshifu.fmode.cn/report/tLkz2MAoIw
  117. S4报告:https://kangshifu.fmode.cn/report/U3_W7WDliP
  118. 最终验收:59-课堂完成独立验收与偏差补记.md
  119. 更新前快照:F:/kangshifu-board/work/S5-progress-before-completion-acceptance-20261103/。
  120. 52—58号及S5两个固定包保留,不再次执行。
  121. '''
  122. needs = originals['02-后续待补资料.md'].decode('utf-8-sig').replace('\r\n', '\n')
  123. start = needs.index('2026年11月3日更新。')
  124. end = needs.index('\n\n| 研究事项', start)
  125. needs = needs[:start] + '2026年11月3日更新。课堂系统当前S5 / completed;完成事件MV6JyC6Jcx、3报告/1概念/8事件/13问题已独立核对,电脑/手机完成态页面通过77项检查,详见59号。课堂链走完,研究未完成;以下资料缺口全部继续保留,不要求用户现在提供原件,也不重查已知登录墙。历史第06/07步请求键偏差已补记,不补跑。' + needs[end:]
  126. start = needs.index('软件流程状态:')
  127. end = needs.index('\n\n1.', start)
  128. needs = needs[:start] + '软件流程状态:课堂链已完成并独立验收,项目仍3报告、1概念,事件由7增为8,13问题不变。方案规格未知值null、formulaItems/productionSteps为空,均不视为研究结论。13条问题前8条沿用S4,新增5条设计问题如下:' + needs[end:]
  129. start = needs.index('56号已整理课堂总结')
  130. end = needs.index('\n\n前端独立待改:', start)
  131. needs = needs[:start] + '56号总结及57/58号收尾已执行,59号为最终独立验收。无需再转阶段、完成或保存;不重跑53/54/57/58号,不补存新版本。历史第06步保存键偏差由Codex成功审计核实,第07步读取键偏差依据运维回执核查回报,原因未知;不以再次执行修正。正式员工确认/发布、真实研究与企业落地分别推进;当前13项不因课堂完成而关闭。' + needs[end:]
  132. needs = needs.replace('本轮更新前完整快照位于F:/kangshifu-board/work/S5-progress-before-acceptance-20261103/;此前S4快照仍保留。', '本轮更新前完整快照位于F:/kangshifu-board/work/S5-progress-before-completion-acceptance-20261103/;此前快照仍保留。')
  133. readme = originals['README.md'].decode('utf-8-sig').replace('\r\n', '\n')
  134. start = readme.index('当前状态(')
  135. end = readme.index('\n\n以下编号材料', start)
  136. readme = readme[:start] + '当前状态(2026年11月3日):S5 / completed,课堂链已完成并独立验收,详见59号。项目S_CikxZeBs,3报告/1概念/8事件/13未决问题;完成事件MV6JyC6Jcx。9项数据、77项匿名电脑/手机生产浏览器检查通过。尚未员工确认、正式发布或企业批准,实物/市场/量产验证均未做。历史S5第06/07步请求键偏差分别按独立审计/运维回执回报补记;不补跑、不补存、不再完成。后续按实际研究或正式确认/发布各自推进。' + readme[end:]
  137. readme = readme.replace('本轮旧01/02/README完整快照在F:/kangshifu-board/work/S5-progress-before-acceptance-20261103/;S4旧快照仍保留。', '本轮旧01/02/README完整快照在F:/kangshifu-board/work/S5-progress-before-completion-acceptance-20261103/;此前快照仍保留。', 1)
  138. readme = readme.replace('- 56-课堂总结与完成条件.md:当前收尾范围,', '- 59-课堂完成独立验收与偏差补记.md:当前最终结论;课堂completed、9项数据/77项生产浏览器通过,13问题保留,补记第07步读取键偏差。\n- 56-课堂总结与完成条件.md:历史收尾范围,', 1)
  139. readme = readme.replace('- 57-发给运维001-课堂完成准备.txt:下一步;落地1份固定模板、核合同/归属/状态/回执/在途,不代跑完成。', '- 57-发给运维001-课堂完成准备.txt:已回报落地及预检通过,保留不重跑。', 1)
  140. readme = readme.replace('- 58-发给王刚001-课堂完成与回读.txt:57号通过后在真实消息执行3步;project-status→project-progress→project-status,1写2读,只更新课堂完成状态。', '- 58-发给王刚001-课堂完成与回读.txt:已执行1写2读,完成态经59号独立验收,不再执行。', 1)
  141. readme = readme.replace('- ksf-S5-classroom-completion-20261103.zip:9条目、清单8/8;模板两ID为null不可直接提交,生产未完成。', '- ksf-S5-classroom-completion-20261103.zip:已使用的收尾原包,9条目、8/8核验;保留原样,不再次执行。', 1)
  142. readme = readme.replace('- 55-S5方案与课堂报告独立验收结果.md:当前结论;', '- 55-S5方案与课堂报告独立验收结果.md:S5保存阶段历史结论;', 1)
  143. readme = readme.replace('当前入口:\n\n', '当前入口:\n\n- 已完成项目进度:https://kangshifu.fmode.cn/members\n', 1)
  144. updates = {'01-工作进展汇报.txt': progress, '02-后续待补资料.md': needs, 'README.md': readme}
  145. for name, text in updates.items():
  146. assert 'completed' in text and 'MV6JyC6Jcx' in text and '13' in text
  147. assert '未执行完成写入' not in text
  148. BACKUP.mkdir()
  149. for name, content in originals.items():
  150. with (BACKUP / name).open('xb') as stream:
  151. stream.write(content)
  152. with (BACKUP / 'manifest.json').open('x', encoding='utf-8') as stream:
  153. json.dump({n: sha256(b).hexdigest() for n, b in originals.items()}, stream, ensure_ascii=False, indent=2)
  154. with RECEIPT.open('x', encoding='utf-8') as stream:
  155. json.dump(receipt, stream, ensure_ascii=False, indent=2)
  156. with REPORT.open('x', encoding='utf-8') as stream:
  157. stream.write(report)
  158. for name, text in updates.items():
  159. (DOCS / name).write_text(text, encoding='utf-8', newline='\n')
  160. for name, expected in old_hashes.items():
  161. assert digest(DOCS / name) == expected
  162. print(json.dumps({'ok': True, 'businessWrites': 0, 'acceptance': str(REPORT), 'receipt': str(RECEIPT), 'progressState': 'completed', 'oldFilesUnchanged': len(old_hashes), 'updated': list(updates)}, ensure_ascii=True, indent=2))