test: PPT quality eval baseline with svg-pptx route and machine gates (#1273) - #1490
Conversation
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.
|
Warning Review limit reached
Next review available in: 2 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR introduces two evaluation harnesses under Estimated code review effort: 5 (Critical) | ~150 minutes ChangesOffice Route Eval Harness
PPT Quality Eval Harness
Vendored svg-pptx-native Conversion Engine
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
flowchart TD
Cli --> Discovery
Discovery --> Converter
Converter --> Elements
Converter --> NativeObjects
Elements --> Builder
NativeObjects --> Builder
Builder --> Notes
Builder --> Narration
Builder --> PptxOutput
Possibly related issues
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 winUse a hardened XML parser for SVG input.
xml.etree.ElementTreeisn’t hardened for untrusted SVG; switch this parse step todefusedxml.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 valueUse
withstatement forzipfile.ZipFileto avoid resource leak.
zfis 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 winExtract
estimate_text_widthinto a shared helperpackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/check_text_budget.pyandpackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/utils.pyboth 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 valueUnused loop variable
idx.
idxisn't referenced in this loop body; rename to_idxto 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 valueRedundant
int()aroundround().
round(x)with nondigitsalready returns anintin 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_relationshipdoes not XML-escaperel_typeortarget.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
⛔ Files ignored due to path filters (2)
packages/opencode/script/office-route-eval/fixtures/sales-2026.csvis excluded by!**/*.csvpackages/opencode/script/ppt-quality-eval/fixtures/revenue-mix.csvis excluded by!**/*.csv
📒 Files selected for processing (64)
.gitignorepackages/opencode/package.jsonpackages/opencode/script/office-route-eval/README.mdpackages/opencode/script/office-route-eval/eval.test.tspackages/opencode/script/office-route-eval/eval.tspackages/opencode/script/office-route-eval/fixtures/board-notes.mdpackages/opencode/script/office-route-eval/fixtures/growth-brief.mdpackages/opencode/script/office-route-eval/report.mdpackages/opencode/script/office-route-eval/route-skills/officecli-eval-policy/SKILL.mdpackages/opencode/script/office-route-eval/route-skills/python-office-eval/SKILL.mdpackages/opencode/script/office-route-eval/route-templates/python/pyproject.tomlpackages/opencode/script/office-route-eval/runs/.gitignorepackages/opencode/script/ppt-quality-eval/README.mdpackages/opencode/script/ppt-quality-eval/eval.test.tspackages/opencode/script/ppt-quality-eval/eval.tspackages/opencode/script/ppt-quality-eval/fixtures/investor-update.mdpackages/opencode/script/ppt-quality-eval/fixtures/market-report.mdpackages/opencode/script/ppt-quality-eval/fixtures/template-following-brief.mdpackages/opencode/script/ppt-quality-eval/report.mdpackages/opencode/script/ppt-quality-eval/route-skills/html-showcase/SKILL.mdpackages/opencode/script/ppt-quality-eval/route-skills/officecli-current/SKILL.mdpackages/opencode/script/ppt-quality-eval/route-skills/pptxgenjs-native/SKILL.mdpackages/opencode/script/ppt-quality-eval/route-skills/python-pptx-native/SKILL.mdpackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/LICENSEpackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/SKILL.mdpackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/VENDORED.mdpackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/check_text_budget.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/console_encoding.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/resource_paths.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_finalize/__init__.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_finalize/flatten_tspan.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/__init__.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/animation_config.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/__init__.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/context.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/converter.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/elements.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/paths.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/styles.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/drawingml/utils.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/__init__.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_data.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_style.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chart_xml.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/chartex.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/marker_common.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/table.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/native_objects/workbook.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/__init__.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/builder.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/cli.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/dimensions.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/discovery.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/media.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/narration.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/notes.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/pptx_package/slide_xml.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/tspan_flattener.pypackages/opencode/script/ppt-quality-eval/route-skills/svg-pptx-native/scripts/svg_to_pptx/use_expander.pypackages/opencode/script/ppt-quality-eval/route-templates/python/pyproject.tomlpackages/opencode/script/ppt-quality-eval/route-templates/svg-pptx/pyproject.tomlpackages/opencode/script/ppt-quality-eval/runs/.gitignorepackages/opencode/script/ppt-quality-eval/scripts/check_pptx_assets.py
- 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
Summary
packages/opencode/script/ppt-quality-eval/(3 tasks × 5 routes, OOXML zip-inspection judge, no LibreOffice).svg_to_pptxconverter as thesvg-pptxroute with LICENSE/VENDORED attribution.--filearray flag swallowing the prompt, and the judge zip reader dropping binary entries (madeppt/mediachecks 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
Documentation
Bug Fixes