WillTools: precast shop-ticket QC and panel handling tools
ci / test (push) Has been cancelled

Public demo snapshot of an in-house pyRevit extension for precast concrete
shop-ticket QC (37 checks / 46 checklist rows) and a standalone panel
handling solver (PCI Chapter 8).

- No client, job, plant or product data: knowledge layers ship as
  structural templates only.
- Ticket QC's model-read escalation targets a LAN model server endpoint
  (configurable), not a cloud provider.
- Built from the private development repo via tools/make_dist.py.
This commit is contained in:
2026-09-03 16:33:47 -05:00
commit 52d94303bc
281 changed files with 155656 additions and 0 deletions
+163
View File
@@ -0,0 +1,163 @@
# WillTools
Precast engineering tooling for Revit: shop-ticket QC against the design
summary, and PCI Chapter 8 handling calculations. Built for one precast
plant's workflow and shared here so a colleague can try it against their own.
Two halves, deliberately kept apart. `WillTools.extension` runs inside
Revit, on the model. `panellift` is plain CPython outside Revit — the same
handling arithmetic, testable in seconds with no Revit licence at all.
## Quick start
```bash
git clone https://github.com/will123song/pyrevit-dev.git
cd pyrevit-dev
python tools/setup_machine.py
```
That installs the host-side Python dependencies and proves the install with
real answers — not just exit codes: it runs `panellift` against a published
worked example and checks the arithmetic against the number the article
prints. Read [INSTALL.md](INSTALL.md) for what to do with the output, and
for pointing pyRevit at the extension so the ribbon shows up in Revit.
Try the handling calculator immediately, no Revit needed:
```bash
python -m panellift examples/example-panel.job.json -o report.html
```
## What works without knowledge layers, and what stands down
This distribution ships **no knowledge** — not a plant's parameter names,
not its casting-bed conventions, not even the published hardware catalogue.
See [`knowledge/README.md`](knowledge/README.md) for why and what the shape
of a real layer looks like.
Runs fully, with no knowledge at all:
- `panellift`'s handling checks against a job file — the example above, or
one you build by hand.
- The ribbon itself, and **Self Check**, which tells you exactly what is and
is not configured on this machine.
- `python tools/setup_machine.py --check` — reports the no-knowledge state
as a **pass**, not a failure. A knowledge-less trial install is an
expected, first-class state here, not a broken one.
Stands down cleanly, with a stated reason rather than a wrong or silent
answer: anything that needs a plant's parameter mapping, the published
hardware catalogue, or the master shop-ticket checklist — most visibly,
**Ticket QC**, which refuses to open with a one-line reason rather than
rendering a report that looks like every ticket passed. Ask the owner for
real knowledge layers once you are ready to point this at an actual job.
## `WillTools.extension` — inside Revit
A pyRevit extension. Runs on IronPython 2.7 on Revit's UI thread, so it does
the things that need the model and nothing that needs testing.
One tab, **WillTools**, four panels. The four tools that are finished are the
four large buttons on **Tools**; everything else is one click down behind a
pulldown, which is what keeps them apart.
| Panel | Button | |
| --- | --- | --- |
| Tools | **Reinforce** | Suggests reinforcing for a design from what comparable designs already carry. |
| | **Panel Lift** | PCI Chapter 8 handling check on the piece, from the insert positions the model already holds. |
| | **Ticket QC** | Checks every shop ticket of a design against its spec — f'c, f'ci, I.T., strand count/grade/diameter, W.W.F., unit weight, pattern legend, size envelope. Needs a knowledge layer; see above. |
| | **Snapshot** | Takes a timestamped detached copy of the model at close-out. |
| Setup | **Config** ▾ | A pulldown. The commands you run to get a job ready or to look at it sideways, rather than the four you press all day. |
| | ↳ Project Config | Writes the project config layer: every setting that is the engineer's to make, in one file, wherever they want it. |
| | ↳ Design Extract | Scrapes a design packet — every sheet whose number reduces to the design, and every view placed on them — reads it with the regex/geometry parser in-process, writes a reviewable `spec.json`. No AI call, no subprocess, nothing that leaves Revit. Run once per design. |
| | ↳ Self Check | Probes everything the tools assume about this machine, this Revit and this model. Run it first on a new computer. |
| | ↳ Job Recon | Reconciles the issued ticket set against the whole job — the question no per-ticket check can answer, because a ticket that is not there cannot be checked. |
| | ↳ Takeoff | What the job contains, per piece and in total: hardware by part number, reinforcing by bar mark. |
| Design | **DesignHub** ▾ | A pulldown, and a quarantine: both rows below are buttons-and-docs only. |
| | ↳ Gravity (WIP) | Gravity load chasing. Unfinished; today the button writes nothing at all. |
| | ↳ Lateral (WIP) | Lateral extraction. Unfinished; today it writes a JSON model, two CSVs, and a RISA draft that is deliberately not a real RISA input yet. |
Anything half-built lives behind the **Design** panel's pulldown and carries
`(WIP)` in its name, so nothing unfinished ever sits beside a tool that works.
The design intent lands on disk as JSON that a human reads and corrects before
anything trusts it. Repeated checking is then pure arithmetic — no model, no
judgement, same answer every time.
See [INSTALL.md](INSTALL.md) to deploy it, including on a different Revit
version.
## `panellift` — outside Revit
PCI Design Handbook Chapter 8 handling checks: stripping and yard handling of
flat panels, from the insert positions the model already holds.
Plain CPython, **no dependencies**, and no Revit import anywhere. That is the
point — a calculation whose output reaches a plant has to be verifiable, and
verifiable means a test suite that runs in seconds without a licence.
It reproduces every published number in the ASPIRE Winter 2019 worked examples
(which reprint PCI Table 8.3.1 and Figure 8.3.2), and it *derives* PCI's
0.0214 moment coefficient from the beam solution rather than quoting it:
```bash
cd panellift && python -m pytest
```
**Run it rather than trusting a number printed here** — a suite grows every
day and a README does not.
See [panellift/PLAN.md](panellift/PLAN.md) for what is built, what is next,
and the idealisations that are known to be idealisations.
## Filing feedback
Please do — that is what this trial is for. Two templates when you open an
issue: **Bug report** for something that crashed or gave a wrong answer,
**Question** for something that was unclear.
One thing worth knowing before you file: **this tool refuses rather than
guesses, by design.** A row that reads "NOT JUDGED" with a stated reason —
an unmapped parameter, a missing knowledge layer, a check that legitimately
has nothing to say about this piece — is very often the tool working
*correctly*, not a bug. The bug report template asks you to tell these two
apart:
- **Wrong answer** — it computed something, and the something is wrong, or
it crashed. That is a code bug; file the Bug report template, and paste
`python tools/setup_machine.py --check`'s full output — it is the single
most diagnostic thing you can attach.
- **Refused, and I think it shouldn't have** — it declined to answer and you
believe it had enough information to. That is usually knowledge-layer
work (a parameter role that needs mapping, a rating that needs
publishing) rather than a code fix — file it as a Question, and say what
you expected it to know.
**No client or job data in an issue, a PR, or a screenshot — ever.** See
[CONTRIBUTING.md](CONTRIBUTING.md) for the placeholder convention this
project uses everywhere instead.
### What to ask the owner for
This distribution ships no knowledge on purpose. To point it at a real job
you will want, from the owner directly (not filed as an issue — these are
not code, and they identify a real plant):
- a **plant knowledge layer** — your office's parameter names, casting-bed
conventions, and rigging defaults;
- the **published hardware catalogue** — manufacturer ratings for lifting
inserts and connectors, plus the master shop-ticket checklist Ticket QC
reads;
- sample decks or a walkthrough, if you want a guided first run rather than
starting from the example in `examples/`.
## Working on this
- **Never use pyRevit → Reload. Restart Revit.** A reload leaves the routes
handler pointing at a dead engine and the next bridge request kills Revit.
- IronPython 2.7 syntax under `WillTools.extension/`; modern Python is fine in
`tools/` and `panellift/`.
- Any change to a model needs a Transaction. Internal units are decimal feet.
- Scope every `FilteredElementCollector`. An unfiltered one crashed Revit.
See [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR.