Skip to content
This repository was archived by the owner on Aug 15, 2026. It is now read-only.

Repository files navigation

AI/legal-use disclosure: This repository is experimental, AI-assisted workflow software. It is not legal advice, not a primary legal source, and not lawyer-reviewed as a complete statement of law. Outputs are first drafts for human review, intended to reduce creation effort while increasing focused review effort. See AI_DISCLOSURE.md.

Transactional Tax Forms — Open Automation Library

⚠ Licensing notice

This repository is licensed Apache-2.0, but installing it pulls in AGPL-3.0 code.

PyMuPDF (imported as fitz) is dual-licensed AGPL-3.0-or-commercial by Artifex. It is a required dependency of this snapshot (requirements.txt), and the engine layer also reaches it through maine-forms-engine.

If you convey a work combining this code with PyMuPDF, or expose it to users over a network (AGPL-3.0 §13), the AGPL-3.0 terms attach to the combination. Artifex sells a commercial license if that is not acceptable for your deployment.

This repository is archived and read-only — a snapshot frozen in July 2026, not maintained. This notice was added later to disclose a dependency term the Apache-2.0 LICENSE alone does not mention. It does not change the license of this repository's own source, which remains Apache-2.0.

Fill the tax forms that ride along with a business formation, a real-estate closing, or an estate — Maine Revenue Services forms and federal IRS forms, one self-contained folder per form, filled deterministically from structured case data.

This is a sibling of maine-corporation-forms, maine-court-forms, and maine-probate-forms: same form-by-form layout, same fetch-on-demand + drift-detection model, same deterministic fill engine. The blank PDFs are fetched on demand from the official source and never redistributed (see Getting the blanks).

⚠️ Not legal or tax advice — for professional use only. This is software that produces draft forms. It is meant to be used solely as one component of a broader workflow that is implemented, supervised, and reviewed by a licensed attorney or qualified tax professional — not as a do-it-yourself substitute for professional advice. Output is a draft that may be wrong; verify every form against the current official source and applicable law before filing. See DISCLAIMER.

Scope — organized by transaction

Domain Forms
Corporations IRS SS-4 (EIN), IRS 2553 (S-corp election), IRS 8832 (entity classification), MRS 1120ME (corporate income), MRS 941ME / 900ME (withholding), MRS W-4ME
Real estate ME RETTD (real estate transfer tax declaration)
Probate / estates IRS 706 (federal estate tax), IRS 1041 (estates & trusts income), IRS 56 (fiduciary notice), MRS 706ME (Maine estate tax), MRS 700-SOV (statement of value), MRS 1041ME (fiduciary income)

SS-4 and 706 are cross-listed (an estate also needs an EIN). See catalog/by_domain.json.

Status

14 forms — every form now fills. Seven Maine Revenue forms were mapped in maine-court-forms and lifted here; the rest were mapped in this repo.

  • Mapped & verified (5): MRS 706ME, 1120ME, 941ME, 900ME, W-4ME — widget-survival confirmed against the current maine.gov blanks. The 706ME residency and marital-status groups and the W-4ME filing-status group are declared "fill": "manual" radio groups (same yellow-light treatment as below).
  • Mapped, machine-verified (2): MRS 1041ME (the current maine.gov blank had drifted from the mapped revision; rebuilt deterministically against the current widget tree — 123/125 widgets, with a field_splits.json detaching its shared area-code field) and MRS 700-SOV (was an empty recipe pointer; direct-mapped from its descriptive widget names — 42/44 widgets). Both fill end-to-end with every sample value confirmed on reopen (every fillable mapping now records built_against_sha256 — see Staying current). Their radio groups (1041ME third-party designee Yes/No, 700-SOV Resident/Nonresident) are declared "fill": "manual" in mapping.json: the engine never writes radio groups, and the fill report carries a yellow-light radio_groups entry with the option suggested from the case — select it by hand. Not yet human-verified field-by-field.
  • Opus-adjudicated (7): IRS SS-4 (44 fields), 2553 (23), 8832 (53), 706 (146), 1041 (79), 56 (33), ME RETTD (74). Drafted from the rendered form by the Qwen-VL cluster (tools/vision_map.py), then reviewed field-by-field against each printed caption by Opus (tools/opus_adjudicate.py), which corrected 86 keys and removed 15 non-data widgets — most notably realigning IRS-1041's shifted income/deduction lines (68 fixes) and IRS-SS-4's over-split city/state/zip block (9). Each form records its corrections under mapping.json.adjudication. The big returns map identity/party fields; some numbered line items remain facts.*. ME-RETTD + IRS-SS-4 fill end-to-end.

Two canonical models, for now. The five inherited Maine Revenue forms use the court library's parties.<role> model; the vision-mapped forms above use the tax-native roles (entity, responsible_party, decedent, executor, fiduciary, transferor/transferee, property). Unifying the two is a roadmap item; until then, read each form's mapping.json for its keys — both shapes are documented in docs/integrations/README.md.

Computed lines (printed arithmetic)

Six forms (MRS 1041ME, 1120ME, 706ME, W-4ME; IRS 1041, 706) carry a computations.json next to mapping.json declaring the arithmetic the form itself prints ("Total payments. (Add lines 7a, 7b and 7c.)" — every formula_text is quoted verbatim from the blank; no statutory rates or tax tables are encoded from memory). The shared engine evaluates it topologically: omit a computed key (with its inputs supplied) and it is computed and filled, reported under computed_fields; supply it and your value is written as-is — a contradiction only adds a COMPUTATION_MISMATCH entry under computation_warnings (CLI and MCP fill_form alike). Warnings only, never blocking, and nothing is embedded in the PDF — no AcroForm calculation JavaScript. Lines whose printed math is conditional (e.g. 706ME amount-due vs refund-due, 1120ME tax-due vs overpayment) or split across dollars/cents widgets (941ME) are deliberately not declared.

Getting the blanks

Blank forms are not redistributed here. Maine forms are public records of Maine Revenue Services; federal forms are public-domain U.S. Government works. Fetch on demand; each download is verified byte-for-byte against catalog/pdf_manifest.json:

python3 tools/fetch_pdfs.py                    # all forms
python3 tools/fetch_pdfs.py --forms MRS-706ME  # a subset

Staying current — detecting a revised form

Every mapping is built against one specific revision of the blank, pinned by SHA-256 in the manifest. Agencies re-issue forms yearly; when the bytes change, field layouts can move and a fill built on the old mapping lands values in the wrong place. Two guards:

python3 tools/check_upstream.py            # re-probe official URLs; flag CHANGED / GONE

check_upstream re-downloads each blank, hashes it, and reports drift; it is read-only and exits non-zero on any change, so it runs as a weekly early-warning (.github/workflows/drift.yml). At fill time the engine checks the on-disk blank against the manifest — TTF_VERIFY_BLANK=warn (default), strict, or off (MCF_VERIFY_BLANK is honored as a fallback) — so a re-issued blank can't be filled unnoticed.

Every fillable mapping.json also records built_against_sha256 — the manifest revision its widget references were last verified against (tools/verify_mapping_fields.py, which re-checks every mapped field against the pinned blank's AcroForm tree before stamping). The engine refuses to fill when the manifest moves off that revision; a mapping that fails verification stays unstamped and goes remap-pending instead.

Draft (vision-mapped) tier. A vision-mapped mapping is an unreviewed vision-LLM draft ("review before production") that has not yet been through opus-adjudicated/verified. Because these maps back real IRS/MRS PDFs, the engine refuses vision-mapped by default — it is not in the reviewed FILLABLE_STATUSES. Filling a draft is an explicit opt-in, which warns loudly and must be human-reviewed before any real filing:

python3 -m engine.fill_via_mapping --form IRS-SS-4 --allow-draft ...
# or:  TTF_ALLOW_DRAFT=1 python3 -m engine.fill_via_mapping --form IRS-SS-4 ...
# or, in code:  fill_via_mapping(form_id, facts, out_dir, allow_draft=True)

Quickstart — fill a form

pip install -r requirements.txt                # PyMuPDF
python3 tools/fetch_pdfs.py --forms MRS-706ME  # download the blank, verified
python3 -m engine.fill_via_mapping --form MRS-706ME --case forms/MRS-706ME/examples/sample_case.json --out out/706me.pdf

The engine resolves each form's mapping.json against a canonical fact object and writes the filled AcroForm. Unmapped forms (status unmapped) carry a widgets.json inventory but no mapping.json yet.

Layout

forms/<FORM_ID>/
  form.yaml          metadata: title, agency, domain, page/widget counts, status
  widgets.json       raw AcroForm widget inventory (name, type, page, rect) — mapping input
  mapping.json       canonical fact-key -> widget (mapped forms)
  schema.json        JSON Schema for the fill data (mapped forms)
  fields.csv         reviewable field inventory (mapped forms)
  SKILL.md / README  per-form guide (mapped forms)
  examples/          sample_case.json — fictional fact pattern covering the mapping
catalog/
  source_urls.json   form_id -> official URL + domain grouping
  pdf_manifest.json  per-form sha256 + bytes + pages for fetching/verifying blanks
  forms_index.json   master list (generated)
  by_domain.json     forms grouped by transaction domain (generated)
engine/              deterministic AcroForm fill engine (PyMuPDF) — thin shims over
  fill_via_mapping.py  form_filler.py  field_split.py  text_fit.py  verify.py
                       the shared `maine-forms-engine` package (required; see
                       requirements.txt), configured with this repo's policy:
                       status allowlist, built_against_sha256 staleness gate,
                       diagnostics result dict
tools/
  fetch_pdfs.py       download verified blanks
  build_manifest.py   fetch + hash + dump widget inventory
  check_upstream.py   re-probe official URLs; flag revised forms
  verify_mapping_fields.py  re-verify mapped fields vs the pinned blank; stamp built_against_sha256
  vision_map.py       Qwen-VL draft mapping from the rendered form
  opus_adjudicate.py  Opus caption-grounded review of the drafts
  infer_labels.py     heuristic widget-caption inventory
  gen_catalog.py      regenerate the catalogs
  gen_skill.py        regenerate per-form SKILL.md + sample case (mapped forms)
  agent_server.py     MCP server (find_forms / get_form / fill_form)
docs/integrations/    the canonical fact object (case shape) reference
.mcp.json             MCP registration; AGENTS.md / CLAUDE.md — agent guide

License

Apache-2.0. See LICENSE and NOTICE.

About

Experimental tax form automation for first drafts and review workflows; not legal/tax advice or a primary source.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages