| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- """Prepare S5 templates and handoffs locally. Does not call any business API."""
- from copy import deepcopy
- from pathlib import Path
- import hashlib
- import json
- ROOT = Path(__file__).resolve().parents[1]
- DOCS = Path('F:/文档/工作坊当前资料')
- OUT = ROOT / 'work/S5-classroom-next-20261103'
- assert not OUT.exists()
- OUT.mkdir()
- BASE = 'KSF-真实资料-20261102-01'
- S4 = json.loads((ROOT / 'work/S4-classroom-next-20261103/05-project-S4-save.template.json').read_text(encoding='utf-8'))
- accepted = json.loads((ROOT / 'work/live-S4-independent-acceptance-20261103.json').read_text(encoding='utf-8'))
- assert accepted['ok'] and accepted['artifactId'] == 'U3_W7WDliP'
- original = Path('C:/Users/JSHY/.codex/attachments/47f3dfe1-3de6-42a3-8709-ce63f100891c/Pasted text.txt').read_bytes()
- with (ROOT / 'work/S5-submitted-draft-20261103.txt').open('xb') as f:
- f.write(original)
- def put(name, value):
- with (OUT / name).open('x', encoding='utf-8', newline='\n') as f:
- f.write(value)
- def put_json(name, value):
- put(name, json.dumps(value, ensure_ascii=False, indent=2) + '\n')
- def para(title, text):
- return {'kind': 'para', 'title': title, 'text': text}
- def table(title, cols, rows):
- return {'kind': 'table', 'title': title, 'data': {'cols': cols, 'rows': rows}}
- pending = list(S4['pendingQuestions']) + [
- '三行分区呈现(净含量/面饼/件数)能否被正确理解,会不会反而更乱。',
- '信息呈现是否增加购买负担(货架识别、比价、货架停留)。',
- '包材版面、渠道素材能否执行,改动成本未知。',
- '“可选搭配”会不会被读成“必须加”,从而反向暗示原份量不足。',
- '研究中记录为何补主食的方式本身会不会影响行为,需要评估记录负担和观察者效应。',
- ]
- inheritance = ['原S4问题'] * 8 + ['承原1、4', '承原4、6', '承原7', '承原8', '承原3、6']
- name = '燃魂份量选择提示与搭配指引(待验证概念)'
- concept = {
- 'name': name,
- 'targetAudience': '拟研究把燃魂拌面用于一次用餐、需要判断一份与当次食量是否适配的人;是假定研究范围,非已证实人群。',
- 'usageScenario': '购买前与制备前判断份量和做法;当次目的可为正餐、加餐或其他,地点、时间、频率等未知。',
- 'specification': {
- 'designScope': '份量与制备信息布局及可选搭配指引;效果待验证,尚未确定新品实物规格。',
- 'packaging': '待核;未选定拟新品包装形态,不把P1图示当目标规格。',
- 'netWeightG': None, 'noodleWeightG': None, 'packCount': None, 'currentSku': None,
- 'informationLayout': ['单份含料净含量单列', '面饼重量单列', '组合件数单列'],
- 'preparation': '拟与后续明确的实际商品包装说明一致;本轮不设煮制时间。',
- 'optionalPairing': '可选搭配与规定步骤分开;不要求加菜,也不承诺搭配解决份量不足。',
- },
- 'valueProposition': '待验证:份量与做法信息集中呈现,帮助使用者判断是否适合当次用餐;不承诺更饱或购买提升。',
- 'flavor': '待核;燃魂是系列线索,不据此确定具体口味。',
- 'sellingPoints': ['待验证:份量与做法一处看明白。', '待验证:规定步骤与可选搭配清楚分开。'],
- 'productionSteps': [], 'pendingQuestions': pending,
- }
- design_rows = [
- ['份量信息', 'P1标题117g×5与参数585克算术一致;单袋图目视含料117克、面饼90克。仅是页面/图示观察。', '拟将单份含料净含量、面饼重量、组合件数分三行标示;一包、一组与一次用餐分开。', '当前及拟新品SKU/规格未知,信息理解未测试;重量不直接证明饱腹程度。'],
- ['煮制信息', 'P1图示6—7分钟;P2作者历史自述自己煮10分钟才软。图示与个体叙述分别保留。', '拟按后续明确商品的实际包装说明呈现制备信息,与可选搭配分开。', '没有购买路径理解测试;P2不证明包装错误或信息位置问题,不设10分钟为新标准。'],
- ['可选搭配', '两篇份量自述中有额外加食,但原因不全清楚;没有本轮干预或食用结果。', '搭配只作可选信息,不要求加菜;允许不搭配,保留真实用餐结果。', '会不会被理解为必须加菜或暗示原份量不足,额外负担与效果均未知。'],
- ['增量/双规格', '现有材料不足以支持选定增量幅度或两档规格。', '仅作有条件的备选;明确商品与用途、取得份量问题证据后再比较。', '克数、价格、袋数、配方、包装、产线及可行性未知;不声称燃魂已有或将推出加量版。'],
- ]
- spec_rows = [
- ['方案性质', '信息布局与可选搭配指引的设计提案', '未验证设计效果,不是已定新品'],
- ['净含量/面饼重量/组合件数', '目标值均待核;结构化数值为null', 'P1标示585克、含料117克、面饼90克及117g×5只作各自页面/图片参考'],
- ['包装形态/当前SKU/具体口味', '均待核', '页面对象不等于已取得样品,旧帖/P1/P2不合并SKU'],
- ['信息布局', '拟三行分别呈现净含量、面饼重量与件数', '是拟定设计,尚未验证理解效果或版面可执行性'],
- ['制备说明', '待明确实际商品后与其包装说明一致', '不把归档6—7分钟或作者10分钟设为拟新品标准'],
- ['配方/配料', '未取得;formulaItems=[]', '不造materialId、比例、用量或供应商,不以空数组认定无需配料'],
- ['生产工艺', '未取得;productionSteps=[]', '不造processId;用户使用、研究和待核步骤不充作生产工序'],
- ['成本/价格/合规', '资料未取得,保持未知', '不填0、不作正向可行性评分,不声称低成本、合规通过或可量产'],
- ]
- quote_rows = [[e['claim'], e['quotes'][0]['text'], e['sourceId']] for e in S4['report']['evidence'].values()]
- validation_rows = [
- ['信息表达', '未来用明确标为概念稿的说明布局做理解观察;目标、对象、记录方式及规则事前确定。', '出现误读、阅读或购买负担时调整版式与文案。', '资源不足或预先规则触发时暂停该设计;无差异不等于已证明无效。'],
- ['份量适配', '有明确商品与实际食用观察后,分别记录用途、习惯、提前加主食与吃后补食的原因。', '习惯与补偿可并存;动机混杂时继续区分,不因习惯存在便排除份量问题。', '缺对象/行为证据则不下结论;不凭未定义的“多数”判定整个份量假设无效。'],
- ['增量/双规格', '份量问题证据足以提出比较后,再事先确定规格、资源、方法和判断规则。', '证据或执行条件不足时调整问题,保留其他解释。', '本轮不实施;暂不推进不等于已经证明方案没有需求。'],
- ['企业可行性', '取得配方、工艺、成本、包材、渠道及相应合规依据后再评。', '依据冲突或条件不满足时调整方案。', '资料未取得则判断为未知,暂停可行性判断,不认定不可行或可量产。'],
- ]
- chapters = [
- {'id': 'scope', 'title': '方案范围与人群场景', 'stage': 'S5', 'sections': [
- para('方案摘要', '把一份面的份量、份数、制备方式和可选搭配集中呈现,供购买前与制备前判断是否适合当次用餐。这是目前可展开比较的设计提案,不是已验证需求;不承诺仅靠文案解决吃不饱。'),
- para('拟研究人群与场景', concept['targetAudience'] + concept['usageScenario'] + '年龄、购买力和购买身份未知,不补造学生夜宵或加班白领等事实画像。'),
- para('拟定使用路径', '购买前判断份量与做法→按后续明确商品的实际包装制备→按本次目的选择是否搭配并食用。这是设计路径,没有真实消费者执行结果。'),
- para('研究记录单列', '若后续开展研究,可另行记录为何补主食;记录方法、时机和负担需审阅。它不作为产品使用的必需步骤,也不默认能无干扰地观察行为。'),
- ]},
- {'id': 'design', 'title': '设计内容与候选卖点', 'stage': 'S5', 'sections': [
- table('设计对照', ['设计项', '已有依据及边界', '拟定设计', '仍需验证'], design_rows),
- para('候选文案', '待验证文案:“份量与做法,一处看明白。一包多少、一组几包、怎么煮,都写在一处。”这是待制作和验证的设计,不是现行包装或已验证卖点。'),
- para('提出设计的理由', 'P1提供页面参数与图示标示,P2提供历史个体制备叙述;两者均未证明“信息分散”或购买路径不清。集中呈现与可选搭配分区是设计假设,理解、购买判断、购买行为与饱腹体验分别验证。设计、包材与渠道执行成本未知。'),
- para('增量与承诺边界', '增量/双规格仅为条件分支,不给克数、价格或配方;不声称燃魂已有加量版。候选文案不作管饱、健康营养、成本最优或固定分钟必熟的承诺。'),
- ]},
- {'id': 'spec', 'title': '规格与执行条件', 'stage': 'S5', 'sections': [
- table('设计、观察与未知', ['项目', '本方案状态', '依据或约束'], spec_rows),
- para('结构化口径', '本轮方案结构可记录待核规格对象、候选卖点和13项未决问题。空配料与工艺数组表示未取得依据,不表示产品不需要原料或工艺。方案保存与阶段报告分别用专用命令,不创建产品、SKU、原料或工艺实体。'),
- ]},
- {'id': 'evidence', 'title': '证据与适用边界', 'stage': 'S5', 'sections': [
- table('主引文', ['支持范围', '逐字引文', 'sourceId'], quote_rows),
- para('历史个案与图示分开', 'cq-03/cq-04为2023年两个显示账号的历史自述。cq-04同文肯定味道;加蛋肠原因未知,cq-03加挂面的原因明确但其他配菜动机未知。P1是公开高清图片页观察,P2为2023年个人叙述;都未核购买身份,不拼成同SKU。来源可支持提出设计,不能证明设计有效或市场普遍需求。'),
- ]},
- {'id': 'validation', 'title': '验证路径与未决问题', 'stage': 'S5', 'sections': [
- table('继续、调整与暂停', ['维度', '何时继续', '何时调整', '何时暂停或不下结论'], validation_rows),
- table('待补问题', ['序号', '待核实问题', '承接关系'], [[str(i + 1), q, inheritance[i]] for i, q in enumerate(pending)]),
- para('阶段结论', '已形成可审阅的信息提示与搭配指引概念;设计效果、当前需求、实物、市场和量产验证未完成。计划保存后项目保持S5 / in_progress;本轮执行不包含completed、员工确认、企业审批或正式发布。'),
- ]},
- ]
- report = {
- 'subtitle': '份量与做法信息呈现的待验证概念,规格与效果待核',
- 'executive': [
- '基于已验收S4公开资料桌面评估形成设计概念,非试吃、市场或量产结果。',
- '主方案是份量选择提示与可选搭配指引;三行信息布局是设计假设,不称已经发现信息分散。',
- '增量或双规格仅为有条件的备选;规格、口味、配方、工艺与成本尚未确定。',
- '沿用4来源/4主引文;保留S4原8项缺口并增加5项设计问题,共13项。',
- ],
- 'method': '依据S4固定内容与既有来源验收进行桌面设计和证据边界审阅;本轮没有新采集、称量、试吃、招募、问卷、A/B测试或市场比例估计。候选文案与信息布局为拟定设计。',
- 'sources': S4['report']['sources'],
- 'chapters': chapters, 'evidence': deepcopy(S4['report']['evidence']),
- }
- title = '燃魂份量选择提示与搭配指引|S5桌面方案 第1版'
- raw_parts = [title, *report['executive']]
- for chapter in chapters:
- raw_parts.append(chapter['title'])
- for section in chapter['sections']:
- raw_parts.append(section['title'])
- if section['kind'] == 'para':
- raw_parts.append(section['text'])
- else:
- raw_parts.append(' | '.join(section['data']['cols']))
- raw_parts.extend(' | '.join(row) for row in section['data']['rows'])
- raw_text = '\n\n'.join(raw_parts)
- tasks = {
- '01-project-S5-progress.template.json': {'sessionId': None, 'projectId': None, 'toStage': 'S5', 'state': 'in_progress',
- 'note': 'S4公开资料桌面评估U3_W7WDliP已保存并独立验收;进入S5形成待验证的信息提示与搭配指引概念,不代表实物、市场或量产验证完成。'},
- '02-concept-save.template.json': {'sessionId': None, 'projectId': None, 'version': 1, 'concept': concept, 'formulaItems': []},
- '03-project-S5-save.template.json': {'sessionId': None, 'projectId': None, 'taskKey': BASE + ':S5', 'version': 1, 'stageCode': 'S5',
- 'title': title, 'artifactType': 'concept', 'category': '拌面', 'rawText': raw_text, 'sourceIds': deepcopy(S4['sourceIds']),
- 'pendingQuestions': pending, 'report': report},
- }
- for filename, task in tasks.items():
- put_json(filename, task)
- request_specs = [
- ('project-status', BASE + ':portion-fit-project:S5:precheck:v1', '00-project-status.json'),
- ('project-progress', BASE + ':portion-fit-project:to-S5:v1', '01-project-S5-progress.json'),
- ('project-status', BASE + ':portion-fit-project:read-S5:v1', '00-project-status.json'),
- ('concept-save', BASE + ':portion-fit-project:concept:save:v1', '02-concept-save.json'),
- ('project-status', BASE + ':portion-fit-project:concept:read:v1', '00-project-status.json'),
- ('workshop-save', BASE + ':S5:save:v1', '03-project-S5-save.json'),
- ('workshop-read', BASE + ':S5:read:v1', '03-project-S5.read.json'),
- ('project-status', BASE + ':portion-fit-project:S5:read-final:v1', '00-project-status.json'),
- ]
- runbook = {'sessionId': 'btrFqkz0yw', 'projectId': 'S_CikxZeBs', 'opportunityId': 'QE9hjtCj8E',
- 'priorS3ArtifactId': 'XF4h-Z7l5o', 'priorS4ArtifactId': 'U3_W7WDliP', 'taskKey': BASE + ':S5',
- 'steps': [{'step': i + 1, 'command': cmd, 'requestId': req, 'inputFile': inp} for i, (cmd, req, inp) in enumerate(request_specs)],
- 'expectedFinal': {'stageCode': 'S5', 'progressState': 'in_progress', 'projectArtifactCount': 3,
- 'projectEventCount': 7, 'conceptVersion': 1, 'formulaItemCount': 0, 'pendingQuestions': 13,
- 'newCommittedWrites': 3, 'formalReportPublished': False, 'employeeConfirmed': False, 'enterpriseApproval': False}}
- put_json('runbook.json', runbook)
- markdown = ['# ' + title, '', '待验证概念;未执行生产保存,系统阶段仍为S4 / in_progress。', '']
- markdown += [p + '\n' for p in report['executive']]
- for chapter in chapters:
- markdown += ['## ' + chapter['title'], '']
- for section in chapter['sections']:
- markdown += ['### ' + section['title'], '']
- if section['kind'] == 'para':
- markdown += [section['text'], '']
- else:
- data = section['data']
- def cell(value):
- return str(value).replace('|', '\\|').replace('\n', '<br>')
- markdown += ['| ' + ' | '.join(data['cols']) + ' |', '| ' + ' | '.join(['---'] * len(data['cols'])) + ' |']
- markdown += ['| ' + ' | '.join(cell(v) for v in row) + ' |' for row in data['rows']]
- markdown += ['']
- put('S5桌面方案第1版-审阅稿.md', '\n'.join(markdown) + '\n')
- review = '''# S5桌面方案审阅与定稿
- 2026年11月3日。王刚001提交的文字草稿可进入固定材料准备,无需再退回重复改稿。Codex已直接校正以下内容,定稿正文见同包《S5桌面方案第1版-审阅稿.md》,具体持久化输入以三份固定模板为准。
- 1. 删去“P1信息分散”这一事实断言。现有参数与图示核查没有验证信息位置或购买路径,集中呈现是设计提案。
- 2. P2只支持作者历史制备叙述,不能证明包装错误、说明位置问题或设计有效;“无任何证据”改为“现有材料不足以支持选定增量幅度/两档规格”,避免抹掉份量历史线索。
- 3. 不用未定义的“多数为习惯”判断整个份量问题停止。习惯与补偿可能并存;资料缺失时暂停相应判断,不写证明无效或不可行。
- 4. 将研究中的“记录为何补主食”从产品使用必经步骤中移出,另列记录负担与观察者效应待验证。
- 5. “四份来源原站核查与购买身份核验沿用50号”更正为“原站核查沿用既有验收;购买身份仍未独立核实”。作者、购买与普遍需求不冒称已核。
- S4原8条pendingQuestions逐字保留;新增5条设计问题,共13条,方案输入与报告及可见表完全对应。四段主引文直接从S4固定报告取值,P1使用真实换行,不把Markdown的<br>写进quote。所有下划线编号保留。
- 未来concept仅记录待验证的信息提示与搭配指引概念。规格数值null,formulaItems=[]、productionSteps=[];没有创建原料/工艺或把研究步骤当生产步骤。pendingQuestions按现网处理写入项目meta.pendingQuestions和保存响应,不要求KfConcept上有同名字段。
- 本轮Codex只做本地审阅准备及另行留证的生产只读预检,没有运行project-progress/concept-save/workshop-save。拟执行后为S5 / in_progress、1个concept v1、项目3份报告及7条事件,不自动completed、员工确认或正式发布。概念、报告和正文来源是三个不同编号;方案并未通过conceptRef直接写进KfArtifact,核对方式为同项目、版本、字段及事件对应,不造不存在的Pointer。
- 王刚001两条业务只读及身份登记调用编号、远端目录8文件/权限/退出码依据提交回报,Codex没有读取该远端文件系统。本轮未将这些回报升级为Codex独立核实。归档原稿保持原字节,系统对象精确编号按runbook.json,不按口头省略下划线的文本拼命令。
- 本包供53号运维落地预检,通过后按54号在王刚001真实消息中执行。沿用用户已选方向,不重新问选项、不要求先提供实物,不重导资料、不建第二套卡或项目。执行前状态或合同有新差异则停核,不能用本地模拟代替生产回读。
- '''
- put('52-S5桌面方案审阅与定稿.md', review)
- hash_lines = '\n'.join(f"{n}:{len((OUT/n).read_bytes())}B,sha256={hashlib.sha256((OUT/n).read_bytes()).hexdigest()}" for n in tasks)
- ops = f'''运维001,请按本包准备S5固定模板;本轮只落地与只读预检,不代跑业务。
- 先读52号审阅裁定及S5审阅稿。沿用用户选定的燃魂份量与用餐目的适配,方案为“份量选择提示与搭配指引”(待验证概念),不是已验证需求或量产新品。当前会话btrFqkz0yw、项目S_CikxZeBs,S4/in_progress;S4成果U3_W7WDliP已验收,不重做S4、不再问方向、不要求用户先交实物。
- 将三份template原样落地/opt/data/ksf-executor-20261103/S5-classroom-next-01/,root:root 0644,hermes实读。三份均sessionId=null/projectId=null,不可直接提交;本轮不生成绑定ID的可执行输入。
- 固定指纹:
- {hash_lines}
- 按FILES.sha256核包,按现网专用命令合同核project-progress / concept-save / workshop-save / project-status / workshop-read。合法转阶段命令是project-progress,不能写project-transition;artifactType=concept,reportType按workshop_auxiliary、artifactSubtype=classroom_task核,不从通用导入表字段推定命令形状。发现差异只报不改Skill/Function/schema/wrapper或放宽校验。
- 核同一当前真实会话/员工/Agent归属,项目仍S4/in_progress,机会QE9hjtCj8E与项目互链;S3基线XF4h-Z7l5o、S4评估U3_W7WDliP恰两份项目成果、四条事件、无concept。只读核四来源/证据对及sourceRef、原文quote、productRef=null:m1OQx9aynA/_9mUml0wmh,QdeMcyTTjX/2bFGP7axMo,PjORcvaRHn/xHGV_mRWcG,5S_Y4IgT5q/CeAEIwymTa,不重导或重新采集。
- 查本项目KfConcept(包括currentConceptRef未挂载的既有版本)与KSF-真实资料-20261102-01:S5系列,无v1或其它版本;查runbook.json八个requestId在KsfOperation的成功写入审计、相关对象与本地回执。读取requestId不保证入KsfOperation,不能据该表声称读命令从未运行。已有对象或回执即停报编号,不换键、删记录或升级版本绕开。
- 核目标/opt/data/ksf-workshop-private/S5-classroom-next-01/及54号所有将生成的输入、stdout/stderr/退出码目标均不存在、无在途;目录仅不存在才新建hermes:hermes0700且确认为空。保留S5-live-00/、S1—S4各版、原第08失败与恢复回执。不要复用或覆盖旧目录。
- 静态自检:pendingQuestions方案与报告恰13条且逐字相同;前8条逐字等于S4;可见待补表13行逐项对应;4来源/4主引文与S4完全相同;specification未知数值为null;formulaItems=[]、productionSteps=[];无opportunity对象,无新project-create。specification是非空JSON对象,不为满足字段临时填数字。
- 本轮不执行project-progress/concept-save/workshop-save,不更新任何旧业务记录或前端,不正式发布。回报模板字节/完整哈希、合同、身份归属、来源、版本/回执/在途及目标文件检查;通过后由用户转交54号王刚001真实消息执行。按原业务键一次执行,任一步失败即停。包内preflight与隔离模拟只证明本地准备,不代替现网结果。
- '''
- put('53-发给运维001-S5方案与报告准备.txt', ops)
- steps_text = '\n'.join(f"{i+1:02d}. {cmd};input={inp};requestId={req}" for i, (cmd, req, inp) in enumerate(request_specs))
- actor = f'''王刚001:本单用于已审阅的S5方案及课堂报告保存。用户此前已选“燃魂份量与用餐目的适配”,本条转交表示继续既有课堂测试,不再问选择。先确认53号落地预检通过,52号校正已纳入固定模板。沿用会话btrFqkz0yw、项目S_CikxZeBs、机会QE9hjtCj8E;不新建会话、卡或项目。
- 一、当前消息身份与输入
- 无参数运行ksfregistercurrent_employee(可信运行时正式工具名以现有接入为准),核完整agentProfileKey与员工/发送者/会话及S4归属一致。不得用旧截断键、姓名或复制身份JSON代替本条真实核验;不一致即停。跨日不自动新会话。
- 三模板位于/opt/data/ksf-executor-20261103/S5-classroom-next-01/;完整哈希如下:
- {hash_lines}
- 执行留存/opt/data/ksf-workshop-private/S5-classroom-next-01/必须为53号已确认的空目录0700。先核目标不存在及无历史回执/在途;每份绑定输入都从模板读进内存,只填sessionId=btrFqkz0yw、projectId=S_CikxZeBs,逐字段差异恰这两处,O_EXCL独占新建0600。所有读输入、每步stdout.json/stderr.log/exitcode也独占新建0600;已有即停查,不覆盖。复用本单只读输入是规定操作,不重建同路径。
- 二、八步固定顺序与requestId
- {steps_text}
- 第01步:独占新建00-project-status.json,仅含{{"sessionId":"btrFqkz0yw","projectId":"S_CikxZeBs"}};核两层ok+EXIT0、项目S4/in_progress/live/workshop、同归属,S3基线XF4h-Z7l5o与S4报告U3_W7WDliP恰两份、事件四条、concept=null、formulaItems=[]。任何变化先停,不套旧状态继续。
- 第02步:从01-project-S5-progress.template.json绑定两ID生成01-project-S5-progress.json,执行一次project-progress;应S5/in_progress、projectId不变、enterpriseApproval=false,取eventId。
- 第03步:复用00-project-status.json;应S5/in_progress、成果仍两份、事件五条,最后一条stage_changed,无concept。
- 第04步:从02-concept-save.template.json绑定两ID生成02-concept-save.json,执行一次concept-save;取conceptId/version=1/projectId/eventId,formulaItemIds=[]、pendingQuestions13条逐字等模板、enterpriseApproval=false。
- 第05步:复用00-project-status.json。核project.currentConceptRef→KfConcept/新conceptId;concept.objectId、projectRef、version1、dataMode=live、recordState=active;name/targetAudience/usageScenario/specification/valueProposition/flavor/sellingPoints/productionSteps逐项等模板,specification含null也做深比。formulaItems=[];项目meta.pendingQuestions13条逐字等模板;事件六条,末条concept_saved;项目成果仍两份。pendingQuestions不要求在KfConcept有同名字段,不能因此重存或补写。previousVersionRef可缺/null,不声称已有版本链。
- 第06步:从03-project-S5-save.template.json绑定两ID生成03-project-S5-save.json,执行一次workshop-save;取新artifactId/sourceId,sessionId及projectId沿用,version1/S5,opportunityId=null。方案conceptId与报告artifactId是不同对象;本报告输入没有conceptRef,不臆造直接Pointer。
- 第07步:根据第06实际返回的artifactId,独占新建03-project-S5.read.json,仅含{{"className":"KfArtifact","objectId":"<新artifactId>"}}。精读核下节所有字段及可见表。
- 第08步:复用00-project-status.json;核项目S5/in_progress,成果恰3份(旧S3、旧S4、本次S5),concept仍第04同一v1,formulaItems=[],meta.pendingQuestions13条;事件恰七条按序:原project_created、task_submitted、stage_changed、task_submitted,再本次stage_changed、concept_saved、task_submitted。最后两条分别为概念保存与S5报告提交。本轮不执行completed,不自行再转阶段。
- 三、命令格式与留存
- 写:node /opt/data/skills/ksf-workshop-runtime/scripts/ksf-secure.mjs <project-progress或concept-save或workshop-save> --agent-profile <本条已核完整agentProfileKey> --input /opt/data/ksf-workshop-private/S5-classroom-next-01/<本步输入名> --request-id <本步完整requestId>
- 读:node /opt/data/skills/ksf-workshop-runtime/scripts/ksf-secure.mjs <project-status或workshop-read> --input /opt/data/ksf-workshop-private/S5-classroom-next-01/<本步输入名> --request-id <本步完整requestId>
- 八步stdout/stderr/退出码按01-precheck、02-to-S5、03-status-S5、04-concept-save、05-concept-status、06-S5-save、07-S5-read、08-final-status分别留存;保存结果编号另做独占JSON记录。每步核外层ok、entryResult.ok、EXIT=0,stderr如有内容逐条解释,不以某个空字段直接宣布失败或通过。
- 四、S5报告精确回读
- 核artifactType=concept、reportType=workshop_auxiliary、artifactSubtype=classroom_task、stageCode=S5、version1、schemaVersion=ksf.v0.7、dataMode=live、dashboardState=workshop、reportSeriesKey={BASE}:S5。ownerSession/sessionRef→btrFqkz0yw,projectId/projectRef→S_CikxZeBs,Agent归属与既有一致,sourceRef→第06返回新正文sourceId,tags含拌面与课堂过程成果。
- rawText逐字等模板;sourceIds恰m1OQx9aynA/QdeMcyTTjX/PjORcvaRHn/5S_Y4IgT5q;evidenceCount4,四段主引文含P1换行逐字与report.evidence全块一致。report.chapters/method/sources/subtitle逐项等模板,executive仅在最前预期增加“课堂过程成果,未经员工正式确认;待验证项不作为市场结论。”,report.title/generatedAt为服务新增。
- meta.workshop.pendingQuestions恰13条且逐字等方案输入与项目meta.pendingQuestions;report中待补问题表13行、原8条与新增5条承接关系全等;其余设计对照/规格/主引文/验证路径表均全块比对。不要只核文字rawText而漏掉可见表。
- boardVisible只在保存响应核为true,不要求回读存在。正式发布/员工确认在保存响应为false,dashboardPublishedAt为null;字段缺失不等于“已正式发布”。enterpriseApproval=false,未开生产浏览器则browserVerified=false,后续Codex按新编号验收;本地预览不能替代生产浏览器。
- 五、停止与边界
- 任一步失败、超时或不确定立即停,保留原requestId、输入、所有已返回编号与完整回执;不自动重试、换键、删记录或回滚。错误不等于零写入;只读失败不因此重做任何save/progress。交Codex按编号核对后决定恢复方式。
- 预期新增仅1个KfConcept v1、1份KfArtifact及其正文KfSource、3条事件和3条写入审计;同一项目达到S5/in_progress。方案pendingQuestions更新项目meta,不覆盖旧报告的8条缺口。无新机会卡/项目/产品/SKU/配方原料/生产工艺,不重导来源,不改S1—S4、Skill/Function/schema/wrapper/前端,不采购、招募或试吃,不代员工确认或正式发布。当前实物、市场和量产验证仍未发生。
- 最终回报八步requestId、两层invocationId、EXIT及stderr,conceptId/artifactId/sourceId/eventId、逐项精确核对结果、项目阶段/成果/事件、实际留存清单和权限。不要把课堂方案存入库说成当前产品已定型或需求已证实。保留S5-live-00/及全部旧回执。
- '''
- put('54-发给王刚001-S5方案与课堂报告保存.txt', actor)
- put('README.txt', 'S5固定材料包:先52审阅,再53运维只读预检,通过后54由王刚001真实消息执行。\n三模板sessionId/projectId为null,不可直接提交。顺序为S4前检→project-progress转S5→concept-save并核→S5报告保存并核→最终状态。\n只记录待验证概念,配方工艺缺资料时数组为空、数值待核。不自动completed或正式发布。不含凭据、浏览器档案或完整私聊。\n')
- put_json('preflight.json', {'ok': True, 'at': '2026-11-03', 'localStructureOnly': True, 'packagePreparationBusinessApiCalls': 0,
- 'productionBusinessWrites': 0, 'saved': False, 'browserVerified': False,
- 'sourceIds': S4['sourceIds'], 'evidenceCount': 4, 'pendingQuestionCount': 13,
- 'originalS4PendingCount': 8, 'newDesignPendingCount': 5, 'rawTextCodepoints': len(raw_text),
- 'chapters': len(chapters), 'tables': [{'title': s['title'], 'cols': len(s['data']['cols']), 'rows': len(s['data']['rows'])}
- for c in chapters for s in c['sections'] if s['kind'] == 'table'],
- 'inputDraftSha256': hashlib.sha256(original).hexdigest(),
- 'scopeNote': 'Separate live read-only preflight and isolated simulation are recorded outside this initial local-structure preparation.'})
- print(json.dumps({'ok': True, 'prepared': str(OUT), 'templates': len(tasks), 'rawTextCodepoints': len(raw_text),
- 'pendingQuestions': len(pending), 'businessApiCalls': 0, 'productionBusinessWrites': 0}, ensure_ascii=True))
|