opentakeoff-mcp 0.9.3 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -117,7 +117,10 @@ includes document text, shape vertices, or result payload content.
117
117
  | `delete_shape` | Remove a committed shape by id. |
118
118
  | `edit_shape` | **Revise** a committed shape instead of redoing it: new `verts`, a different `condition`, a different `role`, or any combination — quantities recomputed from the result. Refuses shapes a human affirmed. |
119
119
  | `edit_materials` | Add/remove/patch supporting-materials rows on a condition — the coverage-rate lines (adhesive at N sf/gal, grout at N lf/bag, …) that turn a measured quantity into an order quantity, matching the canvas's Supporting Materials panel. `condition` mints on first touch, like `one_click`/`measure_polygon`. No review gate (materials rows are quantity config, not traced geometry) — edits directly, reversible with `undo_last`. |
120
- | `undo_last` | Step back over your own last `n` mutations, newest first. Exact inverses: a commit is removed, an edit restored verbatim, a delete re-inserted where it was, a materials edit's whole array restored. A whole `detect_rooms` sweep is **one** step. |
120
+ | `edit_condition` | Set a condition's **waste %** and **×N multiplier** — the knobs that turn measured quantities into order quantities (`takeoff_summary`'s `*_net`); without them an agent takeoff always ships net === gross. Resolves an **existing** finish tag or errors a typo must not mint an empty condition. No review gate; one `undo_last` step restores both knobs verbatim. |
121
+ | `export_report` | The **computed Report document** — `opentakeoff.report.v1`, the same JSON the canvas Report exports: gross + waste-adjusted quantities, the computed materials **buy list** per condition plus the project-wide roll-up, per-sheet base subtotals, and scale provenance. The contract for pricing consumers — `export_takeoff` carries materials as config rows, `takeoff_summary` strips them. Inline, and to disk with `path`. |
122
+ | `export_marked_pdf` | The **marked-up planset** — the deliverable. Writes a distribution-ready PDF: a legend cover (per-condition totals, swatches, by-sheet breakdown) plus every sheet that carries work, vector-copied from the source with shapes, hatches, per-shape quantity chips, and annotations burned in — built by the same module as the canvas's MARKED SET button. Machine-traced shapes are disclosed as pending human review on the document itself. Default path: `<plan> - marked set.pdf` next to the plan. Works without `@napi-rs/canvas`. |
123
+ | `undo_last` | Step back over your own last `n` mutations, newest first. Exact inverses: a commit is removed, an edit restored verbatim, a delete re-inserted where it was, a materials edit's whole array restored, a condition edit's waste/multiplier pair restored. A whole `detect_rooms` sweep is **one** step. |
121
124
  | `read_sheet_text` | Positioned page text (image px), optionally restricted to a region — title blocks, room labels, finish schedules. |
122
125
  | `find_text` | **Locate** a known string — the complement to `read_sheet_text` (which returns what a region *says*; this finds *where* a string sits). Case-insensitive substring match per pdf.js text run; each hit's center feeds straight into `one_click`'s seed. |
123
126
  | `sheet_context` | The region's STRUCTURE in one frame: classified vector segments (endpoints as drawn, meta byte per segment), text spans with bboxes, and hatch-family instances with content-derived ids — same pattern spec ⇒ same id anywhere on the sheet, so plan↔legend matching is `id === id`. Decimation is declared and counted on every reply: `kept + dropped === total_in_region`, cap applies longest-first so walls survive. |
@@ -215,8 +218,14 @@ one_click { "sheet": "sample-plan.pdf", "x": 600, "y": 464, "condition":
215
218
  one_click { "sheet": "sample-plan.pdf", "x": 1600, "y": 464, "condition": "CPT-1" } → ~438 SF
216
219
  takeoff_summary {} → CPT-1, 4 shapes, ~1752 SF
217
220
  export_takeoff { "path": "/tmp/takeoff.json" } → the app's save payload
221
+ export_marked_pdf {} → the marked-up planset PDF,
222
+ written next to the plan
218
223
  ```
219
224
 
225
+ A takeoff finishes with **both** exports: `export_marked_pdf` is what a human
226
+ reviews (construction takeoffs are no good without markup), `export_report` is
227
+ what pricing consumes.
228
+
220
229
  Sheet keys follow the app's codec: page 1 is the bare file name
221
230
  (`plan.pdf`), pages 2+ are `plan.pdf#2`. Tools also accept the title-block
222
231
  sheet number (`A-101`) wherever a sheet is named.
@@ -227,8 +236,9 @@ sheet number (`A-101`) wherever a sheet is named.
227
236
  `one_click` reports it plainly; a raster fallback is a planned seam
228
237
  (`src/session.ts`, `ensureMask`), not yet built.
229
238
  - One document per session; `load_plan` replaces it.
230
- - The takeoff lives in memory. `export_takeoff` is the way out and its
231
- payload is exactly what the app persists, so nothing is lost in translation.
239
+ - The takeoff lives in memory. `export_takeoff` (the app's exact save payload,
240
+ nothing lost in translation) and `export_marked_pdf` (the reviewable marked
241
+ planset) are the ways out.
232
242
 
233
243
  ## Tests
234
244