new-site/docs/plans/plotter-plan.md
justin 0b06043437 healthcare: verify wet-signature requirements across all services
Source-grounded check of which services need an ORIGINAL ink signature (plotter
target) vs e-sign/typed. Verified firsthand against the official forms:

- Confirmed wet-ink: the 5 CMS Medicare/NPI paper filings only (855I/B/O +
  10114), which are exactly the no-login Standard-path filings the plotter serves.
- CLIA CMS-116 does NOT require original ink — the form explicitly permits 'SIGN
  IN INK OR USE A SECURE ELECTRONIC SIGNATURE', so our digital stamp suffices;
  plotter optional for CLIA.
- DEA registration/renewal is online-only (Form 224 unavailable in PDF),
  e-certified, no wet ink.
- State CSR / state Medicaid are the only open items: paper in many states but
  original-ink-vs-e-sign is state-specific; verify per state.
- All FCC/telecom/DOT/BOC-3/CRTC/PUC filings are electronic (e-sign fine).

Added the verified matrix to state-healthcare-compliance-opportunities.md, saved
docs/CMS-116 Form.pdf, and the plotter plan.
2026-06-07 02:40:47 -05:00

177 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Plotter Plan — ink-signature station for no-login CMS filings
Goal: turn the (already-built) ink-signature pipeline into a reliable physical
station that draws an **original wet-ink signature** on each printed CMS form so
the Standard (no-login) filing path can be mailed and accepted. The CR-10 V2 is
the motion system; this plan covers the retrofit, calibration, the
software/hardware integration that remains, validation, and the operational
runbook.
Status legend: ✅ done · 🔲 to do · ⏳ blocked on hardware
---
## 0. What already exists (software, hardware-independent)
-`signature_vector` capture end-to-end (migration 090, signing page, API).
-`ink_signature_plotter.py` — fit-to-box, PDF-pt → bed-mm, G-code (Z pen or
M280 servo/BLTouch), SVG preview, `render_signature_on_pdf` digital twin,
gated serial sender.
-`ink_signature_cli.py` — load record → gcode + preview, `--test-box`,
`--plot`.
-`test_ink_signature.py` 30/30; signature anchor verified inside the
CMS-10114 Section 4A cell.
-`docs/ink-signature-plotter.md` — retrofit + interpretive-risk writeup.
The remaining work is hardware + a few integration/safety pieces.
---
## 1. Hardware retrofit (CR-10 V2)
1. 🔲 **Pen holder.** Print a spring-loaded CR-10/Ender X-carriage pen holder
(Printables/Thingiverse). Spring = even contact pressure. Print it before
converting (you still have the hotend).
- BOM: printed bracket, 1 compression spring (~812mm), 23× M3 screws, a
smooth **gel/rollerball** pen (wet ink, hand-written look).
2. 🔲 **Mount + cable management.** Attach beside the hotend; make sure the pen
tip is the lowest point and the bed can still home.
3. 🔲 **Pen-up/down method — pick one:**
- *Z mode (default, simplest):* pen fixed; G-code lifts/drops Z. Spring
forgives over-press. No firmware change.
- *Servo/BLTouch mode (optional):* actuate pen with a servo or repurpose the
BLTouch; `--servo-pen` emits `M280`. Faster, no Z lash, more build effort.
- **Decision:** start Z mode; revisit servo only if Z lift is too slow.
4. 🔲 **Paper jig.** Tape an L-shaped corner stop to the bed (front-left) so a
US-Letter sheet always sits at the same `(jig_x_mm, jig_y_mm)`. This is the
single most important accuracy factor.
5. 🔲 **Pen-touch Z reference.** Either set `pen_down_mm` by hand, or use the
BLTouch to probe a fixed point on the jig for a repeatable touch height.
Reversibility: nothing here is permanent; swap the hotend back to print anytime.
---
## 2. First-light calibration (uses --test-box)
1. 🔲 Connect: CR-10 enumerates as CH340 `/dev/ttyUSB0` @ 115200. Confirm with
`ls -l /dev/ttyUSB*` and a manual `G28` via pronterface/printrun.
2. 🔲 Dry-run inspect: `ink_signature_cli.py --order <X> --doc cms10114
--test-box` → review the `_testbox.gcode` + `_preview.svg`.
3. 🔲 Plot the box on a **blank** sheet in the jig:
`--test-box --plot --home --port /dev/ttyUSB0`.
4. 🔲 Print a real (unsigned) CMS-10114 cert page, lay it in the jig, plot the
test box again, and confirm the rectangle frames the Section 4A signing cell.
5. 🔲 Tune `--jig-x/--jig-y` (position) and `--pen-down` (ink without digging in)
until the box lands on the line. **Record the final values** as the station
defaults.
6. 🔲 Bake the calibrated defaults into `PlotterConfig` (or a small
`plotter_config.json` the CLI/worker reads), so operators don't pass flags.
Acceptance: the plotted rectangle sits within ~1mm of the cell, repeatably,
across 3 reloads of the sheet.
---
## 3. Software/integration still to build
1. 🔲 **Persisted station config.** `scripts/workers/services/plotter_config.json`
(jig offset, pen heights, feeds, port) loaded by `PlotterConfig.from_file()`.
Keeps calibration out of code + flags.
2. 🔲 **Anchor scaling parity test.** A test that plots/previews against a page
whose `page_w/page_h` differ from the authored size, asserting the strokes
still land in the cell (the stamper already scales; add the matching ink
test).
3. 🔲 **Signature-quality guard.** Reject/flag vectors that are too few points,
near-empty bbox, or a single dot (someone tapped instead of signing) before
they reach the pen. Add to `ink_signature_plotter` + a unit test.
4. 🔲 **855 anchors for ink.** `cms855_pdf_filler` only has the 855I signature
rect today; add 855B/O/A signature rects so org filings can also be plotted
(currently human-placed). Mirror the CMS-10114 anchor approach.
5. 🔲 **Batch integration.** Teach `daily_paper_batch.py` to, for each signed
filing in a batch: (a) print the filled form, (b) call the plotter to ink the
signature, (c) include it in the per-agency envelope. Sequencing + a
per-sheet "plotted ✓" status column so a crash doesn't double-sign or skip.
6. 🔲 **Plot audit trail.** Store the emitted G-code hash + a post-plot photo (if
a camera is added) on the esign/batch record for traceability.
7. 🔲 **Operator safety.** `--plot` already gated; add a hard env guard
(`INK_PLOTTER_ENABLED=1`) so a stray `--plot` on a dev box can't move a
machine, and a `--confirm` prompt for live runs.
---
## 4. Validation (build verifiable criteria)
- 🔲 **Geometry (done, extend):** keep `test_ink_signature.py` green; add the
page-scale parity + quality-guard tests above.
- 🔲 **Physical accuracy:** a calibration card — plot a 10mm grid + the test box,
measure with calipers, assert ≤1mm error. Document the measured numbers.
- 🔲 **Legibility:** plot 5 real captured signatures, scan, eyeball that each is
recognizably the signer's mark (not mangled by resampling). Tune
`min_segment_mm` / feeds if jagged.
- 🔲 **Ink originality sanity:** confirm under magnification the line is
continuous wet ink (not dotty), since "deemed not original" is the failure mode
we're guarding against.
- 🔲 **End-to-end dry run:** one fake order → form printed → signature plotted →
batched → addressed envelope, with nothing actually mailed.
---
## 5. Go-live policy (interpretive risk)
CMS does not explicitly bless/ban autopen for the 855/10114. Therefore:
1. 🔲 **Two paths, choose per filing:**
- *Plotter (fast):* default for low-stakes changes (e.g. address/contact
NPPES updates) where a re-file is cheap.
- *True wet-signature mail-out (safe):* a printed packet to the provider
(cover sheet with a signing arrow + return envelope) for high-stakes
filings (enrollment, reactivation) until acceptance is proven.
2. 🔲 **Pilot:** run a handful of real plotter-signed filings, track acceptance
vs rejection at the MAC/Enumerator. If clean, widen the plotter default.
3. 🔲 **Kill switch:** if any rejection cites the signature, fall back to wet-sig
mail-out for that service and log it.
Note: never expose any of this (plotter, paper, ink, MAC, Enumerator) in
client-facing copy — same rule as the rest of the no-login model.
---
## 6. Operational runbook (once calibrated)
```
# Daily, per signed Standard filing (or via daily_paper_batch once wired):
1. Print the filled, unsigned form (form printer, plain paper).
2. Lay the cert page in the jig on the CR-10.
3. Plot the signature:
INK_PLOTTER_ENABLED=1 python scripts/workers/ink_signature_cli.py \
--order CO-XXXX --doc cms10114 --plot --home --confirm
4. Verify the ink landed on the line; reassemble the form pages.
5. Hand to the daily batch -> per-agency Priority Mail envelope.
```
---
## 7. Sequence (what to do, in order)
1. Print + mount the spring pen holder; tape the jig. (§1)
2. Calibrate with `--test-box`; record jig/pen values. (§2)
3. Add persisted `plotter_config.json` + load it. (§3.1)
4. Add quality guard + page-scale parity tests. (§3.23.3)
5. Physical accuracy + legibility validation. (§4)
6. Wire into `daily_paper_batch` with per-sheet plotted status. (§3.5)
7. Add env/confirm safety guards. (§3.7)
8. Pilot live filings under the go-live policy; widen or fall back. (§5)
9. (Later) 855B/O/A anchors so org filings can be plotted too. (§3.4)
---
## Dependencies / risks
- ⏳ Everything in §12 is blocked on the pen holder + jig (cheap, fast).
- Risk: jig drift → signature off the line. Mitigate with a fixed, screwed-down
jig and a per-session `--test-box` check.
- Risk: pen dry-out / skipping → illegible mark. Mitigate with gel/rollerball +
legibility validation + a "prime the pen" pre-stroke.
- Risk: CMS deems plotted signature "not original." Mitigate with the two-path
go-live policy + pilot.