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).
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
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).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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
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_artifactgains optionalformatparam (mddefault /docx); a name ending in.docxauto-upgrades to real docx; MIME follows the extMIME convention.runmgr.WriteArtifactindexing now extracts text via ingest for binary content and skips the index when nothing extractable — no more binary garbage in the knowledge index.#docdemo emits a real docx when the user names docx/word; HITL choice copy now matches real capability.Verification
**leakage, bullet paragraphs), format dispatch, three rejection paths, fs guard, schema exposure.make testat 75b34699d8 (synced to f65d89e): core 1 + backend 18 packages, frontend vitest 33/33, ui tsc + vitest 49/49, agent-command 2 packages — exit 0.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).
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).
Pull request closed