feat: add OpenCode rich document reader - #1
Merged
Conversation
…and media handling
…d lint checks pass
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Continue delivery of the public OpenCode rich-document reader at https://github.com/ddbaron/opencode-rich-document-reader as a continuation of the existing user-facing DOCX, ODT, and PPTX reader work. Preserve the implementation and committed fixes already present on fm/opencode-reader-restart-m3 at dcd8a29; do not reimplement the reader, discard the six approved pipeline fixes, retain the cancelled 3dbdfa5 fix, add ancestor-symlink security machinery, or create duplicate work. Validate and deliver this non-default branch through the configured no-mistakes pipeline with yolo off, including tests, documentation, lint, publication, PR, and CI; handle all findings through no-mistakes and never hand-edit the project during an active run. Keep origin at git@github.com:ddbaron/opencode-rich-document-reader.git, do not push or merge the default branch, and finish at a green CI-ready PR. Captain clarification: approve RDR-001 as-is if it appears; RDR-006 and RDR-007 fixes are already included. Escalate any genuinely new ask-user decision rather than choosing a new product or security scope.
What Changed
read_rich_documentOpenCode tool for converting DOCX, ODT, and PPTX files into structure-preserving Markdown with document context, warnings, and metadata.Risk Assessment
✅ Low: The reviewed changes are bounded to additive WebP support and a semantics-preserving linear media-selector lookup, with no material source risks found.
Testing
Targeted executable tests and direct public-tool verification exercised structure-preserving Markdown, media indexing and selection, format/error handling, and concurrent ancestor-symlink rejection; all completed successfully with no transient worktree artifacts. The reviewer-visible evidence is a CLI transcript because this plugin has no rendered UI surface, so no screenshot applies.
Evidence: Public read_rich_document end-to-end transcript
Evidence: Concurrent symlink safety result
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 2 issues found → auto-fixed ✅
src/media.ts:16- The new selector allowlist omitsimage/webp, even though officeparser 7.5.1 emits valid WebP attachments with that MIME; selecting the listed media label therefore throwsMEDIA_SELECTOR_INVALIDfor an otherwise supported image. Confirm that WebP is intentionally unsupported or include/document the supported MIME set.src/media.ts:203- The publicmediaarray is unbounded, while each selector performs a linearrecords.findfollowed by a linearselected.some, allowing a large caller-supplied selector list to force quadratic work against up to 4096 attachments. Resolve selectors through a map and track selected labels with aSet, or bound the array at the schema boundary.🔧 Fix: Support WebP and linearize media selector resolution
✅ Re-checked - no issues remain.
🔧 **Test** - 1 issue found → auto-fixed ✅
test/read-rich-document.test.ts:269- Running two copies of the symlink-escape test concurrently caused a fixture collision because both use the fixed sibling path outside.docx; one process reported Document not found instead of the expected symlink escape. The same test passed serially, so this is test-fixture flakiness rather than a product failure. Use a unique outside fixture path if concurrent test execution is expected.node --experimental-strip-types --test --test-name-pattern='extracts DOCX structure|extracts ODT structure|retains PPTX slide|attaches only explicitly|attaches selected WebP|leaves the source' test/read-rich-document.test.tsnode --experimental-strip-types --test --test-name-pattern='rejects lexical path escapes and symlinks that resolve outside the project' test/read-rich-document.test.tsnode --experimental-strip-types --test --test-name-pattern='associates media after a DOCX section boundary|labels media from headers, footers|rejects unsupported, missing|rejects an unknown media selector|rejects image-labeled|rejects parser-truncated|rejects oversized tables' test/read-rich-document.test.tsRegisteredread_rich_documentthrough the plugin, read generated DOCX/ODT/PPTX fixtures, selected an image attachment, and exercised escaping and in-project ancestor symlinks; transcript captured at the evidence artifact path.git status --short --untracked-files=all🔧 Fix: Made symlink fixture paths unique; concurrent focused tests pass
✅ Re-checked - no issues remain.
node --experimental-strip-types --test --test-name-pattern='extracts DOCX structure|extracts ODT structure|retains PPTX slide' test/read-rich-document.test.tsnode --experimental-strip-types --test --test-name-pattern='attaches only explicitly selected image media|attaches selected WebP image media' test/read-rich-document.test.tsTwo concurrent invocations ofnode --experimental-strip-types --test --test-name-pattern='rejects lexical path escapes and symlinks that resolve outside the project' test/read-rich-document.test.tsnode --experimental-strip-types --test --test-name-pattern='rejects unsupported, missing, and malformed documents with useful errors|rejects an unknown media selector instead of attaching every image' test/read-rich-document.test.tsDirect invocation of the registeredRichDocumentReaderPluginread_rich_document.executeagainst generated DOCX, ODT, and PPTX fixtures, including selectedmedia-1attachment output.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.