# Contributing Thanks for trying this out. Short version: run the tests, never paste real job data anywhere, and expect review on anything that changes a verdict. ## Running the tests Two independent suites, both plain CPython, no Revit and no licence needed: ```bash python -m pytest panellift -q # PCI Chapter 8 handling checks python -m pytest WillTools.extension -q # the Revit-free half of the extension ``` Both are self-contained -- fixtures build their own data, nothing reads a real job. `python -m compileall WillTools.extension tools panellift/src` is a fast syntax smoke test across all three, including the IronPython-targeted code under `WillTools.extension/`, which only runs for real inside Revit. `python tools/setup_machine.py --check` is the doctor. Run it before filing an issue and paste its output in full -- see the bug report template. ### What does not run in a trial install `knowledge/catalogue.yaml` ships here, but as a carve-out -- read its own header for the exact list of what it carries (trade-standard vocabulary, the shop-ticket checklist skeleton) and what it deliberately omits (the owner's real manufacturer capacity ratings). A small number of tests exist specifically to pin THAT real data -- "does the catalogue publish 4:1 in shear for QLPD4T5WG", not "does the tool's arithmetic work" -- and they are tests of the owner's knowledge, not of this tool. Faking them with invented numbers would just be that same real data through a back door, so instead each suite's `tests/conftest.py` carries an appended block (written by `tools/make_dist.py`'s `append_test_exclusions()`) that SKIPS them by name, with that reason, rather than letting them fail: | suite | tests skipped | why | | --- | --- | --- | | `WillTools.extension` | 6, in `tests/test_knowledge.py` | read `catalogue.inserts` directly, assert a real ALP insert's factor/spacing, or a real HK Composites tie's edge distance | | `panellift` | 1 parametrized function (7 cases), in `tests/test_safety_factors.py` | its own docstring already calls it "a golden-value check against a page, not a recomputation" | Both blocks **auto-detect**: they check whether `catalogue.inserts` in the `knowledge/catalogue.yaml` the test run actually finds is non-empty, and stand down with no edit needed the day someone runs these suites against the owner's real knowledge layers. Run `python -m pytest -rs` (either suite) to see every skip and its reason printed, rather than trusting a count copied into this paragraph. ## No client or job information in the repo. Ever. Not in an issue, not in a PR description, not in a commit, not in a screenshot, not in a test fixture. If you need to refer to one, use the placeholder convention this repository already uses everywhere — write the placeholder rather than deleting the sentence: | | | | --- | --- | | a client / owner | `sample_client` | | a job / project / model | `sample_job` | Product codes are not client information and stay as they are: design numbers (`PNL1.0`), piece marks (`PNL101`), and hardware part numbers (`ANCHOR_FACE_4T`) are naming conventions, not identities. `python tools/scrub.py --worktree --terms .scrub-terms.example` is the same check CI runs, and you can install it as a pre-commit hook on your own clone: ```bash python tools/scrub.py --install-hook ``` It runs on the generic sample terms here (there is no real `.scrub-terms` file in this distribution) plus structural patterns -- an absolute Windows user path, a `.rvt`/`.rfa` filename, an email address -- which catch a leak whether or not it happens to be on anybody's list yet. ## Opening a PR - Keep it focused. A PR that fixes one thing is reviewed faster than one that fixes three. - If it changes what a check reports (a verdict, a finding, a threshold), say so explicitly in the description and expect the owner to review it personally -- these tools produce numbers a real plant floor may act on, and "the tests still pass" is necessary but not sufficient for that class of change. - If it's a new tool or button, read `docs/architecture-migration.md` and the `plan-*.md` docs first for the shape this project is moving toward. ## Filing an issue instead See the two issue templates -- **Bug report** for something that crashed or gave a wrong answer, **Question** for something that was unclear or a refusal you think should have been an answer. The README's "Filing feedback" section has more on the difference between those two, and it matters: a refusal is very often the tool working correctly.