From 4a6182a76afa8446b96c717cd22226531423c60a Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 30 Jun 2026 14:37:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(ppt):=20=E4=BF=AE=E7=94=9F=E6=88=90=20PPT?= =?UTF-8?q?=20=E7=BC=BA=E5=9B=BE=E5=BD=A2(=E6=89=81=E5=B9=B3=20deck=20?= =?UTF-8?q?=E8=B4=A8=E6=A3=80=20gate=20+=20=E7=AD=96=E7=95=A5=E5=B1=82?= =?UTF-8?q?=E8=A7=86=E8=A7=89=E4=B8=8B=E9=99=90)(bump=200.33.4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 延续缺图标排查,统计最近 ppt生成 任务 24 页 SVG 的元素构成:=0、 =0,整本是 (文字方块),零示意图/图表/配图。根因同 图标——71 个 charts/ 模板没用、content→版式映射形同虚设,且策略层把"Not every page needs a chart"当跳过口子(spec_lock 实际 page_layouts: free design、无 page_charts 段),输出层又无 gate 拦扁平 deck。两层修(用户选定): - A' 输出 gate(svg_quality_checker):统计每页图形图元 // /(rect/line 是版面脚手架不算);≥6 页且文字密集(avg ≥10/页)却全 deck 0 图元 → deck 级 error 退非零(逼回执行重写);多数页无图元 → INFO;<6 页豁免(不误伤极简/teaser)。实测:8 页文字方块→exit 1;任一页带 path→放行;4 页→豁免。 - B' 策略层视觉下限(strategist.md GATE):把 §633「Template Match」从纯建议升为 硬下限——内容 deck(≥6 页)每个能结构化的内容页必须分配视觉处理(page_charts 模板 / page_layouts 结构模板 / §VII 自绘示意图),spec_lock 不许 page_charts + page_layouts 同时空着;给出 content→图形映射速查;明示下游 A' 会硬卡。同步改 SKILL §大纲映射纪律 + §阶段四质检清单 + spec_lock_reference page_charts 段。 诚实边界:prompt+gate 抬下限(逼别交全文字 deck),执行模型设计功力是上限;gate 守"零图形"底线而非"每页必图表",避免误伤极简风。 Co-Authored-By: Claude Opus 4.8 (1M context) --- PROGRESS.md | 8 ++- core/__init__.py | 2 +- skills/ppt/SKILL.md | 4 +- skills/ppt/references/strategist.md | 5 ++ skills/ppt/scripts/svg_quality_checker.py | 65 +++++++++++++++++++++ skills/ppt/templates/spec_lock_reference.md | 2 + 6 files changed, 82 insertions(+), 4 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index 614c3a9..e1d8349 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -2,7 +2,7 @@ > 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`。 -最后更新:2026-06-30(ppt skill 修图标管线四层断点:executor 不放图标/质检不拦/工具断/导出不兜底 + bump 0.33.3) +最后更新:2026-06-30(ppt skill 修"缺图形":扁平 deck 质检 gate + strategist 视觉下限强制 + bump 0.33.4) --- @@ -21,6 +21,12 @@ ## 已完成关键能力 +### 2026-06-30 / ppt skill 修「生成的 PPT 缺图形」:扁平 deck 质检 gate + 策略层视觉下限(bump 0.33.4) +延续缺图标排查,统计最近 ppt生成 任务 24 页 SVG 的元素构成:**``=0、``=0**,整本是 `` 摞 ``(文字方块),零示意图/图表/配图。根因同图标——71 个 `charts/` 模板没用、content→版式映射形同虚设,且策略层把"Not every page needs a chart"当跳过口子(spec_lock 实际 `page_layouts: free design`、无 page_charts 段),输出层无 gate 拦扁平 deck。两层修(用户选定): +- **A' 输出 gate(svg_quality_checker)**:统计每页图形图元 `///`(`rect`/`line` 是版面脚手架不算);**≥6 页且文字密集(avg ``≥10/页)却全 deck 0 图元 → deck 级 error 退非零**;多数页无图元 → INFO;<6 页豁免(不误伤极简/teaser)。实测:8 页文字方块→exit 1;任一页带 path→放行;4 页→豁免。 +- **B' 策略层视觉下限(strategist.md GATE)**:把 §633「Template Match」从纯建议升为硬下限——内容 deck(≥6 页)每个能结构化的内容页必须分配视觉处理(page_charts 模板 / page_layouts 结构模板 / §VII 自绘示意图),**spec_lock 不许 page_charts + page_layouts 同时空着**;给出 content→图形映射速查;明示下游 A' 会硬卡。同步改 SKILL §大纲映射纪律 + §阶段四质检清单 + spec_lock_reference page_charts 段。 +> 诚实边界:prompt+gate 抬下限(逼别交全文字 deck),执行模型设计功力是上限;gate 守"零图形"底线而非"每页必图表",避免误伤极简风。 + ### 2026-06-30 / ppt skill 修「生成的 PPT 缺图标」四层断点(bump 0.33.3) 查真实用户(caoqianming@foxmail.com)两个「ppt生成」任务的 DB 执行轨迹:24 页 SVG 共 0 个 ``。根因是图标管线四个环节没有一个强制图标落地——**策略层(有时)锁图标,执行层不放、质检层不拦、工具层还断着**。四层一起修: - **B 工具断点**:references/SKILL 里 23 处路径仍指向已不存在的 `skills/ppt-master/`(zcbot 是 `skills/ppt/`)→ 模型按文档 `ls .../icons//|grep` 验名得空集 → 放弃图标;且 strategist 强制用的 `icon_sync.py` 在 zcbot 根本没有(GATE 空转,正是某任务连图标都没锁的原因)。修:全量改路径 + 新建 `skills/ppt/scripts/icon_sync.py`(复用 embed_icons 解析,验名+拷进 project/icons,缺名非零退出)。 diff --git a/core/__init__.py b/core/__init__.py index 1dc6803..cbece73 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1,3 +1,3 @@ # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # 改版本只动这一行。 -__version__ = "0.33.3" +__version__ = "0.33.4" diff --git a/skills/ppt/SKILL.md b/skills/ppt/SKILL.md index 4f87f7b..782c2ca 100644 --- a/skills/ppt/SKILL.md +++ b/skills/ppt/SKILL.md @@ -96,7 +96,7 @@ description: 生成 PowerPoint 演示文稿 (.pptx) 文件。✅ 触发:用户 **逐页大纲**(写进 design_spec.md §IX,也是 spec_lock 的 page_rhythm/page_layouts 依据):**论断式标题 + 每页标节奏**(`anchor`/`dense`/`breathing`)。三条硬纪律(大纲阶段定死): - **论断标题**:写结论不写主题("渗透率破 60%" 不是 "行业背景"); - **节奏不雷同**:相邻内容页不同版式;narrative 真正停顿处插 `breathing`(单概念/金句/大图,**禁多卡网格**);不要为凑节奏造填充页; -- **内容→版式映射**:历程→时间轴、循环→闭环、2-4 数字→KPI、并列→网格、单震撼数字→breathing 大字、≥3 数据点→图表(charts/ 模板或自绘)。 +- **内容→版式映射(必须落到 spec,不能整本留空)**:历程→时间轴、循环→闭环、2-4 数字→KPI、并列→网格、单震撼数字→breathing 大字、≥3 数据点→图表(charts/ 模板或自绘);对比→象限/分栏、流程→process_flow、占比→donut、架构→分层、关系→hub_spoke。每个能结构化的内容页都要在 spec_lock 的 `page_charts`/`page_layouts` 落一个视觉处理 —— **内容 deck 不许 page_charts + page_layouts 同时空着**(=啥图都没分配,执行层必堆文字方块)。视觉下限见 strategist.md「GATE — visual floor」;质检会硬卡"全是文字方块"的扁平 deck(见阶段四)。 大纲连同 a–h **一起给用户预览,⛔ BLOCKING 等确认整份结构**后再进阶段二(改文字比改 slide 便宜)。 @@ -137,7 +137,7 @@ references/visual-styles/.md # 锁定的视觉风格 ``` .venv/Scripts/python.exe /scripts/svg_quality_checker.py ``` -- **任何 `error`(禁用特性 / viewBox 不符 / spec_lock 漂移 / **锁了图标 inventory 却全 deck 0 图标** 等)必须改:回阶段三重写该页再跑**,不放过。 +- **任何 `error`(禁用特性 / viewBox 不符 / spec_lock 漂移 / **锁了图标 inventory 却全 deck 0 图标** / **内容 deck 全是文字方块(≥6 页且零 ``/``/``/``)** 等)必须改:回阶段三重写该页再跑**,不放过。 - `warning`(低分辨率图 / 非 PPT 安全字体等):能顺手改就改,否则知会后放行。 - 跑 `svg_output/`(不要在 finalize 后跑 —— finalize 改写 SVG 会掩盖源级违规)。 diff --git a/skills/ppt/references/strategist.md b/skills/ppt/references/strategist.md index faff063..95f1bbc 100644 --- a/skills/ppt/references/strategist.md +++ b/skills/ppt/references/strategist.md @@ -639,6 +639,11 @@ The catalog covers **both data charts and structural information designs**. A "m The most common Strategist failure mode is missing the structural half — treating "chart" as "numeric chart only" and leaving team / agenda / principles / journey pages as text-only when a template would fit. Read the catalog with both lenses. +> 🚧 **GATE — visual floor (the deck must not ship as text-on-rectangles).** "Not every page needs a chart" is true, but an informative multi-page deck that assigns **zero** visual treatments is the #1 quality failure: flat walls of text in boxes, no diagrams / figures / charts / imagery. Hard floor for any content-bearing deck (≥6 pages, not a pure title/quote teaser): +> - Every **content page whose shape matches a catalog Pick clause** MUST get a visual treatment — a `page_charts` entry (chart / infographic template), a `page_layouts` structural template, or an explicit §VII custom-diagram plan (`no-template-match` with the figure described). Text-in-boxes is the fallback only for pages that genuinely carry no structurable shape, and you must be able to name why. +> - **`spec_lock.md` MUST NOT ship a content deck with `page_charts` empty AND `page_layouts` empty/free-design AND no §VII custom-diagram rows.** That combination means no visual was assigned anywhere — re-scan §IX and map each content page's shape to a figure (comparison→columns/quadrant, process/历程→timeline/process_flow, cycle/循环→concentric/segmented_wheel, share→donut/pie, trend→line/area, ranking→bar, architecture→layered_architecture, relations→hub_spoke/mind_map). +> - Downstream enforcement: `svg_quality_checker.py` **hard-fails** any deck (≥6 text-heavy pages) whose Executor output has zero ``/``/``/`` deck-wide. Leaving the visual plan empty here guarantees that failure later — assign the figures now, at the spec stage, where it is cheapest to change. + > **Reading is mandatory; the catalog is a starting point, not a copy target.** > - Fully read `templates/charts/charts_index.json` **before drafting the Eight Confirmations** — the read happens up front, not when you sit down to write Section VII. The file contains `meta` + `charts..summary` only; each `summary` is a selection rule (`"Pick for … Skip if …"`), not a description. There is **no category, quickLookup, or keyword index** — selection is done by semantically matching each page's content shape against all 71 summaries in one pass. > - Not every page needs a chart. When a page's information structure matches a catalog entry, **use that template as a structural starting point** — keep the visualization type and core layout logic, then adapt composition, density, color, decoration, and accompanying elements to fit this deck's content and visual tone. Free adjustment is encouraged; what is forbidden is (a) generating without reading the catalog, and (b) blind verbatim mimicry that ignores the page's actual content weight. diff --git a/skills/ppt/scripts/svg_quality_checker.py b/skills/ppt/scripts/svg_quality_checker.py index e558e43..f769674 100644 --- a/skills/ppt/scripts/svg_quality_checker.py +++ b/skills/ppt/scripts/svg_quality_checker.py @@ -232,6 +232,17 @@ class SVGQualityChecker: self._icon_inventory_declared = False # any page's spec_lock locked icons self._deck_icon_total = 0 # total across the deck self._pages_missing_icons: List[str] = [] # declared-but-icon-less pages + # Visual-richness aggregation (non-template mode). The most common AI-deck + # regression is "wall of text boxes": every page is on with + # zero diagrams, charts, figures, or imagery. /// + # are the unambiguous "this page draws something" primitives — + # rect/line are layout/divider scaffolding and don't count. A content-rich + # deck (>=6 pages, text-heavy) with zero such primitives deck-wide is the + # flat-deck pathology; catch it so it can't ship silently. + self._deck_page_count = 0 # non-template SVG pages checked + self._deck_graphic_total = 0 # path+polyline+polygon+image across deck + self._deck_text_total = 0 # across deck (density signal) + self._pages_no_graphic: List[str] = [] # pages with zero graphic primitives def check_file(self, svg_file: str, expected_format: str = None) -> Dict: """ @@ -316,6 +327,10 @@ class SVGQualityChecker: if not self.template_mode: self._check_icon_usage(content, svg_path, result) + # 12. Check visual richness (flat text-on-rectangles deck). + if not self.template_mode: + self._check_graphic_richness(content, result) + # Determine pass/fail result['passed'] = len(result['errors']) == 0 @@ -1455,6 +1470,53 @@ class SVGQualityChecker: print(" Cover / section / closing pages may legitimately omit icons; " "verify dense content pages aren't missing them.") + def _check_graphic_richness(self, content: str, result: Dict) -> None: + """Tally graphic primitives per page for the deck-level flat-deck gate. + + Counts /// — the elements that actually + draw a diagram, chart, figure, or photo. and are excluded + on purpose: they are layout cards, backgrounds, and dividers, and a deck + built entirely from them is exactly the "text on rectangles" look this + catches. Per-page nudges stay soft; the hard gate is deck-wide. + """ + g = (len(re.findall(r'=6 pages, text-heavy) with zero path/polygon/ + polyline/image deck-wide is the wall-of-text-boxes pathology — hard + error so it can't ship. Below that bar, surface a soft note when most + pages carry no figure. Short or sparse decks (<6 pages) are exempt to + avoid false-failing minimalist / teaser decks. + """ + pages = self._deck_page_count + if pages < 6: + return + avg_text = self._deck_text_total / pages + if self._deck_graphic_total == 0 and avg_text >= 10: + self.summary['errors'] += 1 + print(f"\n[ERROR] Visual richness: {pages} text-heavy pages but ZERO " + "diagram/figure primitives (///) " + "deck-wide — the deck is text on rectangles.") + print(" Map content shape -> a visual: comparison->columns/quadrant, " + "timeline->process, share->donut, trend->line, ≥3 data points->chart " + "(adapt a templates/charts/ template or draw it), add diagrams/imagery, " + "then re-run.") + elif len(self._pages_no_graphic) >= max(6, int(pages * 0.7)): + print(f"\n[INFO] Visual richness: {len(self._pages_no_graphic)}/{pages} pages " + "have no diagram/figure (///) — " + "verify dense content pages aren't just text + boxes.") + def print_summary(self): """Print check summary""" print("=" * 80) @@ -1486,6 +1548,9 @@ class SVGQualityChecker: # Deck-level icon-usage gate (declared inventory but icon-less deck). self._print_icon_summary() + # Deck-level flat-deck gate (text-on-rectangles, no diagrams/figures). + self._print_graphic_summary() + # Fix suggestions if self.summary['errors'] > 0 or self.summary['warnings'] > 0: print(f"\n[TIP] Common fixes:") diff --git a/skills/ppt/templates/spec_lock_reference.md b/skills/ppt/templates/spec_lock_reference.md index 4385e42..05e3790 100644 --- a/skills/ppt/templates/spec_lock_reference.md +++ b/skills/ppt/templates/spec_lock_reference.md @@ -146,6 +146,8 @@ > > **Whole section omitted** → no data-visualization pages in this deck. > +> ⚠️ **Visual floor**: a content-rich deck (≥6 pages) must not leave `page_charts` empty AND `page_layouts` empty/free-design AND carry no §VII custom-diagram rows — that means zero visual treatment was assigned and the Executor will ship a flat text-on-rectangles deck (which `svg_quality_checker.py` hard-fails). See strategist.md "GATE — visual floor". +> > **Strategist source**: copy from `design_spec.md §VII Visualization Reference List` — only the rows whose `reference template path` points to a `templates/charts/` file. Pages marked `no-template-match` in §VII MUST NOT appear here. ## forbidden