Generate real docx artifacts and guard against pseudo-binary writes #27

Closed
weichen wants to merge 1 commits from feature/docx-generation into main
Owner

Track 1 of the fake-docx remediation (sibling: feature/preview-sniff-fallback already shipped the rendering-side fallback, PRs UI#21 / Frontend#22 / Dev#96).

Why

write_artifact/fs_write_file accept string content only, so models physically cannot emit ZIP containers; every ".docx" artifact written to date was plain text masquerading as Word — the review-session meeting-notes docx preview exploded in JSZip (Can't find end of central directory). The system advertised docx as a first-class delivery format with no serialization path behind it.

Changes

  • new internal/tools/docx.go: minimal OOXML serializer (PK-magic zip, word/document.xml, pStyle HeadingN matching the ingest parser convention, XML escaping, **bold** runs, list bullet paragraphs).
  • write_artifact gains optional format param (md default / docx); a name ending in .docx auto-upgrades to real docx; MIME follows the extMIME convention.
  • write-side guard: string writes to xlsx/pptx/doc/xls are rejected with actionable guidance (both in write_artifact and fs_write_file).
  • runmgr.WriteArtifact indexing now extracts text via ingest for binary content and skips the index when nothing extractable — no more binary garbage in the knowledge index.
  • mock #doc demo emits a real docx when the user names docx/word; HITL choice copy now matches real capability.

Verification

  • go vet (tools/runmgr/runtime) clean; go test ./... 18 packages pass, incl. new docx_test.go: ZIP magic, ingest roundtrip (heading levels, escape roundtrip, no ** leakage, bullet paragraphs), format dispatch, three rejection paths, fs guard, schema exposure.
  • combined acceptance make test at 75b34699d8 (synced to f65d89e): core 1 + backend 18 packages, frontend vitest 33/33, ui tsc + vitest 49/49, agent-command 2 packages — exit 0.
  • task-sync checkpoint: sync_base=f65d89e59b tested_head=75b34699d8 (2026-09-30T18:08:49Z), evidence row in task card.

Impact

write_artifact contract gains an optional format param (backwards compatible); binary-Office extensions fail fast instead of silently producing unopenable files. Stock fake-docx artifacts remain readable via the rendering-side fallback PRs.

Non-goals

md-table → docx table (ingest doesn't parse md tables yet; ships together with that), xlsx/pptx generation.

Refs: .task/feature-docx-generation.md; merge order: Agent-System-Backend PR first, then this parent PR (pins its head).

Track 1 of the fake-docx remediation (sibling: feature/preview-sniff-fallback already shipped the rendering-side fallback, PRs UI#21 / Frontend#22 / Dev#96). ## Why write_artifact/fs_write_file accept string content only, so models physically cannot emit ZIP containers; every ".docx" artifact written to date was plain text masquerading as Word — the review-session meeting-notes docx preview exploded in JSZip (`Can't find end of central directory`). The system advertised docx as a first-class delivery format with no serialization path behind it. ## Changes - new `internal/tools/docx.go`: minimal OOXML serializer (PK-magic zip, word/document.xml, pStyle HeadingN matching the ingest parser convention, XML escaping, `**bold**` runs, list bullet paragraphs). - `write_artifact` gains optional `format` param (`md` default / `docx`); a name ending in `.docx` auto-upgrades to real docx; MIME follows the extMIME convention. - write-side guard: string writes to xlsx/pptx/doc/xls are rejected with actionable guidance (both in write_artifact and fs_write_file). - `runmgr.WriteArtifact` indexing now extracts text via ingest for binary content and skips the index when nothing extractable — no more binary garbage in the knowledge index. - mock `#doc` demo emits a real docx when the user names docx/word; HITL choice copy now matches real capability. ## Verification - go vet (tools/runmgr/runtime) clean; go test ./... 18 packages pass, incl. new docx_test.go: ZIP magic, ingest roundtrip (heading levels, escape roundtrip, no `**` leakage, bullet paragraphs), format dispatch, three rejection paths, fs guard, schema exposure. - combined acceptance `make test` at 75b34699d8 (synced to f65d89e): core 1 + backend 18 packages, frontend vitest 33/33, ui tsc + vitest 49/49, agent-command 2 packages — exit 0. - task-sync checkpoint: sync_base=f65d89e59b tested_head=75b34699d8 (2026-09-30T18:08:49Z), evidence row in task card. ## Impact write_artifact contract gains an optional format param (backwards compatible); binary-Office extensions fail fast instead of silently producing unopenable files. Stock fake-docx artifacts remain readable via the rendering-side fallback PRs. ## Non-goals md-table → docx table (ingest doesn't parse md tables yet; ships together with that), xlsx/pptx generation. Refs: .task/feature-docx-generation.md; merge order: Agent-System-Backend PR first, then this parent PR (pins its head).
weichen added 1 commit 2026-09-30 18:10:32 +00:00
Why: write_artifact/fs_write_file accept string content only, so models
physically cannot emit ZIP containers; every ".docx" artifact written to
date was plain text masquerading as Word (the meeting-notes docx preview
exploded in JSZip). The system advertised docx as a first-class delivery
format without a serialization path behind it.

Evidence: new internal/tools/docx.go serializes markdown to a minimal
OOXML package (PK-magic zip, word/document.xml, pStyle HeadingN) that
ingest.parseDocx round-trips; write_artifact gains format=docx (name
ending .docx auto-upgrades) and rejects xlsx/pptx/doc/xls string writes
with actionable guidance; fs_write_file gains the same guard;
runmgr.WriteArtifact now extracts index text via ingest instead of
stuffing binary bytes into the knowledge index; mock #doc demo emits a
real docx when the user names docx/word. go vet clean; go test ./...
18 packages pass, including new docx_test.go (magic, roundtrip, guards).

Impact: write_artifact contract gains an optional format param
(backwards compatible); binary-Office extensions now fail fast instead
of silently producing unopenable files. Frontend fallback for stock
fake-docx artifacts ships separately (feature/preview-sniff-fallback).

Refs: .task/feature-docx-generation.md
Author
Owner

Superseded by the agent-native deliverable path (Dev #109/#111, now on main): write_artifact format=docx and the in-process OOXML serializer are not being merged. The two pieces main still lacks — refusing pseudo-binary Office writes, and indexing extracted text from binary artifacts — move to feature/binary-doc-index and should land after the run_shell/run_python PR (Dev #113 / Backend #33).

Superseded by the agent-native deliverable path (Dev #109/#111, now on main): write_artifact format=docx and the in-process OOXML serializer are not being merged. The two pieces main still lacks — refusing pseudo-binary Office writes, and indexing extracted text from binary artifacts — move to feature/binary-doc-index and should land after the run_shell/run_python PR (Dev #113 / Backend #33).
weichen closed this pull request 2026-10-01 04:09:54 +00:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: weichen/Agent-System-Backend#27