Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: CI

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
base:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: python -m pip install -r requirements.txt -r requirements-dev.txt
- run: npm test
- run: npm run lint
- run: npm run privacy:check
- run: npm run provenance:check
- run: npm run pack:check

full-render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: sudo apt-get update && sudo apt-get install -y jq libreoffice poppler-utils
- run: python -m pip install -r requirements.txt -r requirements-dev.txt -r requirements-render.txt
- run: npm run test:full
env:
PI_STEEL_REQUIRE_FULL_RENDER: "1"
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@ node_modules/
*.tgz
.DS_Store
outputs/
out/
.a5c/
__pycache__/
*.pyc

# Local company, project, and generated business data
.pi-steel/
company-profile.json
**/company-profile.json
private/
local-data/
customer-data/
vendor-data/
*.local.json
*.private.json
*.xlsx
*.xls
*.pdf
*.dxf
*.png
Comment thread
Steel-tech marked this conversation as resolved.
17 changes: 17 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
**/__pycache__/
**/*.pyc
**/company-profile.json
.pi-steel/
private/
local-data/
customer-data/
vendor-data/
outputs/
out/
*.local.json
*.private.json
*.xlsx
*.xls
*.pdf
*.dxf
*.png
19 changes: 19 additions & 0 deletions DATA_PROVENANCE.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"schema_version": "1.0.0",
"datasets": [
{
"dataset_id": "aisc-shapes-v16-transformed",
"shipped_file": "skills/steel-takeoff/assets/aisc-shapes-database.json",
"claimed_edition": "AISC Shapes Database v16.0",
"rows": 477,
"sha256": "5a7c975c4c290c34df6f7df3b4d0d0d13a00ef7c2b1f45097a49a78d245dcc91",
"required_fields": [
"type",
"designation",
"weight_per_ft"
],
"redistribution_permission": "unverified",
"release_readiness": "blocked"
}
]
}
42 changes: 42 additions & 0 deletions DATA_PROVENANCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Data Provenance

This file records the evidence and release decision for third-party datasets
shipped by pi-steel. The repository's MIT license covers StructuPath-authored
code and documentation; it must not be interpreted as granting rights in
third-party data.

[`DATA_PROVENANCE.json`](DATA_PROVENANCE.json) is the machine-readable release
record checked against the shipped bytes. This document provides the supporting
human-readable evidence and decision rationale.

## AISC shapes database

| Field | Recorded value |
| --- | --- |
| Shipped file | `skills/steel-takeoff/assets/aisc-shapes-database.json` |
| Claimed edition | AISC Shapes Database v16.0, consistent with the 16th Edition Steel Construction Manual |
| Rows in shipped JSON | 477 |
| SHA-256 | `5a7c975c4c290c34df6f7df3b4d0d0d13a00ef7c2b1f45097a49a78d245dcc91` |
| Upstream description | [AISC Shapes Database v16.0](https://www.aisc.org/aisc/publications/steel-construction-manual/aisc-shapes-database-v160/) |
| Release evidence | [AISC's August 14, 2023 companion-material announcement](https://www.aisc.org/news/aisc-releases-complementary-materials-for-the-16th-edition-steel-construction-manual/) |
| Repository introduction | Initial repository commit |
| Transformation history | Unknown; no source workbook, conversion script, field map, or contemporaneous checksum is present in repository history |
| Upstream file checksum | Not recorded; the checked-in JSON cannot currently be byte- or row-reconciled to a preserved source workbook |
| Redistribution permission | Unverified |
| Release gate | Blocked pending affirmative redistribution evidence or replacement with a dataset whose redistribution terms are documented |

The upstream pages establish that AISC publishes the v16.0 spreadsheet as a
downloadable digital supplement and describe its relationship to the 16th
Edition Manual. They do not, based on the evidence recorded here, grant
permission to redistribute a transformed copy in another public package.
Availability without charge is not treated as redistribution permission.

Until the release gate is resolved:

- Do not claim that the repository's MIT license covers the shapes data.
- Do not claim that the checked-in JSON is an independently reproducible
transformation of the official workbook.
- Do not publish a new release containing this file without documented approval
or a documented replacement decision.
- Continue verifying the recorded checksum so an unexplained data change cannot
pass unnoticed.
49 changes: 49 additions & 0 deletions PUBLIC_DATA_POLICY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Public Data Policy

This repository is public. Source code, documentation, tests, fixtures, generated
goldens, commit metadata, issue text, and release artifacts must be safe for public
distribution.

## Allowed

- Clearly labeled synthetic projects, customers, vendors, people, and identifiers.
- Published standards data whose source, edition, license, and redistribution rights
are documented.
- Invented dimensions and quantities that do not reproduce a private project.
- Placeholder configuration such as `Example Fabricator` and `Example City, ST`.
- Product behavior and generic steel-domain terminology.

## Prohibited

- Private company names or identifiers other than the public StructuPath product
identity.
- Customer, vendor, employee, subcontractor, or project names and contact details.
- Real job numbers, drawing references, addresses, schedules, quotes, bids, rates,
margins, payroll, costs, terms, or contract language.
- Production drawings, takeoffs, BOMs, nests, RFQs, quotes, reports, screenshots, or
generated artifacts, including "anonymized" copies derived from them.
- Company profiles, logos, signatures, credentials, tokens, local absolute paths, or
exported cloud files.
- Facts that link this product to a private operating company, facility, customer, or
internal workflow unless separately approved for publication.

## Fixture Rules

1. Create fixtures from scratch; do not sanitize production files for public use.
2. Prefix project-like identifiers with `SYNTHETIC-` or `EXAMPLE-`.
3. Use `Example Customer`, `Example Vendor`, `Example Fabricator`, and
`Example City, ST` unless a test requires another obviously fictional value.
4. Omit prices and commercial terms unless the test specifically requires them. When
required, label values as synthetic in the same fixture.
5. Keep private inputs and generated outputs outside the repository in ignored
directories such as `private/`, `local-data/`, `customer-data/`, or `outputs/`.
6. Run `python3 scripts/check-public-data.py` before every commit and release. Before
pushing, also scan the outgoing range with
`python3 scripts/check-public-data.py --range <remote-ref>..HEAD`.
7. Put private names and identifiers, one per line, in the ignored local file
`.pi-steel/private-terms.txt`; the scanner checks them without committing the
denylist or echoing matched text.

Git history is public too. Removing a value from the current tree does not remove it
from prior commits. Use `npm run privacy:history` for a redacted audit; history
cleanup requires an explicit coordinated rewrite.
55 changes: 45 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# pi-steel

Structural steel estimating skills for the [Pi coding agent](https://pi.dev) — built by working steel estimators, not by people guessing what a takeoff is.
Structural steel estimating skills for the [Pi coding agent](https://pi.dev).

By [StructuPath](https://structupath.ai), from the team behind a production structural-steel fabrication shop in Denver, CO.
By [StructuPath](https://structupath.ai).

## Install

Expand All @@ -17,7 +17,7 @@ pi install npm:@structupath/pi-steel
Structural steel quantity takeoff with a bundled **AISC 16th Edition shapes database (477 shapes)** — W, HSS, angles, channels, pipe — plus scripts the agent runs directly:

- `lookup-member.sh` — full property set for any AISC designation (`W14X30` → plf, d, bf, A, Ix, Sx, …)
- `calculate-weight.sh` — BOM totals with connection and misc-steel allowances, tonnage, cost sensitivity
- `calculate-weight.sh` — BOM weight totals with connection and misc-steel allowances and tonnage; it does not invent pricing
- `validate-bom.py` — catches invalid designations, wrong grades, duplicate marks, unreasonable weights

Also includes reference guides for AISC shape families, takeoff procedures with worked examples, connection types and hardware weights, material grades, and bolt capacities.
Expand All @@ -28,11 +28,17 @@ Ask your agent things like:
> "What's the lightest W-shape with depth ≥ 18" and Ix ≥ 1000?"
> "Total tonnage on this BOM with 12% connections"

### `steel-nest` — plate nesting & burn-table DXF
### `steel-nest` — plate nesting & guarded DXF output

The plate-layout step CAM software does, minus the CAM seat: MaxRects bin-packing of parts onto stock plates with kerf/gap/edge-margin spacing, holes and rectangular cutouts, yield/scrap/reusable-drop numbers, and material cost. Outputs a labeled layout (PDF + PNG per plate), a cut list, and **one DXF per sheet for the burn table** (part outlines on `PROFILE`, holes on `HOLES`, origin at sheet corner — ready for ProNest/FastCAM/SigmaNEST import).
The plate-layout step CAM software does, minus the CAM seat: MaxRects bin-packing of parts onto stock plates with kerf/gap/edge-margin spacing, holes and rectangular cutouts, yield/scrap/reusable-drop numbers, and material cost. Outputs include a labeled layout (PDF + PNG per plate), a cut list, and an explicitly named all-sheets reference DXF.

Honest about its limits: rectangular parts nest exactly; irregular parts nest by bounding box (flagged, never hidden); it deliberately does **not** emit G-code — kerf comp, lead-ins, and pierce points belong to your table's real post-processor.
Per-sheet `burn_plate_N.dxf` files are emitted only for a complete rectangular nest whose supported holes remain inside their parts. Those files contain cut entities only: closed outlines on `PROFILE` and holes/cutouts on `HOLES`. Sheet outlines and labels remain in clearly named reference files. Any irregular part, unplaced part, or out-of-bounds hole suppresses burn DXFs for the whole job and leaves the safe estimating/reference artifacts available with an explicit warning.

Honest about its limits: rectangular parts nest exactly; irregular parts nest by bounding box (flagged, never hidden); reference DXFs are not cutting instructions; and the package deliberately does **not** emit G-code. Kerf compensation, lead-ins, pierce points, and machine-specific verification belong to the table's real CAM and post-processor.

Each command publishes an isolated run under the requested output root and updates
`latest-run.json`. Exit `0` is geometry-verified, `2` requires review, and `3` is
blocked. No named CAM compatibility is claimed.

> "How many sheets does this job need?"
> "Nest these parts on 96×48 plate and give me the yield"
Expand All @@ -44,21 +50,50 @@ Requires `ezdxf`, `matplotlib`, `numpy` (`pip install ezdxf matplotlib numpy`).

Turns a steel estimate/takeoff spreadsheet into a standardized vendor RFQ (.xlsx): materials grouped the way vendors stock them (W-shapes / plate / flat bar), yellow fill-in pricing columns, nesting/drop reference, and terms & conditions — branded with **your** company profile. When `steel-nest` has run for the job, its cutting plan flows straight into the RFQ's nesting table.

The three skills chain into a full estimating pipeline: **takeoff → nest → RFQ**.
The `steel-estimate` orchestrator chains the skills into a review-gated estimating
pipeline: **takeoff → nest → draft RFQ**. It publishes immutable run directories,
QA findings, lineage, and readiness labels; blocked runs never contain a workbook.

One-time setup: copy `skills/steel-rfq/assets/company-profile.example.json` to `company-profile.json` and put in your company name, city, and payment terms. The skill will ask and offer to save it if you skip this.
One-time setup: copy `skills/steel-rfq/assets/company-profile.example.json` to the
ignored path `.pi-steel/company-profile.json` in your project and enter approved
company and commercial information there. Never add the completed profile to this
repository.

> "Send this takeoff out for pricing"
Keep company profiles, customer files, vendor information, live pricing, and generated
artifacts outside this repository. Public examples are synthetic and must follow
[`PUBLIC_DATA_POLICY.md`](PUBLIC_DATA_POLICY.md).

> "Prepare a draft RFQ from this takeoff"
> "Generate an RFQ from this estimate"

## Requirements

- `jq` and `python3` (with `pandas` + `openpyxl` for RFQ generation)
- macOS or Linux

## Development and release checks

```bash
npm test # base, no-render suite
npm run test:full # optional PDF/PNG/DXF/LibreOffice smoke tests
npm run privacy:check # public-repository data guard
npm run privacy:history # redacted audit of every reachable commit
npm run pack:check # npm contents plus unpacked-runtime smoke test
npm run provenance:check # shape-data integrity and recorded decision
npm run release:check # complete release gate
```

`release:check` is intentionally blocked while redistribution permission for the
checked-in transformed AISC shape dataset remains unverified. See
[`DATA_PROVENANCE.md`](DATA_PROVENANCE.md). Do not publish a new package release
by bypassing that gate.

## License

MIT. AISC shape data derived from the publicly available AISC Shapes Database v16.0.
StructuPath-authored code and documentation are MIT licensed. That license does
not grant rights in third-party data. The checked-in AISC-derived shape data has
a separate, currently blocked redistribution decision documented in
[`DATA_PROVENANCE.md`](DATA_PROVENANCE.md).

---

Expand Down
Loading
Loading