Skip to content

test: PPT quality eval baseline with svg-pptx route and machine gates (#1273) - #1490

Merged
Astro-Han merged 13 commits into
devfrom
codex/i1273-office-eval-baseline
Jul 8, 2026
Merged

test: PPT quality eval baseline with svg-pptx route and machine gates (#1273)#1490
Astro-Han merged 13 commits into
devfrom
codex/i1273-office-eval-baseline

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds the PPT quality eval harness under packages/opencode/script/ppt-quality-eval/ (3 tasks × 5 routes, OOXML zip-inspection judge, no LibreOffice).
  • Vendors the ppt-master (MIT, b8808a3) svg_to_pptx converter as the svg-pptx route with LICENSE/VENDORED attribution.
  • Adds three machine gates that turned weak-model failure modes into pre-delivery checks: SVG text budget, package assets (notes/chart/media/summary), and refined out-of-bounds shape counting.
  • Fixes two harness bugs: --file array flag swallowing the prompt, and the judge zip reader dropping binary entries (made ppt/media checks always fail).

Eval verdict (recorded in docs/research/2026-07-08-ppt-master-pptist-embed-decision.md)

30 valid runs on deepseek-v4-flash: svg-pptx 5/6 (winner), pptxgenjs 4/6, officecli 3/6 with 0↔100 variance. Gate-verification rerun: template-following × svg-pptx PASS 100.

Closes nothing yet; evidence base for #1273 route switch.

Summary by CodeRabbit

  • New Features

    • Added new evaluation workflows for Office files and PowerPoint decks, including route-specific scoring and reporting.
    • Added new export options and command-line shortcuts for running these evaluations.
    • Added support for packaged notes, narration, and compatibility outputs in presentation generation.
  • Documentation

    • Added guidance for the new evaluation routes, including usage examples and quality rules.
  • Bug Fixes

    • Improved file ignore rules to keep generated artifacts and Python bytecode out of version control.

Adds a third native-PPTX candidate route to the PPT quality eval for
#1273: model-authored SVG per slide, converted deterministically to
native DrawingML by the vendored ppt-master svg_to_pptx package
(MIT, v3.1.0, b8808a3, zero source patches; see VENDORED.md).

- route-skills/svg-pptx-native: converter, SKILL.md with px font
  floors (60px title = 45pt, 24px body = 18pt), per-line character
  budget so SVG text cannot run off-slide, notes/chart/image
  conventions matching the OOXML gates.
- eval.ts: svg-pptx route wiring (skill mapping, uv-only command
  policy, pyproject injection, SVG_PPTX_SCRIPT env, prompt line,
  report aggregation).
- Refine the out-of-bounds gate: content shapes (text, pics, graphic
  frames) stay strict; decorative shapes may bleed off-canvas unless
  their center leaves the slide. Verified against a real run where 4
  intentional bleed circles were false positives and 15 genuine text
  overflows remain failures.
- Weak-model policy: switch eval examples off GPT-5.4 Mini.
opencode run's --file is array-typed; without a trailing --variant the
positional prompt was swallowed as a second file path and the run died
with 'File not found: <prompt>'. Order scalar flags after the --file
pairs so the prompt always follows a non-array flag.
Weak models under-apply the prose character-budget rule (2 of 15
overflow lines survived round one). Add a stdlib-only pre-conversion
check that mirrors the converter's width estimator and fails on any
line outside the 20..1220px safe area; SKILL.md now requires it to
print OK before converting.
@github-actions github-actions Bot added harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority labels Jul 8, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested priority: P2 (includes non-doc, non-test paths outside the low-risk bucket).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

Comment thread packages/opencode/script/office-route-eval/eval.ts Fixed
Comment thread packages/opencode/script/ppt-quality-eval/eval.ts Fixed
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Astro-Han, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 2 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e1019e76-26b2-4ec5-b105-0d2ff2372cfe

📥 Commits

Reviewing files that changed from the base of the PR and between 1015a88 and 95f30f4.

📒 Files selected for processing (6)
  • packages/opencode/package.json
  • packages/opencode/script/office-route-eval/eval.ts
  • packages/opencode/script/ppt-quality-eval/eval.ts
  • packages/opencode/script/ppt-quality-eval/report.md
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/check_text_budget.py
  • packages/opencode/script/ppt-quality-eval/scripts/check_pptx_assets.py
📝 Walkthrough

Walkthrough

This PR introduces two evaluation harnesses under packages/opencode/script/: office-route-eval (comparing officecli vs python Office-document routes) and ppt-quality-eval (scoring multiple PPTX generation routes), each with run/judge/report CLIs, fixtures, and route skill docs. It also vendors a full svg_to_pptx Python engine converting SVG slides into native PPTX, plus a post-build asset-gate script.

Estimated code review effort: 5 (Critical) | ~150 minutes

Changes

Office Route Eval Harness

Layer / File(s) Summary
Repo setup and scripts
.gitignore, packages/opencode/package.json
Adds bytecode ignore rules and office:eval npm script.
Docs, fixtures, skill policies
packages/opencode/script/office-route-eval/README.md, .../route-skills/*/SKILL.md, .../fixtures/*, .../route-templates/python/pyproject.toml, .../runs/.gitignore
Defines route rules, task fixtures, python route dependencies, and run-output ignore rules.
Evaluation core, judging, reporting
.../office-route-eval/eval.ts, .../eval.test.ts, .../report.md
Implements command extraction/policy checks, run execution, artifact judging for xlsx/docx/pptx, report generation, and CLI dispatch with tests.

PPT Quality Eval Harness

Layer / File(s) Summary
Docs, fixtures, skill docs, templates
packages/opencode/script/ppt-quality-eval/README.md, report.md, route-skills/*/SKILL.md, fixtures/*, route-templates/*/pyproject.toml, runs/.gitignore
Documents route rules for officecli/python-pptx/pptxgenjs/svg-pptx/html-showcase, fixtures, and Python dependency templates.
Evaluation core: run, judge, report
.../ppt-quality-eval/eval.ts
Implements task specs, run execution, native PPTX/HTML judging, scoring/banding, and report aggregation.
Harness unit tests
.../ppt-quality-eval/eval.test.ts
Tests command policy enforcement, shape bounds checking, ZIP media checks, scoring, and evidence gates.
Post-build asset gate
.../ppt-quality-eval/scripts/check_pptx_assets.py
CLI validating built PPTX contains required slides/notes/charts/media/artifact-summary.

Vendored svg-pptx-native Conversion Engine

Layer / File(s) Summary
Route docs and vendoring notes
route-skills/svg-pptx-native/SKILL.md, LICENSE, VENDORED.md
Documents route rules, upstream provenance, and CLI contract for the vendored converter.
Support scripts
scripts/console_encoding.py, scripts/resource_paths.py, scripts/check_text_budget.py
Adds UTF-8 stdio, icon/image path resolution, and text-overflow budget checking.
svg_finalize tspan flattening
scripts/svg_finalize/*
Converts positional tspans into independent text nodes with paragraph-merge heuristics.
Entrypoints & animation config
scripts/svg_to_pptx.py, svg_to_pptx/__init__.py, animation_config.py, tspan_flattener.py, use_expander.py
Wires CLI entrypoint, package exports, and animation target scanning/scaffolding.
Conversion context & utils
drawingml/context.py, drawingml/utils.py
Defines conversion state and shared length/transform/style/font helpers.
Group/element dispatch
drawingml/converter.py
Converts SVG groups and dispatches per-element conversion with animation targeting.
Shape element converters
drawingml/elements.py
Converts rect/circle/line/path/polygon/text/image/ellipse/nested-svg to DrawingML.
Path geometry
drawingml/paths.py
Parses and normalizes SVG paths into DrawingML cubic Bézier commands.
Fill/stroke/effect styling
drawingml/styles.py
Builds solid/gradient/pattern fills, stroke/markers, and shadow/glow effects.
Native chart/table objects
native_objects/*
Converts SVG markers into native PPTX chart/table parts with workbook embedding.
PPTX packaging
pptx_package/*
Assembles native/legacy PPTX with notes, narration, media caching, and CLI.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as eval.ts CLI
  participant Runner as Generator Process
  participant FS as run directory
  participant Judge as judgeRun

  CLI->>Runner: spawn generator with route/task prompt
  Runner-->>FS: write events.jsonl, artifact, artifact-summary.json
  CLI->>Judge: judgeRun(runDir)
  Judge->>FS: readZipEntries(artifact) or read html
  Judge->>Judge: scoreFromFindings, qualityBand
  Judge->>FS: write judge.json
Loading
flowchart TD
  Cli --> Discovery
  Discovery --> Converter
  Converter --> Elements
  Converter --> NativeObjects
  Elements --> Builder
  NativeObjects --> Builder
  Builder --> Notes
  Builder --> Narration
  Builder --> PptxOutput
Loading

Possibly related issues

Suggested labels: ci, task

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers summary and results, but it misses most required template sections like Why, Review Focus, Risk Notes, How To Verify, and the checklist. Add all required template sections, complete the checklist, and include Human Review Status, Related Issue, Review Focus, Risk Notes, and verification results.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is specific and matches the main change: PPT quality eval baseline with the svg-pptx route and gates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/i1273-office-eval-baseline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Astro-Han Astro-Han added the task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work label Jul 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (6)
packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/converter.py (1)

505-505: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Use a hardened XML parser for SVG input. xml.etree.ElementTree isn’t hardened for untrusted SVG; switch this parse step to defusedxml.ElementTree.parse (or equivalent DTD/entity hardening) before accepting route-generated files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/converter.py`
at line 505, The SVG parse step in the converter is currently using the default
xml.etree.ElementTree parser, which is not hardened for untrusted input. Update
the parsing in the SVG-to-PPTX flow, specifically around the tree parsing logic
in the converter module, to use defusedxml.ElementTree.parse or an equivalent
hardened XML parser so route-generated SVG files are handled safely. Keep the
rest of the conversion behavior the same and ensure the parsing change is
applied at the tree creation point used by the converter.
packages/opencode/script/ppt-quality-eval/scripts/check_pptx_assets.py (1)

25-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use with statement for zipfile.ZipFile to avoid resource leak.

zf is never closed. For a short-lived CLI script this is low-impact, but using a context manager is the idiomatic Python pattern and prevents file-handle leaks.

♻️ Proposed refactor
     try:
-        zf = zipfile.ZipFile(args.pptx)
+        with zipfile.ZipFile(args.pptx) as zf:
+            names = zf.namelist()
     except (OSError, zipfile.BadZipFile) as error:
         print(f"FAIL: cannot open {args.pptx}: {error}")
         return 1
 
-    names = zf.namelist()
     slides = sum(1 for n in names if re.fullmatch(r"ppt/slides/slide\d+\.xml", n))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/script/ppt-quality-eval/scripts/check_pptx_assets.py`
around lines 25 - 35, The `check_pptx_assets.py` script opens the PPTX with
`zipfile.ZipFile` but never closes it, so update the `main` flow to use a `with`
statement around the `ZipFile` handling instead of keeping `zf` open. Keep the
existing `try/except` for `OSError` and `zipfile.BadZipFile`, and move the
`namelist()` plus slide/notes/charts/media counting logic inside the `with`
block so the archive is always released cleanly.
packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/check_text_budget.py (1)

19-36: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract estimate_text_width into a shared helper packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/check_text_budget.py and packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/utils.py both define the same estimator, so they can drift and make the pre-check disagree with the converter. Move it to one shared module or import the existing helper from a single source.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/check_text_budget.py`
around lines 19 - 36, The text-width estimator is duplicated between
check_text_budget.py and svg_to_pptx/drawingml/utils.py, so they can drift and
cause mismatched budget checks. Refactor estimate_text_width into a single
shared helper and have both the pre-check script and the DrawingML utility use
that one implementation. Keep the existing estimate_text_width behavior and
update any callers/imports so the shared function is the only source of truth.
packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_data.py (1)

506-506: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Unused loop variable idx.

idx isn't referenced in this loop body; rename to _idx to silence the linter.

-        for idx, item in enumerate(raw_series, start=1):
+        for _idx, item in enumerate(raw_series, start=1):
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_data.py`
at line 506, The loop in chart_data.py uses enumerate(raw_series, start=1) but
the index variable is never referenced in the body, so rename idx to _idx in the
relevant loop near the chart data processing logic to satisfy the linter and
make the unused variable explicit.

Source: Linters/SAST tools

packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_style.py (1)

361-361: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant int() around round().

round(x) with no ndigits already returns an int in Python 3.

-    return f'<a:alpha val="{int(round(alpha * 100000))}"/>'
+    return f'<a:alpha val="{round(alpha * 100000)}"/>'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_style.py`
at line 361, The alpha formatting in chart_style should be simplified because
round(alpha * 100000) already returns an integer in Python 3. Update the logic
in the alpha-returning code path to remove the redundant int() wrapper around
round(), keeping the same output format while relying on the built-in integer
result from round().

Source: Linters/SAST tools

packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/builder.py (1)

72-94: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

_append_relationship does not XML-escape rel_type or target.

If either value ever contains &, <, >, or ", the produced XML would be malformed. Current callers pass URL constants and simple paths, so this is not exploitable today, but it's a latent fragility.

🛡️ Defense: escape attribute values
     rel_xml = (
         f'  <Relationship Id="{next_rid}" '
-        f'Type="{rel_type}" Target="{target}"/>'
+        f'Type="{escape(rel_type)}" Target="{escape(target)}"/>'
     )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/builder.py`
around lines 72 - 94, The `_append_relationship` helper builds XML by
interpolating `rel_type` and `target` directly into the `<Relationship>`
element, so the attribute values should be XML-escaped before writing. Update
`_append_relationship` in `builder.py` to escape both values when constructing
`rel_xml`, using a safe XML attribute escaping approach, while keeping the `rId`
generation and file write logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/opencode/script/office-route-eval/README.md`:
- Around line 50-55: The replacement bar in the README is out of sync with the
actual gate in replacementReady; it currently mentions route-policy failures and
repair-step comparisons that the evaluator does not enforce. Either update
eval.ts/replacementReady to check those additional conditions, or trim the
README wording so it matches the existing “three task families in at least two
of three rounds” rule exactly. Use replacementReady and the OfficeCLI/Python
route comparison logic as the main anchors when making the change.

In `@packages/opencode/script/ppt-quality-eval/eval.ts`:
- Around line 145-152: The default model references in usage() and the fallback
logic still point to openai/gpt-5.4-mini, which conflicts with the weak-model
policy described in the README. Update the example commands in usage() and the
default model values in the relevant option parsing/defaulting code (the two
fallback sites used by calibrate/full) to use an Anthropic Sonnet or Haiku model
instead of GPT-5.4 Mini, keeping the change aligned across the eval CLI paths.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/pptxgenjs-native/SKILL.md`:
- Line 26: The `artifact-summary.json` instruction is under-specified in
`SKILL.md` and omits required fields from the full contract. Update the guidance
for the artifact summary output to explicitly include `artifact`, `route`,
`task`, and `commandsUsed` alongside the existing renderer, slide titles, layout
names, visual rules applied, and limitations so the downstream eval prompt
matches the expected shape.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/python-pptx-native/SKILL.md`:
- Line 25: The artifact summary contract in the python-pptx-native SKILL.md is
incomplete because it only mentions renderer, slide titles, layout names, visual
rules, and limitations. Update the instruction to mirror the full
artifact-summary.json shape used by downstream consumers, including artifact,
route, task, and commandsUsed, and make sure the guidance references the
artifact-summary.json output contract consistently so the route spec matches the
eval prompt.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/resource_paths.py`:
- Around line 55-88: Path resolution in external SVG image handling is
vulnerable to traversal because external_image_reference_candidates(),
resolve_external_image_reference(), and
unresolved_external_image_reference_path() trust the decoded href and can
resolve files outside the intended project tree. Sanitize the href-derived path
before joining, and after resolving any candidate verify it is still contained
within the allowed root (svg_dir/project_root and their approved subfolders)
before returning it. Make resolve_external_image_reference() reject
out-of-bounds matches and keep unresolved_external_image_reference_path()
limited to safe diagnostic paths only.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_finalize/flatten_tspan.py`:
- Around line 682-701: The SVG parsing in process_svg_file still uses
xml.etree.ElementTree.parse, which is unsafe for untrusted input. Update this
function to parse with defusedxml.ElementTree.parse instead, keeping the
existing error handling and flatten_text_with_tspans flow unchanged. Also make
sure the route/package dependency list for svg_finalize includes defusedxml so
the import resolves where process_svg_file is used.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/converter.py`:
- Around line 224-231: Preserve group rotation before flattening single-child
groups in the converter logic. The early return in the single-child non-semantic
group path drops rotation applied via rotate(...) / rotate(cx, cy) on the
enclosing group, so update this branch to avoid flattening whenever a pending
group rotation still needs to be emitted. Use the existing flattening check
around child_results and should_animate_group in converter.py to ensure
one-child groups like rotated text groups keep their group-level transform.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/builder.py`:
- Around line 482-513: The dangling-target check in
`_verify_internal_rels_targets` is currently a no-op because `_REL_TARGET_RE`
cannot match OOXML `<Relationship>` elements; update the regex so it can span
attributes containing `/` and still reach the closing tag, such as by excluding
`>` instead of `/`. Keep the rest of the logic in
`_verify_internal_rels_targets` unchanged so `finditer` can actually discover
relationships and the corrupt-PPTX guard can fire when missing internal targets
are present.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/discovery.py`:
- Around line 78-101: The find_notes_files logic in discovery.py is swallowing
all exceptions with a bare except, which hides real file I/O and parsing
failures. Update the exception handling in the notes_dir.glob loop to capture
the error as e and log it with enough context instead of silently passing, while
keeping the existing matching behavior for svg_index_mapping and
svg_stems_mapping unchanged.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/slide_xml.py`:
- Around line 108-136: The slide relationship XML built by create_slide_rels_xml
interpolates png_filename and svg_filename directly into Target attributes,
which can break XML when special characters are present. Update
create_slide_rels_xml to XML-escape both filenames before formatting the
Relationships string, following the same _xml_escape pattern already used in
chartex.py, and keep the escaping applied in both use_compat_mode branches.

---

Nitpick comments:
In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/check_text_budget.py`:
- Around line 19-36: The text-width estimator is duplicated between
check_text_budget.py and svg_to_pptx/drawingml/utils.py, so they can drift and
cause mismatched budget checks. Refactor estimate_text_width into a single
shared helper and have both the pre-check script and the DrawingML utility use
that one implementation. Keep the existing estimate_text_width behavior and
update any callers/imports so the shared function is the only source of truth.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/converter.py`:
- Line 505: The SVG parse step in the converter is currently using the default
xml.etree.ElementTree parser, which is not hardened for untrusted input. Update
the parsing in the SVG-to-PPTX flow, specifically around the tree parsing logic
in the converter module, to use defusedxml.ElementTree.parse or an equivalent
hardened XML parser so route-generated SVG files are handled safely. Keep the
rest of the conversion behavior the same and ensure the parsing change is
applied at the tree creation point used by the converter.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_data.py`:
- Line 506: The loop in chart_data.py uses enumerate(raw_series, start=1) but
the index variable is never referenced in the body, so rename idx to _idx in the
relevant loop near the chart data processing logic to satisfy the linter and
make the unused variable explicit.

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_style.py`:
- Line 361: The alpha formatting in chart_style should be simplified because
round(alpha * 100000) already returns an integer in Python 3. Update the logic
in the alpha-returning code path to remove the redundant int() wrapper around
round(), keeping the same output format while relying on the built-in integer
result from round().

In
`@packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/builder.py`:
- Around line 72-94: The `_append_relationship` helper builds XML by
interpolating `rel_type` and `target` directly into the `<Relationship>`
element, so the attribute values should be XML-escaped before writing. Update
`_append_relationship` in `builder.py` to escape both values when constructing
`rel_xml`, using a safe XML attribute escaping approach, while keeping the `rId`
generation and file write logic unchanged.

In `@packages/opencode/script/ppt-quality-eval/scripts/check_pptx_assets.py`:
- Around line 25-35: The `check_pptx_assets.py` script opens the PPTX with
`zipfile.ZipFile` but never closes it, so update the `main` flow to use a `with`
statement around the `ZipFile` handling instead of keeping `zf` open. Keep the
existing `try/except` for `OSError` and `zipfile.BadZipFile`, and move the
`namelist()` plus slide/notes/charts/media counting logic inside the `with`
block so the archive is always released cleanly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2b861f16-c99f-49ba-a692-4ae93a3e10c7

📥 Commits

Reviewing files that changed from the base of the PR and between 4bc3294 and 1015a88.

⛔ Files ignored due to path filters (2)
  • packages/opencode/script/office-route-eval/fixtures/sales-2026.csv is excluded by !**/*.csv
  • packages/opencode/script/ppt-quality-eval/fixtures/revenue-mix.csv is excluded by !**/*.csv
📒 Files selected for processing (64)
  • .gitignore
  • packages/opencode/package.json
  • packages/opencode/script/office-route-eval/README.md
  • packages/opencode/script/office-route-eval/eval.test.ts
  • packages/opencode/script/office-route-eval/eval.ts
  • packages/opencode/script/office-route-eval/fixtures/board-notes.md
  • packages/opencode/script/office-route-eval/fixtures/growth-brief.md
  • packages/opencode/script/office-route-eval/report.md
  • packages/opencode/script/office-route-eval/route-skills/officecli-eval-policy/SKILL.md
  • packages/opencode/script/office-route-eval/route-skills/python-office-eval/SKILL.md
  • packages/opencode/script/office-route-eval/route-templates/python/pyproject.toml
  • packages/opencode/script/office-route-eval/runs/.gitignore
  • packages/opencode/script/ppt-quality-eval/README.md
  • packages/opencode/script/ppt-quality-eval/eval.test.ts
  • packages/opencode/script/ppt-quality-eval/eval.ts
  • packages/opencode/script/ppt-quality-eval/fixtures/investor-update.md
  • packages/opencode/script/ppt-quality-eval/fixtures/market-report.md
  • packages/opencode/script/ppt-quality-eval/fixtures/template-following-brief.md
  • packages/opencode/script/ppt-quality-eval/report.md
  • packages/opencode/script/ppt-quality-eval/route-skills/html-showcase/SKILL.md
  • packages/opencode/script/ppt-quality-eval/route-skills/officecli-current/SKILL.md
  • packages/opencode/script/ppt-quality-eval/route-skills/pptxgenjs-native/SKILL.md
  • packages/opencode/script/ppt-quality-eval/route-skills/python-pptx-native/SKILL.md
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/LICENSE
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/SKILL.md
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/VENDORED.md
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/check_text_budget.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/console_encoding.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/resource_paths.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_finalize/__init__.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_finalize/flatten_tspan.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/__init__.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/animation_config.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/__init__.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/context.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/converter.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/elements.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/paths.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/styles.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/utils.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/__init__.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_data.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_style.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_xml.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chartex.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/marker_common.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/table.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/workbook.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/__init__.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/builder.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/cli.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/dimensions.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/discovery.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/media.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/narration.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/notes.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/slide_xml.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/tspan_flattener.py
  • packages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/use_expander.py
  • packages/opencode/script/ppt-quality-eval/route-templates/python/pyproject.toml
  • packages/opencode/script/ppt-quality-eval/route-templates/svg-pptx/pyproject.toml
  • packages/opencode/script/ppt-quality-eval/runs/.gitignore
  • packages/opencode/script/ppt-quality-eval/scripts/check_pptx_assets.py

Comment thread packages/opencode/script/office-route-eval/README.md
Comment thread packages/opencode/script/ppt-quality-eval/eval.ts
Astro-Han added 3 commits July 8, 2026 20:27
- office-route-eval: keep --file pairs ahead of scalar flags (same
  array-flag hazard fixed earlier in ppt-quality-eval)
- office-route-eval: derive the not-ready verdict from run data instead
  of a hardcoded stale narrative
- check_pptx_assets: stop claiming equivalence with the full judge
- check_text_budget: tolerate unit suffixes in x/font-size, add future
  annotations import for pre-3.10 python3
@Astro-Han
Astro-Han merged commit f81c555 into dev Jul 8, 2026
42 checks passed
@Astro-Han
Astro-Han deleted the codex/i1273-office-eval-baseline branch July 8, 2026 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants