Skip to content

[decision] How far does Word form handling go — .docx is tractable, .doc is not, and build_answer_sheet may already be the right answer for both #764

Description

@serge-ivo

The decision

PAGS can fill a PDF form. It cannot fill a Word form, and the two Word formats are not one problem. This issue decides how far in-platform Word form handling goes, and records the answer — it is deliberately a design ticket, not an implementation ticket, because the honest options include "do not build this".

The motivating case (#756) is a club entry form that arrived as .doc and .docx. The user's goal is not "fill a Word document"; it is return the completed form to Kelly before the deadline. Keep that distinction — it is what makes option A viable.

Priority — P3: later: this is a design decision pending a call, and options A and B below deliver most of the user-visible outcome without it.

What exists today — VERIFIED

Three PDF form builtins, workers/api/src/lib/pdf-storage-tools.ts:66-92:

  • inspect_pdf_form (:68-73) — lists fillable fields, types and permitted values
  • fill_pdf_form (:74-84) — fills and saves a new file, returns its id
  • build_answer_sheet (:85-92) — "Generate a clean PDF of questions and their answers, saved to your files. This is the answer when a form is a flat scan with no fillable fields: send it alongside the original rather than attaching an empty form."

build_answer_sheet is the part that matters here, and #756 did not account for it. The platform already has a shipped, honest answer to "this form cannot be filled in place" — it just does not know that a .doc is such a form.

There is no Word equivalent of any of the three, and no ZIP reader in the tree (grep -rn "deflate-raw\|central directory\|centralDirectory" workers/api/src packages/*/src → nothing).

The two formats, and why the split is the whole decision

.docx .doc
Container ZIP of XML OLE2 / CFB compound binary
Read in a Worker tractable — see #763 not realistically
Write in a Worker tractable in principle: edit word/document.xml, re-zip no
Form fields content controls (<w:sdt>), legacy form fields, or — most club forms — plain underscores and table cells, no fields at all same, unreadable

The user's actual attachment is the .doc. So even a complete .docx implementation would not have completed the reported task. Any plan that treats "Word forms" as one item is planning for the case that did not happen.

The third row is the one that usually decides it in practice: a form built by a tennis club in Word almost never has structured form fields. It has a table and blank lines. There is nothing to "fill" programmatically that is not layout reconstruction.

The options, cheapest first

A. Route Word forms to build_answer_sheet — no new format code at all.
Read the form's questions (requires #763 for .docx; for .doc requires C or nothing), call build_answer_sheet, reply with the generated PDF alongside the original attachment via gmail_reply's attachment_file_ids (connectors/gmail.ts:561, shipped in #713). Human-acceptable for a club: a filled answer sheet is a normal thing to receive. Cost: widening build_answer_sheet's description beyond "flat scan PDF", plus prompt guidance. This is the cheapest complete path to the user's actual outcome.

B. .docx read-only inspection. inspect_docx_form: list the visible questions/labels so the agent can ask the user for values and then take path A. Depends on #763.

C. .doc text via an external conversion step. The only way to read .doc at all. It puts the owner's documents through a third party, so it is a product decision, not an implementation choice — needs an explicit call, a named provider, and a consent story. My recommendation: do not build this. Instead, when a .doc arrives, say so plainly and offer path A driven by the user's own description of the fields, or ask them to re-send as PDF/.docx. An agent that says "I can't read a .doc; paste the questions or send it as a PDF and I'll fill it" is more useful than one that silently gets it wrong.

D. True .docx fill. Edit word/document.xml, re-zip, save as a new file. Only defensible if a survey of real forms shows structured fields are common. It is the largest option and the one most likely to produce a subtly corrupted document — the failure mode a club secretary discovers, not the platform.

My recommendation: A + B, decide C explicitly as "no", and gate D behind evidence.

The open question the owner should answer

Is "the agent returns a clean answer sheet PDF alongside the original form" an acceptable outcome, or must the returned file be the original document with values in it?

If the first: A + B, and this issue closes small. If the second: D becomes necessary for .docx and .doc is out of scope permanently. This cannot be decided from the code and should not be guessed. #710 left an adjacent question open — "Whether real-world club forms like the motivating one are AcroForms or flat scans… Not reproduced — needs the actual attachment" — and reality answered it worse than either branch: they were not PDFs at all.

Alternatives considered and rejected

  • Convert .doc/.docx → PDF and reuse fill_pdf_form. Rejected: conversion produces a flat PDF with no AcroForm fields, so fill_pdf_form refuses it by design and you land on build_answer_sheet anyway — which is option A, without the conversion.
  • Have the model emit a whole new .docx from scratch. Rejected: it discards the club's layout and produces a document that looks like a different form. build_answer_sheet is the same idea, honest about being a separate sheet.
  • Ask the runner (pags up) to open Word / LibreOffice locally. Rejected: it makes the capability depend on a local machine with an office suite, which the runner does not require today and which cloud-only agents (runtime: null) do not have at all.

Acceptance criteria

This ticket is done when the decision is recorded, not when code ships:

  • The open question above is answered on this issue by the owner.
  • The chosen option is split into its own implementation issue(s) with the usual file:line grounding.
  • Whatever is decided, the agent's behaviour when handed a .doc is pinned by a test on the refusal string: it names the format, says it cannot be read, and offers the next step. Silence is the failure this issue exists to prevent.

Regression risk

  • Option A widens build_answer_sheet's description, which is prompt surface for every agent that has the tool. A description that stops saying "flat scan" may see it used where fill_pdf_form should have been. Keep the "call inspect_pdf_form first" ordering explicit.
  • Option D can emit a corrupt .docx that opens with an error in Word. That is worse than not sending, and there is no in-Worker validator for it. If D is chosen, round-tripping through a real Word/LibreOffice open is a manual acceptance step and should be stated as one.

Parent: #756. Depends on #763 (reading a .docx at all) and #755 (getting the file into the store). Precedent: #712 built the PDF form tools.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3: laterDesign, strategy, or deferred pending a decision or demandbackendBackend / Worker / API workquestionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions