@floless/app 0.51.0 → 0.53.0
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/dist/floless-server.cjs +9 -5
- package/dist/skills/floless-app-queue/SKILL.md +1 -1
- package/dist/skills/floless-app-report-issue/SKILL.md +1 -1
- package/dist/skills/floless-app-steel-model/SKILL.md +160 -0
- package/dist/skills/floless-app-steel-takeoff/SKILL.md +8 -8
- package/dist/skills/floless-app-tweak-contract/SKILL.md +2 -2
- package/dist/skills/reading-structural-drawings/SKILL.md +127 -0
- package/dist/templates/{steel-takeoff.flo → steel-model.flo} +2 -2
- package/dist/web/aware.js +1 -1
- package/dist/web/steel-3d-view.js +1 -1
- package/dist/web/steel-editor.html +2 -2
- package/package.json +1 -1
package/dist/floless-server.cjs
CHANGED
|
@@ -52856,7 +52856,7 @@ function appVersion() {
|
|
|
52856
52856
|
return resolveVersion({
|
|
52857
52857
|
isSea: isSea2(),
|
|
52858
52858
|
sqVersionXml: readSqVersionXml(),
|
|
52859
|
-
define: true ? "0.
|
|
52859
|
+
define: true ? "0.53.0" : void 0,
|
|
52860
52860
|
pkgVersion: readPkgVersion()
|
|
52861
52861
|
});
|
|
52862
52862
|
}
|
|
@@ -52866,7 +52866,7 @@ function resolveChannel(s) {
|
|
|
52866
52866
|
return "dev";
|
|
52867
52867
|
}
|
|
52868
52868
|
function appChannel() {
|
|
52869
|
-
return resolveChannel({ isSea: isSea2(), define: true ? "0.
|
|
52869
|
+
return resolveChannel({ isSea: isSea2(), define: true ? "0.53.0" : void 0 });
|
|
52870
52870
|
}
|
|
52871
52871
|
|
|
52872
52872
|
// workflow-update.ts
|
|
@@ -53893,7 +53893,7 @@ function contractToScene(contractInput) {
|
|
|
53893
53893
|
color: pickColor(profile, i, contract)
|
|
53894
53894
|
}));
|
|
53895
53895
|
return {
|
|
53896
|
-
scene: { meta: { name: contract.title || "Steel
|
|
53896
|
+
scene: { meta: { name: contract.title || "Steel Model", units: "mm", up: "z" }, groups, elements },
|
|
53897
53897
|
skipped
|
|
53898
53898
|
};
|
|
53899
53899
|
}
|
|
@@ -60631,14 +60631,18 @@ var PRODUCT_SKILLS = [
|
|
|
60631
60631
|
// file a diagnosed bug/idea/question to the private log via the floless.io relay
|
|
60632
60632
|
"floless-app-routines",
|
|
60633
60633
|
// author event-driven ("on trigger") routines
|
|
60634
|
+
"floless-app-steel-model",
|
|
60635
|
+
// front-door guide: orchestrate a steel drawing SET into a model (project → knowledge → agents → confirm-gated reads via the reader)
|
|
60634
60636
|
"floless-app-steel-takeoff",
|
|
60635
60637
|
// read a steel drawing into an editable steel.takeoff/v1 contract (the Steel Takeoff reader)
|
|
60636
60638
|
"floless-app-tweak-contract",
|
|
60637
|
-
// handle a tweak-contract request from the
|
|
60639
|
+
// handle a tweak-contract request from the Steel Model contract editor (Slice 2 AI round-trip)
|
|
60638
60640
|
"floless-app-ui",
|
|
60639
60641
|
// compose Custom Panels (~/.floless/ui/extensions.json) for the Dashboard
|
|
60640
|
-
"floless-app-workflows"
|
|
60642
|
+
"floless-app-workflows",
|
|
60641
60643
|
// author/run .flo workflows
|
|
60644
|
+
"reading-structural-drawings"
|
|
60645
|
+
// the drawing-set reading discipline (non-namespace) the steel guide + reader lean on; shipped so users get it too
|
|
60642
60646
|
];
|
|
60643
60647
|
function selectShippedSkillNames(names) {
|
|
60644
60648
|
const present = new Set(names);
|
|
@@ -40,7 +40,7 @@ documented in `floless-app-bridge`; the five types map to:
|
|
|
40
40
|
|---|---|---|
|
|
41
41
|
| `tweak` | "Tweak node **`<nodeId>`** in **`<appId>`** — *<instruction>*" | `floless-app-workflows` |
|
|
42
42
|
| `use-template` | "Add template **<template.name>** to **`<appId>`**" | `floless-app-workflows` |
|
|
43
|
-
| `tweak-contract` | "Edit the
|
|
43
|
+
| `tweak-contract` | "Edit the Steel Model contract for **`<appId>`** — *<instruction>* (+N screenshot(s))" | `floless-app-tweak-contract` |
|
|
44
44
|
| `ui-customize` | "Customize the Dashboard (optionally `panel <panelId>`) — *<instruction>*" | `floless-app-ui` |
|
|
45
45
|
| `rebake` | "Re-read the **<inputName>** drawing (<sourceName>) in **`<appId>`** — *<instruction>*" | `floless-app-rebake` |
|
|
46
46
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: floless-app-report-issue
|
|
3
|
-
description: File a diagnosed bug / idea / question from floless.app into the PRIVATE product log via the floless.io relay. Use when the user invokes /floless-app-report-issue, clicks "Report an issue" in the floless.app UI (a queued report or a copied prompt), or says "report this", "file a bug", "something broke in floless", "send feedback / a feature idea". It READS the live run evidence first (latest run trace, failing node + error, the .flo, exec code), offers a workaround when one exists, then composes a maintainer-ready report and sends it — always showing the exact text and confirming first. Read-only
|
|
3
|
+
description: File a diagnosed bug / idea / question from floless.app into the PRIVATE product log via the floless.io relay. Use when the user invokes /floless-app-report-issue, clicks "Report an issue" in the floless.app UI (a queued report or a copied prompt), or says "report this", "file a bug", "something broke in floless", "send feedback / a feature idea". It READS the live run evidence first (latest run trace, failing node + error, the .flo, exec code), offers a workaround when one exists, then composes a maintainer-ready report and sends it — always showing the exact text and confirming first. Read-only — it never re-runs a workflow node.
|
|
4
4
|
metadata:
|
|
5
5
|
version: 0.1.0
|
|
6
6
|
---
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: floless-app-steel-model
|
|
3
|
+
description: The front-door guide for turning a structural steel drawing SET into an editable model in floless.app — the "Steel Model" flow. This skill orchestrates the whole pipeline — set up a project folder, learn the set into plain-English knowledge files, provision the right AWARE agents (region-specific steel detailer plus any bake targets), confirm which sheets are plans / elevations / details, then hand off to the Steel Takeoff reader to read each plan into a steel.takeoff/v1 contract — with explicit confirm gates between stages. Use it when a user wants to model steel from a drawing SET or asks things like "model this steel job from the drawings", "take off this whole set", "start a steel takeoff project", "turn these structural drawings into a model", "I have a PDF set of framing plans", or "/floless-app-steel-model". It is re-runnable — resume at any stage. For a single already-isolated framing plan the Steel Takeoff reader (floless-app-steel-takeoff) can be used directly; this guide is for driving a real job end to end.
|
|
4
|
+
metadata:
|
|
5
|
+
version: 0.1.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Steel Model — guide a steel drawing set into an editable model
|
|
9
|
+
|
|
10
|
+
## What this is
|
|
11
|
+
|
|
12
|
+
The **front door** to floless.app's steel pipeline. A real steel job arrives as a *set* of PDFs
|
|
13
|
+
(framing plans, elevations, sections, details, schedules) plus firm conventions — not a single
|
|
14
|
+
clean plan. This guide drives that whole job: project setup → learn the set → provision agents →
|
|
15
|
+
classify the sheets → read each framing plan into an editable **steel.takeoff/v1 contract**, then
|
|
16
|
+
point the user at the on-canvas tools (filter, 3D, IFC/Tekla export, BOM, the connection library,
|
|
17
|
+
clickable callouts).
|
|
18
|
+
|
|
19
|
+
It is the **orchestration layer ABOVE** the readers and the editor. The actual drawing reading is
|
|
20
|
+
done by **`floless-app-steel-takeoff`** (the Steel Takeoff reader) — this guide gets the project to
|
|
21
|
+
the point where that read is reliable, and hands off. The host AI is the brain (the FloLess thin-UI
|
|
22
|
+
contract): reading happens at COMPOSE time with the terminal AI's own vision; there is no model in
|
|
23
|
+
the run path and no API key.
|
|
24
|
+
|
|
25
|
+
**Re-runnable + interactive.** Each stage ends with an explicit **confirm gate** — show the user
|
|
26
|
+
what was found and get an OK before spending effort on the next stage. Resume at any stage on
|
|
27
|
+
re-invoke ("we already set up the folder, provision the agents").
|
|
28
|
+
|
|
29
|
+
> Companion skills (both ship with floless.app — invoke them, don't duplicate them):
|
|
30
|
+
> - **`reading-structural-drawings`** — the reading *discipline* (massing + coordinate frame FIRST,
|
|
31
|
+
> members LAST, cross-validate every view). Follow it whenever skimming or classifying the set
|
|
32
|
+
> (stages 2 and 5) — it stops the classic failures (two buildings read as one, a sloped roof read
|
|
33
|
+
> as flat, grids conflated across sheets).
|
|
34
|
+
> - **`floless-app-steel-takeoff`** — reads one framing plan into the contract (the heavy vision
|
|
35
|
+
> pipeline, the filter pre-stage, the AISC/EN/BS lookup, the contract write + editor hand-off).
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## The flow
|
|
40
|
+
|
|
41
|
+
Work the stages in order. Announce the stage, do the work, then **stop at the confirm gate** and
|
|
42
|
+
wait for the user's OK before the next stage.
|
|
43
|
+
|
|
44
|
+
### 1. Project folder
|
|
45
|
+
|
|
46
|
+
A steel job has many files and derived artifacts — keep them together. Ask the user to pick or
|
|
47
|
+
create a **dedicated project folder** (e.g. `~/projects/<job-name>/`). Everything lives there: the
|
|
48
|
+
drawing PDF(s), the knowledge files (stage 2), and any exported contracts / IFC / BOM. If they
|
|
49
|
+
already have one, use it. Record the absolute path for the rest of the run.
|
|
50
|
+
|
|
51
|
+
**Gate:** confirm the folder path and that the drawing set (PDF) is in it (or get its path).
|
|
52
|
+
|
|
53
|
+
### 2. Learn the set → plain-English knowledge files
|
|
54
|
+
|
|
55
|
+
Before reading geometry, skim the set and capture what matters into a few short Markdown files in
|
|
56
|
+
the project folder (a few files, **not** a framework):
|
|
57
|
+
|
|
58
|
+
- **`set-index.md`** — one line per sheet: number, title, and what it is (framing plan / elevation /
|
|
59
|
+
section / detail / schedule). This is the map the later stages classify against.
|
|
60
|
+
- **`general-notes.md`** — the General Notes that bind the whole job: design spec, default
|
|
61
|
+
connection type, bolt/weld standard, material grades, anything that overrides a single sheet.
|
|
62
|
+
- **`company-rules.md`** *(ask first)* — **ask whether the firm has company-specific standards**
|
|
63
|
+
(e.g. "moment → detail 50S504 → Tekla component 146"). If yes, capture them here. This file feeds
|
|
64
|
+
the connection-library pre-fill in stage 6 (the editor's Connections panel reads these as
|
|
65
|
+
`source:"company-rules"`). If the firm has none, skip the file — don't invent rules.
|
|
66
|
+
|
|
67
|
+
Read the set with the terminal AI's own vision, following the **`reading-structural-drawings`**
|
|
68
|
+
discipline while skimming (massing + coordinate frame first — it's what makes the sheet
|
|
69
|
+
classification reliable).
|
|
70
|
+
|
|
71
|
+
**Gate:** show `set-index.md` (the sheet map) and confirm the classification looks right — the user
|
|
72
|
+
knows their set better than any read.
|
|
73
|
+
|
|
74
|
+
### 3. Provision the AWARE agents
|
|
75
|
+
|
|
76
|
+
The reader leans on a **region-specific steel detailer** agent (AISC vs EN vs BS section tables) and,
|
|
77
|
+
if the user will bake later, the host bridges.
|
|
78
|
+
|
|
79
|
+
1. **Check what's installed:** `aware agent list --json`.
|
|
80
|
+
2. **Steel detailer — ask the region**, then install the match: `steel-detailer-us` (AISC /
|
|
81
|
+
imperial), `steel-detailer-eu` (EN), or `steel-detailer-uk` (BS). Install with
|
|
82
|
+
`aware agent install <id>`. **Verify it's live** with a known-section lookup before relying on it
|
|
83
|
+
(a section that should resolve — e.g. a W-shape for US — returns a weight).
|
|
84
|
+
3. **Bake targets (optional, only if they'll export later):** offer `tekla`, `rhino`, `revit`,
|
|
85
|
+
`sketchup` — install the ones they want. (3D and IFC export need no host; Tekla bake needs Tekla
|
|
86
|
+
open with a model.)
|
|
87
|
+
4. **Discover more:** `aware agent catalog` / `aware agent search <capability>` lists agents that
|
|
88
|
+
are *available but not installed*. Scan it and suggest any genuinely useful one for steel work;
|
|
89
|
+
don't install without asking.
|
|
90
|
+
|
|
91
|
+
If `aware agent catalog` is unsupported (older AWARE), say so and offer to update AWARE (the footer
|
|
92
|
+
↑ Upgrade pill / `floless-app-onboarding` covers this); fall back to `aware agent list`.
|
|
93
|
+
|
|
94
|
+
**Gate:** confirm the detailer (right region, verified live) and any bake agents are installed.
|
|
95
|
+
|
|
96
|
+
### 4. Read method — PyMuPDF + hide the title block
|
|
97
|
+
|
|
98
|
+
The read method is settled: a deterministic **PyMuPDF** pass enumerates the drawing elements (no
|
|
99
|
+
LLM, no API key) and the framing area is rastered for the vision read. The **title block is
|
|
100
|
+
excluded** from what's read and rastered (it carries client/project/firm identity — see
|
|
101
|
+
Confidentiality). This is handled inside the Steel Takeoff reader and the filter pre-stage; surface
|
|
102
|
+
it to the user as "your title block stays out of the read," and confirm the crop excludes it on the
|
|
103
|
+
first sheet.
|
|
104
|
+
|
|
105
|
+
**Gate:** on the first framing plan, confirm the framing area is captured and the title block is
|
|
106
|
+
out of frame.
|
|
107
|
+
|
|
108
|
+
### 5. Classify the sheets + confirm, view by view
|
|
109
|
+
|
|
110
|
+
The set has many sheets; only the **framing plans** become takeoff contracts. Walk the user through,
|
|
111
|
+
with an explicit OK at each kind (this is the interactive heart — never one-shot a whole set):
|
|
112
|
+
|
|
113
|
+
- **Framing plans** — the sheets that get read into members. Confirm the list before reading.
|
|
114
|
+
- **Elevations / sections** — used for member heights (TOS/BOS), moment-frame schedules, and as
|
|
115
|
+
jump targets for clickable callouts (stage 6). Confirm which sheets these are.
|
|
116
|
+
- **Details** — the connection details the callouts point to. Confirm the detail sheets.
|
|
117
|
+
- **A sample line + profile** — on the first plan, read ONE member (its segment + profile label)
|
|
118
|
+
and show it back; get an OK that the geometry + size mapping is right before reading the rest.
|
|
119
|
+
|
|
120
|
+
**Gate:** explicit OK on the framing-plan list and the sample read before the full read.
|
|
121
|
+
|
|
122
|
+
### 6. Hand off to the reader + the on-canvas tools
|
|
123
|
+
|
|
124
|
+
With the project, knowledge, agents, and classification confirmed, drive the actual reads and point
|
|
125
|
+
the user at the editor:
|
|
126
|
+
|
|
127
|
+
- **Read each framing plan** via **`floless-app-steel-takeoff`** — it runs the filter pre-stage
|
|
128
|
+
(isolate the steel linework by layer/thickness/colour), the vision read, the AISC/EN/BS lookup
|
|
129
|
+
via the detailer, honors `target_confidence`, writes the `steel.takeoff/v1` contract, and opens
|
|
130
|
+
the overlay editor. One contract per `steel-model` app; multi-sheet sets ride the filter's
|
|
131
|
+
`sheets[]` + the editor's plan switcher.
|
|
132
|
+
- **Pre-fill the connection library** from `company-rules.md` (stage 2): emit the firm's rows into
|
|
133
|
+
the contract's `connections[]` with `source:"company-rules"`; the user reviews/assigns them per
|
|
134
|
+
member end in the editor's **Connections** panel (the per-end picker + confidence card).
|
|
135
|
+
- **Point at the rest of the canvas:** the **filter** view (refine the kept linework), **Approve**
|
|
136
|
+
(bake the lock — the determinism gate), **3D** model, **IFC** / **Tekla** export, the **BOM**, the
|
|
137
|
+
**confidence report**, and the **callout bubbles** (click a section/elevation/detail mark on a
|
|
138
|
+
plan to jump to the referenced sheet).
|
|
139
|
+
|
|
140
|
+
**Done** when each framing plan has an approved, editor-reviewed contract and the user knows which
|
|
141
|
+
on-canvas tool does what. The exports (3D/IFC/Tekla/BOM) are on-demand from the editor.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Guardrails
|
|
146
|
+
|
|
147
|
+
- **The host AI is the brain; the run is deterministic.** Reading is a compose-time act; never put
|
|
148
|
+
an LLM or heavy compute in the run path or the server.
|
|
149
|
+
- **Confidentiality (hard rule).** Never commit or echo `raster_b64` / `bg_b64` page rasters or any
|
|
150
|
+
client / project / firm names. The title block is excluded from the read for this reason. Keep job
|
|
151
|
+
files in the user's project folder, not the repo.
|
|
152
|
+
- **Confirm gates are not optional.** A steel set is easy to misread (two buildings on one sheet, a
|
|
153
|
+
sloped roof, grids that differ across sheets). Show findings and get an OK at each stage — the
|
|
154
|
+
user catches what a read misses.
|
|
155
|
+
- **Don't duplicate the companions.** Hand the actual drawing read to `floless-app-steel-takeoff`;
|
|
156
|
+
follow `reading-structural-drawings` for the reading discipline. This guide owns the orchestration
|
|
157
|
+
and the gates, not the pixel-level read.
|
|
158
|
+
- **Tekla (or any platform) component INSERTION at bake is deferred** — the connection library +
|
|
159
|
+
per-end references + scoring are editor-verifiable today; native component placement is a later,
|
|
160
|
+
Tekla-gated step. Don't promise it.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: floless-app-steel-takeoff
|
|
3
|
-
description: Read a structural steel drawing into an editable steel.takeoff/v1 contract in floless.app — the "Steel Takeoff" reader. Triggers on a pending floless `rebake` request for the `steel-
|
|
3
|
+
description: Read a structural steel drawing into an editable steel.takeoff/v1 contract in floless.app — the "Steel Takeoff" reader. Triggers on a pending floless `rebake` request for the `steel-model` app (queued from its "Re-read & re-bake ▸" button), or asks like "read this framing plan into a takeoff", "turn this structural drawing into a takeoff", "bake my drawing into steel-model", "extract members from this PDF". Teaches the host AI to READ a steel drawing (PDF/image) with its own vision at COMPOSE time, build a steel.takeoff/v1 contract (members + profiles + elevations + weights from AISC lookup), write it to the contract store, and hand control to the editor — no model in the run path, no API key.
|
|
4
4
|
metadata:
|
|
5
5
|
version: 0.1.0
|
|
6
6
|
---
|
|
@@ -9,7 +9,7 @@ metadata:
|
|
|
9
9
|
|
|
10
10
|
## What this is
|
|
11
11
|
|
|
12
|
-
`steel-
|
|
12
|
+
`steel-model` is a FloLess app that turns a structural steel drawing into an editable
|
|
13
13
|
**takeoff contract** — members, profiles, AISC weights, T.O. elevations, connection detail refs
|
|
14
14
|
— rendered in the overlay editor, then baked at Approve into the app's `read` node.
|
|
15
15
|
|
|
@@ -34,7 +34,7 @@ but do not attempt them here.
|
|
|
34
34
|
### 1. Find the drawing
|
|
35
35
|
|
|
36
36
|
From a `rebake` request: `GET http://localhost:<port>/api/requests` → the entry with
|
|
37
|
-
`type:"rebake"` and `appId:"steel-
|
|
37
|
+
`type:"rebake"` and `appId:"steel-model"` carries `snapshots: ["<abs path>"]` (the drawing
|
|
38
38
|
file) and optionally `sourceName` (the original filename — use it for the `source.name`
|
|
39
39
|
provenance field). If the user just attaches or points at a drawing in prose, skip the lookup
|
|
40
40
|
and proceed from that path.
|
|
@@ -72,7 +72,7 @@ native/display coords):
|
|
|
72
72
|
`*BEAM*STEL*`, `*COL*`, `*BRACE*`, `*JOIST*`) → default **on**; others off. Mark
|
|
73
73
|
`drawable: false` on pure text/dimension/title-block layers.
|
|
74
74
|
5. Set `filter.mode: "layer"`, `filter.active: 0`. **PUT** the contract
|
|
75
|
-
(`PUT /api/contract/steel-
|
|
75
|
+
(`PUT /api/contract/steel-model`). On a re-read, preserve any existing per-facet `on` flags.
|
|
76
76
|
|
|
77
77
|
Then tell the user to open the **Filter** node, flip through the sheets, narrow to the steel, and
|
|
78
78
|
**Save**. The saved `on` flags + `mode` are what step 2 reads — **per sheet** (each sheet's elements
|
|
@@ -180,7 +180,7 @@ excluded from the average and counted separately as the headline drag).
|
|
|
180
180
|
**The score endpoint is your gauge — call it, don't guess:**
|
|
181
181
|
|
|
182
182
|
```
|
|
183
|
-
POST http://localhost:<port>/api/contract/steel-
|
|
183
|
+
POST http://localhost:<port>/api/contract/steel-model/score
|
|
184
184
|
Content-Type: application/json
|
|
185
185
|
{ "contract": <your draft contract>, "target": <target_confidence, e.g. 70> }
|
|
186
186
|
```
|
|
@@ -309,7 +309,7 @@ Key field rules:
|
|
|
309
309
|
### 5. Write to the contract store
|
|
310
310
|
|
|
311
311
|
```
|
|
312
|
-
PUT http://localhost:<port>/api/contract/steel-
|
|
312
|
+
PUT http://localhost:<port>/api/contract/steel-model
|
|
313
313
|
Content-Type: application/json
|
|
314
314
|
|
|
315
315
|
<contract JSON body>
|
|
@@ -317,7 +317,7 @@ Content-Type: application/json
|
|
|
317
317
|
|
|
318
318
|
The server schema-validates the body. If it responds with `400`, read the error, fix the
|
|
319
319
|
offending fields, and re-PUT. You can read back the current contract with
|
|
320
|
-
`GET /api/contract/steel-
|
|
320
|
+
`GET /api/contract/steel-model`.
|
|
321
321
|
|
|
322
322
|
### 6. Hand off to the user
|
|
323
323
|
|
|
@@ -347,7 +347,7 @@ DELETE http://localhost:<port>/api/requests/<id>
|
|
|
347
347
|
|
|
348
348
|
Never write client, firm, or project identifiers into files, commits, or responses. The
|
|
349
349
|
contract carries the source path in `source.path` and an embedded raster in `raster_b64` — both
|
|
350
|
-
are machine-local (stored under `~/.floless/contracts/steel-
|
|
350
|
+
are machine-local (stored under `~/.floless/contracts/steel-model.json` by the server and
|
|
351
351
|
never committed). Clip title blocks from any embedded preview.
|
|
352
352
|
|
|
353
353
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: floless-app-tweak-contract
|
|
3
|
-
description: This skill should be used when there is a pending floless `tweak-contract` request — the user typed an instruction in the
|
|
3
|
+
description: This skill should be used when there is a pending floless `tweak-contract` request — the user typed an instruction in the Steel Model contract editor and clicked Send (Ask AI). Also triggers on asks like "edit the steel takeoff contract via AI", "adjust the steel takeoff in the contract editor", "the user asked me to change the steel contract", "pick up my tweak-contract request", "update the member profile in the contract". It teaches the host AI to read the request, fetch the current steel.takeoff/v1 contract, apply the instruction (and any pasted screenshots), PUT the updated contract back, and resolve the request.
|
|
4
4
|
metadata:
|
|
5
5
|
version: 0.1.0
|
|
6
6
|
---
|
|
@@ -9,7 +9,7 @@ metadata:
|
|
|
9
9
|
|
|
10
10
|
## What this is
|
|
11
11
|
|
|
12
|
-
The floless.app
|
|
12
|
+
The floless.app Steel Model contract editor surfaces an **Ask AI** panel: the user types
|
|
13
13
|
an instruction ("change all W12X26 to W14X30", "add a new beam on sheet S-202", "mark this
|
|
14
14
|
member as moment-frame") and optionally pastes screenshots, then clicks **Send**. That records
|
|
15
15
|
a `tweak-contract` request in the reverse channel. You pick it up here, edit the contract
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reading-structural-drawings
|
|
3
|
+
description: This skill should be used BEFORE modelling anything from a structural/architectural drawing SET (PDF). Use it whenever turning drawings into a 3D frame, takeoff, IFC, or Tekla model — it is the prerequisite reading discipline for the `floless-app-steel-takeoff` reader (and the `floless-app-steel-model` guide that orchestrates the full flow). Triggers on "read this drawing set", "model this structure from the PDF", "take off this steel", "build a model from these drawings", or any pure-PDF → structure task. It encodes the method that stops the classic failures (missing that a set is TWO buildings, missing a curved/sloped roof, conflating grids across sheets, tracing dimension lines as members) — establish MASSING + COORDINATE FRAME first (from the index + elevations + sections), members LAST; deterministic geometry feeds the reasoning; cross-validate every view; verify before presenting.
|
|
4
|
+
metadata:
|
|
5
|
+
version: 0.1.2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Reading a structural drawing set — the discipline (do this BEFORE you model anything)
|
|
9
|
+
|
|
10
|
+
## Why this exists (the lesson, in one line)
|
|
11
|
+
|
|
12
|
+
A frontier vision model is **document-literate, not drawing-literate** — free-reading a multi-sheet
|
|
13
|
+
set and counting members "by eye" fails *by default* (symbol-grounded geometry ≈ 0.4–0.55 accuracy,
|
|
14
|
+
AECV-Bench 2026). Getting a building wrong (two buildings read as one, a curved roof read as flat,
|
|
15
|
+
a skewed grid read straight) is **not an OCR problem — it is a topology / cross-sheet-fusion
|
|
16
|
+
problem.** The fix is order and validation, not "look harder". This skill is that order.
|
|
17
|
+
|
|
18
|
+
> **Hard rule:** establish the **massing** (how many buildings, roof shape) and the **coordinate
|
|
19
|
+
> frame** (grids + levels) FIRST. Members come LAST. If you are reading member sizes before you can
|
|
20
|
+
> state the building count and roof geometry, STOP — you are about to be confidently wrong.
|
|
21
|
+
|
|
22
|
+
## The one mistake to never repeat
|
|
23
|
+
|
|
24
|
+
Plans cannot show the third dimension. **Building count, roof shape, and storey heights live in the
|
|
25
|
+
ELEVATIONS and SECTIONS — read those before the framing plans.** (A real failure this skill came
|
|
26
|
+
from: a set was modelled as one straight box from the plans; it was actually two separate buildings,
|
|
27
|
+
one with a curved roof — both obvious in the elevations, invisible in the plan.)
|
|
28
|
+
|
|
29
|
+
## Tools — use the deterministic layer; the AI interprets, never measures
|
|
30
|
+
|
|
31
|
+
- **Render/extract with PyMuPDF (`fitz`)** — prefer it over `pdftoppm` (which may not be installed).
|
|
32
|
+
`page.get_text("words")` gives positioned text (grid bubbles, sizes) **losslessly** on vector PDFs;
|
|
33
|
+
`page.get_drawings()` gives every line with real coordinates. Read vectors before you OCR pixels.
|
|
34
|
+
- **AWARE `vision` agent** (`aware agent describe vision`) — image/PDF → **fixed-schema** structured
|
|
35
|
+
JSON via a model. Use it for the structured extraction passes below; the FIXED schema is the point
|
|
36
|
+
(it constrains hallucination). The terminal AI / `vision` *interprets and assembles*; AWARE's
|
|
37
|
+
deterministic nodes own measurement and the `.lock` (the floless contract).
|
|
38
|
+
- **Ask for DXF/DWG first.** If the source CAD exists, `ezdxf` (layers → grids/members/dims directly,
|
|
39
|
+
ARCs → curved roof for free) collapses ~80% of this. AWARE also ships CAD agents
|
|
40
|
+
(`autocad-2025/26`, `tekla`, `tsd-25/26`, `allplan`, `archicad`) if a real model file is available —
|
|
41
|
+
reading the model beats reverse-engineering the drawing.
|
|
42
|
+
|
|
43
|
+
## The method — ordered passes (do not start a pass until the prior one is done)
|
|
44
|
+
|
|
45
|
+
### Pass 0 — Inventory & sheet classification
|
|
46
|
+
Read the **cover / drawing index** and **general notes** first. Build a sheet list classified by
|
|
47
|
+
type (index, notes, foundation plan, framing plans per level, frame elevations, sections, details,
|
|
48
|
+
**schedules**). Confirm the set is complete + current revision. Grab the legend, datum, material
|
|
49
|
+
defaults, and the **abbreviations** (FC/MF/BF/(E)/(N)/matchline symbols). Trust PyMuPDF page_count over
|
|
50
|
+
any external count.
|
|
51
|
+
|
|
52
|
+
### Pass 1 — MASSING (how many buildings, what shape) — from elevations/sections, not plans
|
|
53
|
+
- **Count the buildings.** Look for separate grid-label namespaces, **expansion/seismic joints**
|
|
54
|
+
(a double grid line / gap = two *structurally independent* buildings — members never frame across),
|
|
55
|
+
matchlines, building-name labels, and **disjoint grid clusters** (cluster the long grid lines from
|
|
56
|
+
`get_drawings()` — separate clusters = separate buildings).
|
|
57
|
+
- **Roof + heights** from the **frame elevations and sections**: flat / sloped / hipped / **curved**;
|
|
58
|
+
ridge/eave elevations; storey heights; mezzanines. State each building's roof type explicitly.
|
|
59
|
+
- Output a massing statement BEFORE going further, e.g. *"2 buildings: West (grids F–K.1 × 0.5–5.2),
|
|
60
|
+
2-storey, curved roof; East (grids A–F × 0.5–6), 2-storey, ~flat roof; separated by a seismic joint."*
|
|
61
|
+
|
|
62
|
+
### Pass 2 — COORDINATE FRAME (grid + levels) per building
|
|
63
|
+
- **Grid:** grid-bubble label positions are usually real text (`get_text("words")`). Per building,
|
|
64
|
+
per axis, build `(label, position, real_offset)`. **Calibrate scale from a real dimension string**
|
|
65
|
+
(e.g. a "16'-7¾"" between two bubbles) — NOT the title-block "1:100" (PDFs get re-scaled on plot).
|
|
66
|
+
A 2-point fit gives `real = A·pixel + b`. Check the grid is orthogonal / skewed / radial — don't
|
|
67
|
+
assume 90°. **Each sheet may have its own origin/orientation — re-anchor per sheet; never carry one
|
|
68
|
+
sheet's grid onto another** (this conflation is a top failure).
|
|
69
|
+
- **Levels:** OCR the level/T.O.STEEL tags from an elevation/section into a datum table
|
|
70
|
+
(L1 +0'-0", L2 +16'-6", Roof …). Members snap to these.
|
|
71
|
+
|
|
72
|
+
### Pass 3 — MEMBERS (now, and only now), per building, per level
|
|
73
|
+
- Tile big sheets: **always include a low-DPI full-sheet overview alongside overlapping high-DPI
|
|
74
|
+
tiles** (≥200 DPI; overlap ≥ the largest label). A 3×3 of tiles with **no** overview destroys
|
|
75
|
+
coherence — that is the "wrong shape" failure. Tile only as fine as needed to make the smallest
|
|
76
|
+
label ~20 px.
|
|
77
|
+
- Place each member by the **grid lines it spans** + its level. Read its size label; **confirm size
|
|
78
|
+
against the schedule** (column schedule = authoritative per tier/splice; beam schedule maps marks).
|
|
79
|
+
Map W18×35 = wide-flange, 18" nominal depth, 35 lb/ft, etc.
|
|
80
|
+
- **Use a structured schema that enforces the order** (vision agent or your own): fill
|
|
81
|
+
`coordinate_system → buildings(+roof) → grids_per_building → members`, every value carrying
|
|
82
|
+
`source_view`, `evidence_bbox`, `confidence`, plus mandatory `unreadable[]` and `contradictions[]`.
|
|
83
|
+
A nullable/`unreadable` escape on every field is required — forcing a value the sheet doesn't show
|
|
84
|
+
*causes* fabrication.
|
|
85
|
+
|
|
86
|
+
### Pass 4 — CROSS-VALIDATE (no single view is trusted)
|
|
87
|
+
Plan ↔ elevation ↔ section ↔ schedule must agree. Confirm every member in ≥2 views; confirm
|
|
88
|
+
sloped/spliced members in section/elevation. Disagreement → record in `contradictions[]` as an RFI
|
|
89
|
+
candidate; **do not silently pick one.**
|
|
90
|
+
|
|
91
|
+
### Pass 5 — VERIFY before presenting (definition of done)
|
|
92
|
+
Before building/baking ANY model, self-check against the elevations/sections/3D:
|
|
93
|
+
- building count, roof shape, storey heights, footprint — do they match what the elevations show?
|
|
94
|
+
- did any member cross a seismic joint or matchline? (bug)
|
|
95
|
+
- is the grid the right one for *this* building (not another sheet's)?
|
|
96
|
+
Only then build the scene / overlay / IFC. If unsure, present the **massing + grid** for confirmation
|
|
97
|
+
*before* spending effort on members.
|
|
98
|
+
|
|
99
|
+
## Pitfalls checklist (the traps that cause wrong models)
|
|
100
|
+
- [ ] Multiple independent buildings on one set (count first).
|
|
101
|
+
- [ ] Seismic / expansion joint read as one structure.
|
|
102
|
+
- [ ] Skewed / rotated / radial grid assumed orthogonal.
|
|
103
|
+
- [ ] Curved / sloped roof read as flat (read the elevation!).
|
|
104
|
+
- [ ] Grid from sheet A used on sheet B (per-sheet origins).
|
|
105
|
+
- [ ] Dimension lines / grid lines / leaders traced as members (auto-extraction noise).
|
|
106
|
+
- [ ] `(E)` existing vs `(N)` new vs demo merged (read the legend / line-weight / colour).
|
|
107
|
+
- [ ] Member crossing a matchline read as terminating or double-counted.
|
|
108
|
+
- [ ] Mezzanine / intermediate level missed (only sections show it).
|
|
109
|
+
- [ ] Sizes scaled off the PDF instead of read from dimensions/schedule.
|
|
110
|
+
|
|
111
|
+
## Companion skills
|
|
112
|
+
- After this reading produces a verified structure, hand to the **`floless-app-steel-takeoff`** reader
|
|
113
|
+
to produce the editable `steel.takeoff/v1` contract (which then exports 3D + IFC + Tekla + BOM). This
|
|
114
|
+
skill is the *reading discipline*; that one is the *reader*. The **`floless-app-steel-model`** guide
|
|
115
|
+
(the front-door orchestrator) wraps the whole flow and references this discipline at the
|
|
116
|
+
classify-and-verify gates rather than re-deriving it.
|
|
117
|
+
- There is no off-the-shelf OSS tool that does the whole drawing→model job — floorplan vectorisers
|
|
118
|
+
(e.g. CubiCasa5k) are residential-trained and won't read steel framing — which is why the order +
|
|
119
|
+
validation discipline above, not a single tool, is the method.
|
|
120
|
+
|
|
121
|
+
## References (researched 2026-06-16)
|
|
122
|
+
- AECV-Bench — VLMs are document- not drawing-literate; human-in-the-loop for geometry. arXiv 2601.04819.
|
|
123
|
+
- Multi-stage hybrid VLM for multi-view drawings (arXiv 2510.21862); CAD2Program 2D→3D (arXiv 2412.11892).
|
|
124
|
+
- "From Drawings to Decisions" detect-then-read (YOLO-OBB + small VLM), arXiv 2506.17374.
|
|
125
|
+
- Image-tiling needs a global overview (arXiv 2512.11167); Claude vision limits (≤1568 px, images-before-text).
|
|
126
|
+
- AISC 303 Code of Standard Practice (drawings show size/grade/location + work points); steel-detailing read-order guides.
|
|
127
|
+
- Tooling: PyMuPDF, PaddleOCR/Surya, OpenCV/ELSED, ezdxf, IfcOpenShell.
|
package/dist/web/aware.js
CHANGED
|
@@ -2880,7 +2880,7 @@
|
|
|
2880
2880
|
}
|
|
2881
2881
|
|
|
2882
2882
|
// ── Workflow update (module-shaped) ─────────────────────────────────────────────
|
|
2883
|
-
// A FloLess-published workflow (e.g. steel-
|
|
2883
|
+
// A FloLess-published workflow (e.g. steel-model) has a newer bundled template. Poll GET
|
|
2884
2884
|
// /api/workflows/updates; when the OPEN app has one, show a pill → modal with the changelog →
|
|
2885
2885
|
// "Back up & update" POSTs /api/workflows/:id/update (backup → swap structure → re-bake the user's
|
|
2886
2886
|
// data from the contract store → recompile) → reload the app. No auto-update. `_wfUpdates` + the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* steel-3d-view.js — the 3D render/interaction layer for the steel-
|
|
2
|
+
* steel-3d-view.js — the 3D render/interaction layer for the steel-model editor's 3D mode.
|
|
3
3
|
*
|
|
4
4
|
* Three.js lives ONLY here (the rest of the editor is import-free). It renders the SAME scene the
|
|
5
5
|
* IFC/Tekla bake uses (fetched from /api/contract/:id/scene → contractToScene), so the editable 3D
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!doctype html><html><head><meta charset=utf-8>
|
|
2
|
-
<title>Steel
|
|
2
|
+
<title>Steel Model — editor</title>
|
|
3
3
|
<style>
|
|
4
4
|
:root{--bg:#0f172a;--panel:#1e293b;--line:#334155;--text:#e2e8f0;--mut:#94a3b8;--brand:#3b82f6}
|
|
5
5
|
/* Theme EVERY scrollbar — no native white default may leak (applies to the canvas, panels, and every modal list). */
|
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
<script type="module" src="./steel-3d-view.js"></script>
|
|
205
205
|
</head><body>
|
|
206
206
|
<header>
|
|
207
|
-
<b>Steel
|
|
207
|
+
<b>Steel Model</b>
|
|
208
208
|
<div id=viewToggle role=group aria-label="Canvas view"><button id=vt2d class="seg on" aria-pressed=true title="Plan view (2D overlay)">2D</button><button id=vt3d class=seg aria-pressed=false title="3D model view">3D</button></div>
|
|
209
209
|
<select id=planSel title="Switch plan view"></select>
|
|
210
210
|
<span class=stat>Members <b id=mc>0</b></span><span class=stat>Weight <b id=wt>0</b> tons · <b id=wtlb>0</b> lb</span>
|