| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- """Archive the seventh received round, review scope and local instruction changes."""
- from pathlib import Path
- import difflib
- import hashlib
- import json
- import re
- WORK = Path(__file__).resolve().parent
- ROOT = WORK.parents[1]
- def sha(path):
- return hashlib.sha256(path.read_bytes()).hexdigest()
- def main():
- case = json.loads((WORK / 'case.json').read_bytes())
- edits = json.loads((WORK / 'presentation-edits.json').read_bytes())
- for name, expected in edits['originalFileSha256'].items():
- assert sha(WORK / name) == expected, name
- source = 'rounds/R07/reply-verbatim.md'
- display = 'rounds/R07/reply-display.md'
- transformations = [
- (source, display, '线上回读校验已通过:HTTP 200、34,834 B,本地与线上 sha256 一致,关键内容全部命中。\n\n', '', 'omit operational preface'),
- (source, display, '清单:https://s3.fmode.cn/user/DpPsnlBm0K/report/ksf-banmian-checklist-r1-20261109.html', '清单见“研究成果”中的任务与取舍清单。', 'point to the embedded received report'),
- (source, display, '本轮未新增检索扩搜、未购样、未付费测试、未开展访谈、未编写回答、未改 Skill、未改研究库。\n', '', 'omit operational tail; retain explicit unexecuted interview status in business content'),
- ]
- css = '''<style id="presentation-layout">
- body{font-size:16px}.sub,table.g,table.g th,table.g td,.costs,.costs .c b,.lv,.ss,.qn,.ty,.flag,.qt,.qc,.qr,.qc b,.qr b,.qs,.meta,.vl,.note,.key,ol.ol li,.qs-item,.qs-item .why{font-size:15px!important}
- h2{font-size:21px}h3{font-size:18px}.wrap,.q,.qs-item,.note,.key{min-width:0;overflow-wrap:anywhere}.sc{max-width:100%;overflow-x:auto}table.g{min-width:1260px}table.g th,table.g td{min-width:155px;overflow-wrap:anywhere}.task{min-width:155px}.meta{color:#52635b}.qs a{overflow-wrap:anywhere}
- @media(max-width:640px){.wrap{padding:22px 14px 40px}.q,.qs-item{padding:16px}.key,.note{padding:16px}table.g th,table.g td{padding:12px 10px}}
- </style></head>'''
- transformations.append(('rounds/R07/artifacts/checklist-received.html', 'rounds/R07/artifacts/checklist-display.html', '</head>', css, 'presentation-only readable typography and table scrolling; claims unchanged'))
- received_html = (WORK / 'rounds/R07/artifacts/checklist-received.html').read_text(encoding='utf-8')
- for tag in dict.fromkeys(re.findall(r'<a\b[^>]*>', received_html)):
- if 'target=' not in tag:
- transformations.append(('rounds/R07/artifacts/checklist-received.html', 'rounds/R07/artifacts/checklist-display.html',
- tag, tag[:-1] + ' target="_blank" rel="noopener noreferrer">',
- 'open explicit source chips in a separate tab without replacing the embedded report'))
- displays = {}
- for source, display, before, after, reason in transformations:
- content = displays.get(display, (WORK / source).read_text(encoding='utf-8'))
- assert content.count(before) >= 1, source
- displays[display] = content.replace(before, after)
- record = {'source': source, 'display': display, 'before': before, 'after': after, 'reason': reason}
- if record not in edits['edits']:
- edits['edits'].append(record)
- edits['originalFileSha256'][source] = sha(WORK / source)
- for path, text in displays.items():
- (WORK / path).write_text(text, encoding='utf-8', newline='\n')
- edits['originalFileSha256']['rounds/R07/prompt-verbatim.txt'] = sha(WORK / 'rounds/R07/prompt-verbatim.txt')
- (WORK / 'presentation-edits.json').write_text(json.dumps(edits, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
- received = json.loads((WORK / 'rounds/R07/artifacts/download-receipt.json').read_bytes())
- seventh = next(r for r in case['rounds'] if r['roundId'] == 'R07')
- seventh.update({
- 'status': 'received-checklist-and-interview-draft-reviewed-revision-needed',
- 'forwardedConfirmed': None, 'executionConfirmed': True, 'replyReceived': True,
- 'replyPath': 'rounds/R07/reply-verbatim.md', 'replySha256': sha(WORK / 'rounds/R07/reply-verbatim.md'),
- 'replyComplete': True, 'reviewPath': 'rounds/R07/review.md',
- 'promptExecutionMatch': 'inferred-from-conversation-sequence-not-tool-log',
- 'interviewsConducted': False, 'actualUserDecision': None,
- 'claimsIndependentlyVerified': False,
- 'sourceCheckScope': 'Douban full thread and Thepaper article read locally; PTT intermediary timed out; not all report sources verified',
- 'receivedArtifact': {
- 'path': 'rounds/R07/artifacts/checklist-received.html',
- 'presentationPath': 'rounds/R07/artifacts/checklist-display.html',
- 'url': received['url'], 'httpStatus': received['httpStatus'], 'bytes': received['bytes'], 'sha256': received['sha256'],
- 'sourceAnchorLinks': len(received['sourceLinks']), 'uniqueSourceUrls': len({x['href'] for x in received['sourceLinks']}),
- 'fileIndependentlyDownloaded': True,
- 'scope': 'received report; limited cited-source review, not upstream operations or all research claims',
- },
- })
- if not any(r['roundId'] == 'R08' for r in case['rounds']):
- case['rounds'].append({
- 'roundId': 'R08', 'moduleId': 'D1-04',
- 'purpose': '把价值比较、调味调整及制作体验转为可判别研究任务',
- 'promptPath': 'rounds/R08/prompt-verbatim.txt', 'promptSha256': sha(WORK / 'rounds/R08/prompt-verbatim.txt'),
- 'promptOrigin': 'authored-locally-for-user-forwarding',
- 'status': 'prepared-for-user-forwarding', 'forwardedConfirmed': False,
- 'executionConfirmed': False, 'replyReceived': False, 'reportIds': [], 'actualUserDecision': None,
- })
- case['status'] = 'R07-checklist-and-interview-draft-received-R08-prepared'
- case['currentModuleId'] = 'D1-04'
- case['courseModules'][3]['status'] = 'task-checklist-and-interview-draft-received-neutrality-and-priority-need-revision'
- case['demonstration'].update({'actualReplies': 7, 'status': 'seven-replies-six-artifacts-layout-pending', 'latestReplyComplete': True})
- (WORK / 'case.json').write_text(json.dumps(case, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
- local = WORK / 'rounds/R07/local-skill-review'
- skill = ROOT / 'skills/ksf-workshop-runtime'
- baseline = json.loads((local / 'before-fingerprints.json').read_bytes())
- changed = [name for name, digest in baseline.items() if sha(skill / name) != digest]
- assert set(changed) == {'references/workshop-innovation-reasoning.md', 'references/workshop-research-tasking.md'}, changed
- runtime = [name for name in baseline if name.startswith('scripts/') or name == 'runtime-lock.json']
- assert len(runtime) == 7 and all(sha(skill / name) == baseline[name] for name in runtime)
- (skill / 'FILES.sha256').write_text(''.join(sha(skill / name) + ' ' + name + '\n' for name in baseline), encoding='utf-8', newline='\n')
- for name in changed + ['FILES.sha256']:
- target = local / 'diff' / (name + '.diff')
- target.parent.mkdir(parents=True, exist_ok=True)
- target.write_text(''.join(difflib.unified_diff((local / 'before' / name).read_text(encoding='utf-8').splitlines(True),
- (skill / name).read_text(encoding='utf-8').splitlines(True), fromfile='before/' + name, tofile='local/' + name)), encoding='utf-8')
- assert sha(ROOT / 'docs/workshop-skill-release-20261109-r6/ksf-workshop-skill-update-20261109-r6.zip') == 'c329432b9773cfb0a8e5d4a3e5c162b3778eab28d576b79875da6854f33c4dc5'
- receipt = {'ok': True, 'changedInstructions': changed, 'manifestEntries': len(baseline), 'manifestSha256': sha(skill / 'FILES.sha256'),
- 'runtimeChanged': False, 'remoteInstalled': False, 'sealedR6Modified': False,
- 'basis': 'observed leading interview questions and prioritizing the emptiest evidence row',
- 'changes': [{'path': name, 'before': baseline[name], 'after': sha(skill / name)} for name in changed]}
- (local / 'receipt.json').write_text(json.dumps(receipt, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
- print(json.dumps({'actualReplies': 7, 'artifacts': 6, 'nextPromptExecuted': False, 'remoteInstalled': False}, ensure_ascii=False))
- if __name__ == '__main__':
- main()
|