- Restructure to KONEPS (조달청 협상계약 별지5호) standard TOC: I general / II strategy-methodology / III tech-function / IV performance-quality / V PM / VI support / VII misc - 9 new slides: staffing M/M, quantitative eval, standard framework, PM methodology, handover/training, SM/SLA, incident/BCP, managerial security, subcontracting - Scoring alignment updated to tech 90 (70 qual + 20 quant) / price 10 - Nanobanana win-theme dual placement (II applied-tech + III function) - Appendix D screen gallery (19 Stitch drafts) with AI-draft disclosure - QA PASS: RTM 142/142 (3 fixes: F-008/F-010/F-026), no secrets, honesty labels verified - Preserve rebuild toolchain + source docs in deliverables/제안서/_gen (16 files) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
42 lines
1.8 KiB
Python
42 lines
1.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
import json, io, sys, re
|
||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||
S = json.load(open('_qa_slides.json', encoding='utf-8'))
|
||
|
||
ROMAN = ["Ⅰ","Ⅱ","Ⅲ","Ⅳ","Ⅴ","Ⅵ","Ⅶ","Ⅷ"]
|
||
|
||
print("=== PER-SLIDE STRUCTURE (chapter line + first content) ===")
|
||
for s in S:
|
||
n = s["n"]
|
||
chap = ""
|
||
for t in s["texts"]:
|
||
# chapter header like "Ⅲ. 기술·기능 · ..."
|
||
if any(t.startswith(r + ".") or t.startswith(r + " ") for r in ROMAN):
|
||
chap = t
|
||
break
|
||
# headline = the longest early text that's not chapter/boilerplate
|
||
head = ""
|
||
for t in s["texts"][:6]:
|
||
if t == chap: continue
|
||
if "킨텍스" in t or "2026-07" in t or t in ROMAN: continue
|
||
if len(t) > len(head): head = t
|
||
print(f"{n:>3}| {chap[:46]:<46} | {head[:52]}")
|
||
|
||
print("\n=== 배점 / SCORING TOKENS ===")
|
||
pats = ["80/20","35/80","90/10","70+20","90(","기술 90","기술 80","가격 10","가격 20","정성 70","정량 20","재정렬","공고 확정"]
|
||
for p in pats:
|
||
hits=[(s['n'],t[:80]) for s in S for t in s['texts'] if p in t]
|
||
print(f'--- {p!r}: {len(hits)}')
|
||
for n,t in hits[:8]: print(f' {n}: {t}')
|
||
|
||
print("\n=== HONESTY LABELS ===")
|
||
for p in ["[검증됨]","[구현 계획]","[협의]","[가정]","[Non-Goal]","[공고"]:
|
||
hits=[(s['n'],t[:74]) for s in S for t in s['texts'] if p in t]
|
||
print(f'--- {p!r}: {len(hits)}')
|
||
for n,t in hits[:14]: print(f' {n}: {t}')
|
||
|
||
print("\n=== WATERMARK / AI NOTICE ===")
|
||
for p in ["워터마크","AI 생성","AI-generated","watermark","합성 이미지","예상 이미지","시공 예"]:
|
||
hits=[(s['n'],t[:74]) for s in S for t in s['texts'] if p.lower() in t.lower()]
|
||
print(f'--- {p!r}: {len(hits)} : slides {sorted(set(n for n,_ in hits))}')
|