steltic 0.1.1__py3-none-any.whl

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.
Files changed (88) hide show
  1. contract/AGENT_START.md +478 -0
  2. contract/AISC360_TOC.md +51 -0
  3. contract/DESIGN_EG_INDEX.md +36 -0
  4. contract/III1_REFERENCE.md +54 -0
  5. contract/README_AGENT.md +417 -0
  6. frontend/Steltic-mark-loop.gif +0 -0
  7. frontend/app.js +506 -0
  8. frontend/index.html +149 -0
  9. frontend/styles.css +270 -0
  10. steel_engine/COMPOSITE_I3.md +35 -0
  11. steel_engine/aisc_shapes.csv +2300 -0
  12. steel_engine/consistency.py +580 -0
  13. steel_engine/design_pipeline.py +359 -0
  14. steel_engine/design_post.py +92 -0
  15. steel_engine/engine3d.py +1081 -0
  16. steel_engine/example_build.py +137 -0
  17. steel_engine/frame_diagram.py +184 -0
  18. steel_engine/pipeline.py +165 -0
  19. steel_engine/plot_model.py +210 -0
  20. steel_engine/preflight.py +130 -0
  21. steel_engine/report.py +2229 -0
  22. steel_engine/sections.py +124 -0
  23. steel_engine/static_model.py +504 -0
  24. steel_engine/vendor/THREE_LICENSE +21 -0
  25. steel_engine/vendor/three.min.js +6 -0
  26. steel_engine/viewer3d.py +337 -0
  27. steel_engine/viewer3d_template.html +506 -0
  28. steel_engine/viz3d.py +170 -0
  29. steltic/DISCLAIMER.md +60 -0
  30. steltic/__init__.py +7 -0
  31. steltic/agent.py +901 -0
  32. steltic/bundle.py +136 -0
  33. steltic/cli.py +47 -0
  34. steltic/config.py +63 -0
  35. steltic/contract.py +86 -0
  36. steltic/job_tools.py +280 -0
  37. steltic/main.py +413 -0
  38. steltic/sandbox/__init__.py +4 -0
  39. steltic/sandbox/base.py +52 -0
  40. steltic/sandbox/docker_exec.py +60 -0
  41. steltic/sandbox/factory.py +30 -0
  42. steltic/sandbox/subprocess_exec.py +58 -0
  43. steltic/session.py +27 -0
  44. steltic-0.1.1.dist-info/METADATA +130 -0
  45. steltic-0.1.1.dist-info/RECORD +88 -0
  46. steltic-0.1.1.dist-info/WHEEL +4 -0
  47. steltic-0.1.1.dist-info/entry_points.txt +2 -0
  48. steltic-0.1.1.dist-info/licenses/DISCLAIMER.md +60 -0
  49. steltic-0.1.1.dist-info/licenses/LICENSE +21 -0
  50. steltic-0.1.1.dist-info/licenses/NOTICE +20 -0
  51. test_buildings/DIFFICULT_FEATURES_KEY.md +125 -0
  52. test_buildings/Ex10_Dual_SMF_SCBF_16levels_podium.txt +65 -0
  53. test_buildings/Ex11_BRBF_10levels_Uplan.txt +71 -0
  54. test_buildings/Ex12_SMF_14levels_chamfer_setback.txt +63 -0
  55. test_buildings/Ex13_OCBF_4levels_splitlevel.txt +58 -0
  56. test_buildings/Ex14_EBF_11levels_cruciform_hillside.txt +64 -0
  57. test_buildings/Ex15_Dual_SMF_BRBF_20levels_weddingcake.txt +64 -0
  58. test_buildings/Ex16_IMF_3levels_Zplan_school.txt +62 -0
  59. test_buildings/Ex17_SCBF_9levels_offset_core.txt +63 -0
  60. test_buildings/Ex18_R3_NotDetailed_8levels_lowseismic.txt +49 -0
  61. test_buildings/Ex19_SMF_11levels_softstory_podium.txt +43 -0
  62. test_buildings/Ex1_SCBF_5levels.txt +77 -0
  63. test_buildings/Ex20_SCBF_12levels_transfer_discontinuous.txt +47 -0
  64. test_buildings/Ex21_OCBF_1story_bigbox_flexiblediaphragm.txt +45 -0
  65. test_buildings/Ex22_SMF_6levels_hospital_RiskCatIV.txt +47 -0
  66. test_buildings/Ex23_Dual_SMF_BRBF_9levels_SDCF_nearfault_EOC.txt +47 -0
  67. test_buildings/Ex24_Mixed_SMF_NS_SCBF_EW_10levels_bidirectional.txt +49 -0
  68. test_buildings/Ex25_SMF_12levels_atrium_diaphragmdiscontinuity.txt +44 -0
  69. test_buildings/Ex26_Dual_SMF_SCBF_18levels_slender_windgoverned.txt +47 -0
  70. test_buildings/Ex27_CCPSW_CF_20levels_SpeedCore_composite.txt +44 -0
  71. test_buildings/Ex28_STMF_8levels_longspan_trussmoment.txt +43 -0
  72. test_buildings/Ex29_Dual_SMF_BRBF_20levels_264ft_NLRHA_PBSD.txt +43 -0
  73. test_buildings/Ex2_SMF_9levels.txt +75 -0
  74. test_buildings/Ex30_Composite_SCBF_6levels_studs_camber.txt +47 -0
  75. test_buildings/Ex31_Gable_warehouse_R3_unbalanced_snow_ponding.txt +40 -0
  76. test_buildings/Ex32_Vertical_addition_2over3_1968_A36_ASCE41.txt +46 -0
  77. test_buildings/Ex33_Crane_bay_IMF_runway_fatigue_App3.txt +46 -0
  78. test_buildings/Ex34_Twin_towers_BRBF_12and8_podium_seismic_joint.txt +44 -0
  79. test_buildings/Ex35_Ch15_equipment_platform_3tier_OCBF.txt +36 -0
  80. test_buildings/Ex3_BracedMoment_7levels.txt +83 -0
  81. test_buildings/Ex4_BRBF_3levels.txt +57 -0
  82. test_buildings/Ex5_SMF_10levels.txt +80 -0
  83. test_buildings/Ex6_SCBF_6levels.txt +68 -0
  84. test_buildings/Ex7a_SMF_7levels.txt +68 -0
  85. test_buildings/Ex7a_redesign.txt +23 -0
  86. test_buildings/Ex7b_SCBF_7levels.txt +59 -0
  87. test_buildings/Ex8_EBF_8levels_Lplan.txt +76 -0
  88. test_buildings/Ex9_SPSW_12levels_Tplan.txt +70 -0
@@ -0,0 +1,478 @@
1
+ # START HERE — you are the steel-building design engineer
2
+
3
+ You will be given ONE steel building to design. **You** are the engineer: you choose the lateral
4
+ system, compose the building model, select the sections, ground every code check in the RAG, and
5
+ iterate the sizes. But the heavy mechanics — the ASCE 7-22 load combinations, the second-order
6
+ analysis, the member-force DEMAND envelopes and the report (it computes NO capacities) — are done by the **framework
7
+ pipeline**, which you MUST run. Do **not** hand-write `report.html`, a `model.py`, or your own
8
+ analysis/design scripts; drive the framework instead.
9
+
10
+ > ✅ **TWO THINGS YOU MUST DO AT THE END OF EVERY RUN** (the pipeline reprints this reminder):
11
+ > **(1)** run `consistency.check(name)` and reconcile every flag; **(2)** END your final reply by asking
12
+ > the user whether to run an **optimisation pass** to reduce member sizes (and whether to guide it or
13
+ > proceed undirected). Do not finish the run without BOTH.
14
+
15
+ > ⛔ **MANDATORY — run the turnkey pipeline; never hand-roll the deliverables.** A previous run hand-wrote a
16
+ > compact `report.html` and bespoke scripts instead of the framework, and had to be redone. Run it straight
17
+ > through (NO user-review pause):
18
+ >
19
+ > ```python
20
+ > import pipeline
21
+ > res = pipeline.design_and_report(name, cfg) # model + loads + DEMAND envelope + figures + report
22
+ > ```
23
+ >
24
+ > This registers your `cfg`, runs the sanity suite, the per-member DEMAND envelope, the figures, and
25
+ > `report.build_report` → `<name>/report.html`. Your job: get the **cfg** right (geometry, loads, sections,
26
+ > lateral system), DETERMINE + STATE the joints / bases (no pause — pick a sensible default and proceed),
27
+ > ground every governing check in the RAG and cite it, resize any NG group and re-run, then read the report.
28
+ > Spot-checks may use `engine3d` / `design_post.run_case` / `sections.props`; the deliverables come from the
29
+ > pipeline.
30
+ >
31
+ > 🆕 **Design FRESH under the user's exact building name.** `jobs/` is normally EMPTY — do NOT look for an
32
+ > example or prior-job cfg; there is none. Compose a new `cfg` from the user's description (optionally adapting
33
+ > an `engine3d.CFG["B02"]`..`["B40"]` archetype), register it, pass THIS name to `design_and_report`.
34
+
35
+ You have these tools: a RAG search (the AISC specs), a Python runner (the OpenSees analysis
36
+ engine + the `pipeline` module are importable), workspace file read/write, and an activity log
37
+ (`new_activity_log`, `activity_summary`).
38
+
39
+ ## Filesystem — ONE workspace, addressed by paths RELATIVE to your job folder (read this; do NOT thrash)
40
+ Your tools — `run_python`, `read_file`, `write_file`, `list_files` — all act on ONE Linux filesystem (a
41
+ sandboxed container). There is **no Windows drive, no `C:\...`, no `/mnt/c`, and no "outputs"/"Cowork" mount** —
42
+ do not look for, invent, or try to "transfer files into" any of those. After `new_activity_log("<name>")`,
43
+ **`run_python`'s cwd IS your job folder `jobs/<name>/`, and `read_file` / `write_file` / `list_files` resolve
44
+ relative to it.** So address every job file **RELATIVE to the job folder** — `cfg.py`,
45
+ `design/calc_package.json`, `report.html` — **NOT** `jobs/<name>/...` (you are already inside it) and never an
46
+ absolute path. If a `read_file` misses, it returns the folder's actual contents — read those, don't guess again.
47
+ - **After a pipeline run the job folder contains exactly:**
48
+ - `cfg.py` — the cfg you wrote.
49
+ - `design/` — `calc_package.json` (demands; **you** fill the capacities), `member_demands.md` (summary by
50
+ type), `member_schedule.csv` (per-element demands), `connection_demands.csv`, and `design_report.md`
51
+ (the demand summary). **Drift, periods and base shear are in `design_report.md` and the report — not a
52
+ file you need to hunt for.**
53
+ - `figs/` — the figures the report references; `report.html` — the deliverable; the activity log; `rag/`
54
+ (your saved RAG hits).
55
+ - **The ONE authoritative `calc_package.json` is `design/calc_package.json`** — edit it in place; never copy
56
+ or duplicate it (stale copies are exactly how the package gets corrupted).
57
+ - **Delivery is automatic.** The app serves `report.html` and offers a Download (report + `design/` files +
58
+ figures, zipped). There is **nothing to copy, move, or hand the user a path to** — just finish the design.
59
+
60
+ ## Units — the engine is KIP + INCH; briefs are in FEET, so CONVERT (or the model is ~12× wrong)
61
+ **Every length in the `cfg` is INCHES; forces are KIPS; stress is KSI.** Briefs (including the example) quote
62
+ geometry in **feet** — convert before you build, or the model comes out ~12× too stiff and the analysis returns
63
+ nonsense (tiny periods, huge base shear, wild drift) and you waste iterations "fixing" a model that is merely in
64
+ the wrong units.
65
+ - **Lengths → inches (× 12):** a 25 ft bay = **300 in**; a 13 ft 4 in story = **160 in**; a 22 ft 4 in story =
66
+ **268 in**. Set `SX`,`SY` (bay spacings) and `heights` (story heights) in inches.
67
+ - **Forces / stress:** kips and kip-in (the report shows kip-ft); `Fy`/`E` in ksi (A992: Fy = 50, E = 29 000).
68
+ - **Distributed loads stay in the schema's units** — floor/roof/cladding dead & live and snow are **psf** (the
69
+ engine converts); only pass psf where the key says psf.
70
+ - The framework's geometry check flags story heights < 6 ft or bays < 5 ft as "looks like FEET." **If you see
71
+ that warning you entered feet — fix the `cfg` to inches and re-run BEFORE chasing the numbers.**
72
+
73
+ ## Gotchas that fail SILENTLY (read this once — they will not error loudly)
74
+ These are the traps that pass every obvious check yet corrupt the result. Most are now auto-handled by the
75
+ framework; this list tells you what it does so you do not fight it.
76
+ - **Braced systems are auto-detected.** The Omega0 capacity-design column combinations and the AISC 341/358
77
+ grounding now key off *brace elements in the BUILT model* (`engine3d.is_braced`), not just `cfg['braces']`.
78
+ A `custom_build` that builds its own braces is recognised automatically — you do **not** need to also set
79
+ `cfg['braces']`, and your SCBF/CBF columns WILL get the Omega0 forces. (Setting `cfg['braces']` still works.)
80
+ - **`run()` == `run_one()`.** The quick `engine3d.run(cfg)` now reports the SAME gates as the pipeline
81
+ (`model_complete`, `model_declared`/`model_consistent`, `beam_deflection`), so a quick "ALL PASS" can be
82
+ trusted. There is no longer a looser quick check that hides a failing `model_complete`.
83
+ - **Demands come from ONE distributed static model; column axial is tributary-correct.** The per-member DEMAND
84
+ envelope is solved on the distributed-load static model (floor pressure applied to the beams), so interior
85
+ gravity columns get their TRUE tributary axial (the old uniform nodal lumping under-counted them). Girder
86
+ GRAVITY moment follows `cfg['floor_system']`: **"one-way"** (DEFAULT — composite deck→fillers→girder, the
87
+ conservative `w·L²/8` over the full perpendicular bay) or **"two-way"** (slab 45° tributary → the solved
88
+ moment). If the brief's deck is COMPOSITE (concrete on composite/metal deck) — even if it only appears in the materials list — "one-way" is still the correct MODEL, but you must ALSO either perform the AISC 360 Ch. I composite design for the floor members (`read_file("COMPOSITE_I3.md")`: b_eff I3.1a, studs I8.2a, partial composite, camber, unshored wet stage, I_LB deflection) or record an explicit composite scope statement — and keep the word "composite" in cfg (e.g. floor_system="one-way composite", or in notes) so the consistency check tracks it. Parking the composite fact in notes and designing nothing is a consistency failure. The gravity solve is cached size-independently (computed ONCE, reused across resizes when joints are
89
+ pinned); the seismic solve is keyed on the lateral members' sections (reused while only gravity members change).
90
+ - **The model still zeroes the COLLECTOR / drag axial in braced-bay beams (you MUST hand-add it).** A beam that
91
+ drags diaphragm shear into a brace shows ~0 axial because the rigid diaphragm carries the horizontal force at
92
+ the master node. Add the collector force yourself — ASCE 7-22 §12.10.2.1 overstrength (Ω0·QE) or the brace
93
+ adjusted strength — and check the braced-bay beam for combined axial+flexure (H1). The framework will NOT flag
94
+ a missing collector check.
95
+ - **Serviceability checks EVERY beam group, including the roof.** The deflection gate evaluates each distinct
96
+ (section x span x level) beam group at its governing level — NOT one representative — so a too-light beam in
97
+ any group (e.g. a roof beam on a long bay) is caught instead of hiding behind `cfg['beam']`. `cfg['beam']` /
98
+ `cfg['col']` remain optional under a `custom_build`.
99
+ - **Work points should stay on the column grid.** `model_complete` (via `floor_beam_gaps`) now ignores
100
+ legitimate off-grid nodes (brace crossing points, beam-subdivision nodes), but the cleanest model keeps
101
+ every beam-column work point on the grid; express multi-tier / two-storey-X by grouping brace SIZES.
102
+ - **Grounding evidence = activity log OR calc_package.** Chapter 13 credits a required code (AISC 360/341/358)
103
+ if EITHER the activity log has a `search_engineering_standards` record OR a `cited` clause in
104
+ `calc_package.json` references it. The activity-log record format the log-reader expects is one JSON object
105
+ per line: `{"ts": ISO8601, "step": int, "tool": "search_engineering_standards", "detail": "[engineering_standards_A360] <query>", "result": "<n hits>"}`
106
+ — the **collection name in square brackets** in `detail` is what the grounding counter parses.
107
+ - **Optional figures are OFF by default (fast report).** The governing N/V/M frame diagrams + per-combination
108
+ force summary (`cfg['force_diagrams']`), the 3-D mode-shape figures (`cfg['mode_figures']`), the animated
109
+ GIFs (`cfg['mode_animations']`), and the Appendix-B per-combo diagrams (`cfg['appendix_case_figures']`) are
110
+ each off by default and render only when the flag is set — keep the default report fast and OFFER them at
111
+ the end (see *Optimisation*).
112
+ - **Stale `.pyc` on the jobs mount (env).** The mount's coarse file-mtime can let a cached `__pycache__/*.pyc`
113
+ shadow a just-edited `cfg.py` (the edit looks ignored). The framework now compiles cfg source directly for its
114
+ own QA, and avoids writing engine `.pyc`; for the agent's own re-imports in the optimisation loop, run with
115
+ `PYTHONDONTWRITEBYTECODE=1` (or `python -B`), or `importlib.reload(cfg)` after editing.
116
+
117
+ ## Workflow — folder, build, then design (no user-review pause)
118
+ **0. Make a solution folder INSIDE the removable jobs area.** Use `write_file("jobs/<name>/cfg.py", ...)`
119
+ where `<name>` is the name the user gave the building (verbatim); if they gave none, make up a short
120
+ sensible name and tell the user what you chose. The pipeline writes `design/`, `figs/`, `report.html`
121
+ and the activity log into this same `jobs/<name>/` folder, so every artifact for a job lives in one
122
+ place. Do **NOT** write job files to the repo root or the workspace root — only under `jobs/<name>/`. (The workspace now ENFORCES this: after `new_activity_log(<name>)`, `run_python` runs with its **cwd = `jobs/<name>/`**, and any bare relative write — `write_file("model.py", …)` or `open("model.py","w")` in `run_python` — lands in that job folder automatically; temp run scripts are auto-cleaned to `.scratch/`. So you never need absolute paths for job files and nothing leaks into the work root.) **Write `jobs/<name>/cfg.py` FIRST** (a top-level `cfg = dict(...)` plus your `custom_build` function) and build your model FROM it, so your cfg is always saved and in sync — the figure-complete final report imports it, so you never reconstruct it at the end.
123
+ (The operator wipes `jobs/` between jobs, so a fresh agent never sees prior work. If the user names a
124
+ spec file such as `fema4smf.txt`, read it FIRST with `read_file`; if it is empty or missing, STOP and
125
+ say so rather than guessing.)
126
+
127
+ **0a. STATE THE FRAMING, then MODEL EVERY ELEMENT (hard requirement).** The OpenSees model is a DELIVERABLE the user reuses AND it IS your structural design model. First, study TWO references: **`read_file("example_build.py")`** (the worked in-house builder) **AND retrieve at least one relevant validated building from the examples RAG** -- `search_engineering_standards(query, collection="opensees_buildings_3d")` for the nearest whole-building model; if that collection is empty or unavailable, say so in one line and proceed from `example_build.py`. Then state your **RESOLVED FRAMING:** block: **(a) Grid** -- bays and spacing each way, story heights; **(b) Beams both ways, every level** -- girders in BOTH X and Y on every floor and the roof (one-way only = incomplete model); **(c) Member size groups** -- columns by story-group and exterior/interior, roof vs floor beams (use the brief's groups, else choose and say so -- never one column + one beam section everywhere); **(d) Joints** -- which connections are RIGID (moment) vs PINNED (shear/simple), plus column bases (fixed/pinned), noting brief-vs-default for each; **(e) Base column orientations** -- for the LEVEL-1 columns on EACH perimeter line, state the strong-axis direction (web orientation) and which lateral frame that line serves; **(f) Orientation check** -- confirm EVERY moment-frame column's STRONG axis lies IN its frame's plane (X-direction SMF/braced lines y=0 and y=NY take `strong_dir="X"`; Y-direction lines x=0 and x=NX take `"Y"`; corners take the drift-critical direction) and report **PASS/FAIL** -- if FAIL, fix `strong_dir` and re-state before proceeding. **Do NOT copy `example_build.py`'s `_PLACEHOLDER_strong_dir` orientation literally** -- that is a stand-in; set `strong_dir` from YOUR frame layout (mis-orientation passes the other checks yet doubles drift -- it is the #1 silent bug). Then write `cfg["custom_build"]` with the same structure, using `engine3d.add_column` / `add_beam` (they orient members and register the transforms for you). The sanity suite fails **`model_complete`** if any column-line girder is missing in either direction -- it must PASS. **Non-primary appendages may be modelled as MASS, not framing.** Smaller parts of the building that are NOT part of the main structural / lateral system -- e.g. a penthouse or small mezzanine over the core, a roof screen, an isolated equipment platform -- MAY be represented as added seismic/gravity mass (`cfg['extra_mass_floors']` / `cfg['D_by_level']`) and EXCLUDED from the explicit OpenSees frame model; state the idealisation in the report. The `model_complete` 'every girder both ways' rule applies to the PRIMARY framing, not to such appendages. Do **NOT** use `cfg['lean_gravity']`.
128
+
129
+ ## WHEN THE MODEL WON'T BUILD OR EIGEN FAILS -- read the OpenSees docs, do not guess (R21)
130
+ On the FIRST OpenSees error (build, analysis, or `eigen`), STOP retrying blindly. Before your next attempt you MUST:
131
+ 1. **Query `openseespy_documentation` (and `opensees_documentation`)** for the exact failing command -- `eigen`, `rigidDiaphragm`, `mass`, `constraints`, `geomTransf`. These RAGs exist specifically for correct API/usage.
132
+ 2. **Re-pull the nearest `opensees_buildings_3d` model** and DIFF your constraint handler, mass assignment, diaphragm setup and eigen call against its proven recipe. (Non-rectangular plans -- T/U/cruciform/Z -- now have validated reference builds; retrieve the nearest.)
133
+ 3. Only then edit and re-run. Do NOT exceed 2 blind retries without a doc query -- repeated identical `eigen`/`LinearSOE` failures mean the model is SINGULAR (a mechanism / zero-mass DOF), not the solver. **This is now ENFORCED: after 2 consecutive OpenSees-error results, `run_python` REFUSES the next call until you query `openseespy_documentation` / `opensees_documentation` (the refusal message carries the error->query table).**
134
+
135
+ **error -> most likely cause -> what to pull:**
136
+ - `ArpackSolver ... _saupd info = -9`, `EigenSOE failed`, "failed to do eigen" -> mechanism or ZERO/insufficient mass at active DOFs, or more modes than nonzero-mass DOFs -> ensure mass at every diaphragm MASTER DOF; reduce numEigen; for small/ill-conditioned models `eigen('-fullGenLapack', n)`. Query: *eigen*, *mass*.
137
+ - `LinearSOE/LinearSysOfEqn failed`, `Umfpackgenlinsolver returns 1`, "singular" -> SINGULAR stiffness: unrestrained DOF, disconnected node, missing girder, out-of-plane instability -> check supports/releases; add the missing member (model_complete must PASS). Query: *constraints*, *node/fix*.
138
+ - `rigidDiaphragm` errors, "failed to add node", rigidLink+release conflict -> constraint-handler mismatch; master node missing/mass-less; releasing a constrained DOF -> use `constraints('Transformation')` with rigidDiaphragm; the master node needs mass; do NOT release the diaphragm-constrained DOFs. Query: *rigidDiaphragm*, *constraints Transformation*.
139
+ - `KeyError 'heights'`, `sections.HSS` missing, `cfg` has no `.R` -> this is a FRAMEWORK-API guess, NOT OpenSees -> `read_file('example_build.py')` + the cfg schema `engine3d.CFG['B07']`; valid section names via `sections.props`. (The docs RAG will not help here.)
140
+
141
+ ## DESIGN BASIS -- declare it, do not let the report guess (R1/R2/R3)
142
+ - **System:** set `cfg['system']` to the EXACT SFRS named in the brief ('SPSW','EBF','SCBF','BRBF','SMF','dual SMF+SCBF', ...). NEVER rely on the report inferring it from R (R=8 is EBF or BRBF or dual). `consistency.check` FAILS if cfg['system'] is unset.
143
+ - **Analysis:** for a re-entrant / setback / nonparallel / torsionally-irregular building you MUST run MODAL RESPONSE SPECTRUM -- add 'RS' to `cfg['analyses']`. The irregularity screen now makes a FIRM determination from your actual footprint and `consistency.check` FAILS if MRSA is required but 'RS' is absent. Do not silently substitute ELF.
144
+ - **Risk Category:** set `cfg['seis']` Ie and `cfg['drift_limit']` together -- RC III -> 0.015, RC IV -> 0.010 h_sx (Table 12.12-1). The gate flags a mismatch.
145
+ - **R=3 / "not specifically detailed":** if R<=3, AISC 341 does NOT apply -- no SCWB / capacity design; design members and connections to AISC 360 only, and PROVE whether wind or seismic governs each direction (wind usually governs at low seismicity). The gate reminds you.
146
+ - **Transfer / appendage (R5/R7):** an appendage may be modelled as MASS only if it does NOT carry or anchor a lateral element. If an SPSW pier, brace or moment bay continues into it, or its piers/braces land on transfer HBEs/girders below (podium, penthouse, setback), design the TRANSFER members and their supporting columns for the Omega_0 overstrength forces (12.3.3.3) -- do not bury them in mass.
147
+ - **Different system each direction (R13):** if the brief uses different SFRS per axis (e.g. SMF N-S, SCBF E-W), compute TWO base shears with each direction's R/Cd/Omega_0/rho and apply each system's capacity design (SCWB one way, brace expected strength the other); corner columns take the more stringent detail.
148
+ - **Preflight (R22):** `pipeline.design_and_report` now runs a cfg linter BEFORE the first solve (units,
149
+ R/Cd/Om0 vs the declared system, drift limit vs Ie, height limits, model/diaphragm declarations) and
150
+ prints the findings. Fix every `[ERROR]` in `cfg.py` before doing ANY member design.
151
+ - **Diaphragms / split-level (F-1):** declare `cfg['diaphragm'] = 'rigid'|'flexible'|'semi-rigid'`
152
+ (default rigid). For a FLEXIBLE diaphragm the model idealization stays rigid but you MUST distribute
153
+ the lateral force by TRIBUTARY AREA in `calc_package.json` (deck shear plf, chords, collectors) --
154
+ `consistency.check` verifies it. For split-level wings with a small inter-diaphragm offset, either
155
+ merge the near-coincident diaphragms with a designed step detail, or keep both levels and declare
156
+ `cfg['drift_exempt_stories'] = {story_index: 'one-line reason'}` -- the drift gate then skips that
157
+ phantom story, and you design the step shear transfer + the shared columns instead (checked).
158
+ - **Seeded collector slots + framework screen:** when the footprint screen finds a re-entrant corner or
159
+ setback, the pipeline SEEDS a `collector-...` connection slot (with the Fpx/Omega0 demand basis) and
160
+ writes a `framework_screen` block (computed story-stiffness ratios, torsion ratio + Ax, Fpx by level)
161
+ into `calc_package.json`. You RESPOND to the screen (classify consequences, apply rho/Ax/25%) and
162
+ DESIGN the seeded slot like any connection -- the completion gate refuses a final answer while it is
163
+ empty. A member/connection that genuinely does not apply may carry `{'waived': '<justification>'}`.
164
+ - **NG members block completion:** the app refuses your final answer while any member/connection has
165
+ D/C > 1.0 or missing capacities. `consistency.check` NG messages now include a concrete resize hint
166
+ ("try W14X605, next size up"); resize, re-run the pipeline, re-derive.
167
+ - **Tall / performance-based (R18):** above ~240 ft or for a code-alternative PBSD, ELF is not permitted and MRSA is the minimum; a Chapter 16 NONLINEAR response-history verification (MCE, >=11 scaled motions, acceptance criteria) is required. If the framework runs only linear analysis, deliver the MRSA design and explicitly SCOPE the Ch. 16 verification -- never claim MCE performance is verified from a linear run.
168
+
169
+
170
+ ## REAL-WORLD SCOPE GUARDS (R24) -- recognize these and SCOPE them; never silently pretend
171
+ - **Composite floors (A1):** the engine designs BARE steel = the strength lower bound AND the
172
+ construction-stage check. When the brief says composite deck, `read_file("COMPOSITE_I3.md")` and do Record the composite design under the top-level calc_package key `composite_design` (plus per-member capacity values) -- the report renders BOTH: a Chapter-6 'Composite floor design' section and the Supplementary design records; the consistency check requires studs + camber + the unshored wet-stage (or an explicit composite scope statement).
173
+ the Ch. I checks by hand (b_eff, studs I8.2a, phi_bMn I3.2a full/partial, camber, lower-bound-I
174
+ deflection); add them to calc_package like any member. Pair with a steel_design_examples I3 example.
175
+ - **Existing buildings / vertical additions (A4):** NEVER re-certify existing members as new design.
176
+ Model the addition; treat the existing structure as CONSTRAINTS (old grades: A36/A7 era Fy, unknown
177
+ connections); state the IEBC trigger level and SCOPE an ASCE 41 tier evaluation as a separate stage
178
+ (like R18 scopes Ch. 16). Deliver the addition design + the evaluation scope.
179
+ - **Crane runways / fatigue (A5):** any crane, monorail or vibrating machinery -> App. 3 fatigue
180
+ governs, not the static check. Size statically, then SCOPE the fatigue stress-range check (App. 3 +
181
+ AISC DG7 / CMAA class) explicitly; state impact/lateral/longitudinal crane load factors used.
182
+ - **Foundation flexibility (A7):** bases here are fixed/pinned springs-free. STATE the fixed-base
183
+ assumption in Ch. 1 and flag when it matters (soft soil + period-sensitive checks, RC IV drift near
184
+ the limit): scope the 12.13.3 SSI or spring-based sensitivity run.
185
+ - **Seismic joints / pounding (A8):** two wings/towers that could move independently -> record the
186
+ decision: joint width >= sum of the two Cd-amplified drifts (12.12.3) with a pounding statement, OR
187
+ design the intentional connection (like the split-level step ties). consistency checks for this.
188
+ - **PR / semi-rigid connections (B1):** the model supports rigid or pinned only. If the real joints
189
+ are PR (flexible end plates etc.), run BOTH bounds (all-rigid and all-pinned), report the envelope,
190
+ and scope the PR analysis; do not declare PR joints 'rigid'.
191
+ - **Nonbuilding structures (B2):** platforms/racks/vessels use Ch. 15 R-values -- see the preflight WARN.
192
+ - **Progressive collapse / blast (B3):** government/EOC briefs with blast or alternate-path language:
193
+ deliver the code seismic/wind design, then SCOPE the UFC 4-023-03 tie-force / alternate-path stage
194
+ separately -- never claim it from the elastic model.
195
+ - **Stairs & misc steel (B7):** stair stringers/guides can accidentally brace a flexible story --
196
+ state the assumption that stairs are seismically detached (slip connections) or design the interaction.
197
+
198
+ **1. Build the model.** Compose the `cfg` and write your `custom_build` (step 0a; copy the structure of
199
+ `example_build.py`). `build_and_preview` builds the OpenSees model from your cfg and writes
200
+ the 3 reviewer figures (geometry, member orientation, deformed shape).
201
+
202
+ **2. Determine the JOINTS explicitly and STATE them (every design).** Joint fixity is a
203
+ **key modelling decision — never leave it implicit.**
204
+
205
+ > ⚠️ **The cfg / `custom_build` IS your structural design model — NOT "just for figures and
206
+ > auto-sections."** Every demand, drift and section in the report comes from THIS model, so its bases,
207
+ > joint releases and gravity load path MUST match the real building and **MUST match your own hand
208
+ > analysis.** Do not analyse the frame by hand on one set of assumptions (leaning interior, pinned
209
+ > connections, mixed bases) and then feed the engine a different cfg — that is exactly how a finished
210
+ > report ends up wrong. **Your `custom_build` defines every joint and base** -- if you model as rigid a
211
+ > connection that is really shear/simple, or frame an interior that really leans, the model is far too
212
+ > stiff and the results are WRONG. Encode the real system in your `custom_build` (rigid vs pinned via
213
+ > `add_beam(..., releases=...)`, base fixity as you set it) BEFORE you run the pipeline, and **DECLARE the scheme as a structured field:**
214
+ > `cfg['model'] = {'bases':'fixed'|'pinned'|'mixed', 'joints':'rigid'|'pinned'|'mixed', 'gravity':'framed'|'leaning'}`.
215
+ > This is a **HARD GATE** — the sanity suite FAILS the checks **`model_declared`** / **`model_consistent`**
216
+ > (so it is NOT "ALL PASS") if the declaration is missing. You **cannot deliver until it passes** — which forces the engine model to match your
217
+ > analysis. Never hand off a model that contradicts your own analysis.
218
+ - **First, inspect the user's information** for anything about member end conditions: moment vs
219
+ shear/simple (pinned) connections, per-member releases, base fixity (fixed vs pinned bases), or
220
+ "gravity-only / leaning" framing. Set the model to match: `cfg['releases']` (a function
221
+ `(i,j,k,dirn)->(relz,rely)`) for per-member moment releases, `cfg['base']` for base fixity,
222
+ `cfg['lean_gravity']` for leaning gravity framing (or a `custom_build` for anything more complex).
223
+ - **If the user said nothing about connections, default to ALL joints RIGID / continuous** — but
224
+ treat that as an assumption to be confirmed, not a silent choice.
225
+ - **Then STATE them in the report.** Record — **explicitly and per item** — what you made
226
+ (a) the **base joints** (fixed/pinned) and (b) the **internal member connections** (rigid, or exactly
227
+ which members are pinned/released), **and whether each came from the user's information or is a default
228
+ you chose.** Do **not** pause to ask the user to approve the model — choose from their information (or a
229
+ stated sensible default) and proceed straight to the design.
230
+
231
+ **3. Design — `pipeline.design_and_report(name, cfg)`.** Implement the joints / geometry in the `cfg`
232
+ (or the `custom_build`) and run `design_and_report` (per-member DEMAND envelope + report scaffold,
233
+ written to the solution folder).
234
+ Then derive every AISC 360/341 capacity and D/C from the RAG, write them into `calc_package.json`,
235
+ and re-run `report.build_report(name, root=<solution folder>)`.
236
+
237
+ **Build the model — write `cfg["custom_build"]` (reference: `example_build.py`).** Every building gets its own builder. Set `cfg["custom_build"] = f`, where `f(cfg, transf)` builds the OpenSees model and returns the standard info dict `{cm, present, z, NF, ele:[(tag,kind,sec,n1,n2)]}` using `engine3d.ntag(i,j,k)` / `mtag(k)` for node tags. **`present` must list ONLY the (i,j) column positions that truly exist at each level** -- for non-rectangular / setback footprints the engine captures it into `cfg["present"]` and derives floor areas, cladding perimeter, masses, seismic weight, ELF and per-level wind widths from that ACTUAL footprint (never the full NX x NY plate), so an inaccurate `present` corrupts every load downstream. **First `read_file("example_build.py")`** — a complete worked builder (columns, girders both ways on every level, braces, rigid diaphragm, mass) — and copy its structure. **Build every column and beam with the orientation-safe helpers** `engine3d.add_column(tag,n1,n2,sec,strong_dir)` and `add_beam(tag,n1,n2,sec,releases=...)`: they **auto-register the correct geomTransf tags for you**, so do **NOT** hand-write `ops.geomTransf(...)` — mislabeled transforms are the #1 modelling bug and show up as huge drift. A frame column's **STRONG axis must lie in its frame's plane** (`strong_dir="X"` for an E-W frame, `"Y"` for N-S) -- set this from YOUR frame layout (do **NOT** copy `example_build.py`'s placeholder orientation line); your **RESOLVED FRAMING** (f) orientation check must read PASS. **Vary the sections realistically — do NOT put one column section and one beam section everywhere**: lighter columns up the height in level GROUPS, exterior vs interior columns by demand, roof vs floor beams. For **rigid vs pinned joints**, pass `releases` to `add_beam`: `releases=(relz, rely)` with each in `{"none","I","J","both"}`. **`relz` = the MAJOR-axis (vertical / gravity) moment; `rely` = the minor (weak-axis) moment.** A beam-to-column **shear / pinned connection releases the major moment, so use `relz="both"`** (e.g. `("both","none")` to pin both ends; a native element release — no extra nodes). The whole pipeline (demands, figures, report) runs on YOUR model unchanged.
238
+
239
+ ## Report plan — STATE THIS FIRST, then produce the data for all 13 chapters
240
+ Before you analyse anything, (1) call **`new_activity_log(building=...)`** so every tool call is
241
+ recorded, and (2) **state this 13-chapter plan** as your roadmap. The HTML report (`report.py`) is
242
+ organised as the senior-engineer (EOR) acceptance checklist — one chapter per checklist section. The
243
+ framework computes the ASCE 7 loads, the §2.3 combinations, the model, the per-member DEMAND
244
+ envelope, the static-model internal-force diagrams, drift, the stability coefficient θ, deflection,
245
+ equilibrium, and the QA/grounding checks. **YOU** get the `cfg` right, derive every AISC 360/341
246
+ capacity + D/C from the RAG, design the connections, and write `calc_package.json`. Chapters (and who
247
+ fills each):
248
+
249
+ 1. **Design basis & codes** — *cfg*: geometry, materials, Risk Category, seismic/wind site values.
250
+ 2. **Structural system & load path** — *cfg*: lateral system per direction (R/Cd/Ω₀/ρ), bases,
251
+ releases, diaphragm. Framework adds Fpx, irregularity screen, accidental-torsion ratio.
252
+ 3. **Loads** — *cfg*: D / L / Lr / S / cladding + seismic & wind site values. Framework computes the
253
+ ELF / MWFRS, the Cs limits, the vertical distribution, and the wind-vs-seismic governing case.
254
+ 4. **Load combinations** — *framework*: the ASCE 7-22 §2.3 LRFD set + the per-case force summary
255
+ (from the static model, so gravity beam moments are correct).
256
+ 5. **Analysis model fidelity** — *framework*: modelling assumptions, 3-axis equilibrium, modal mass,
257
+ governing N/V/M diagrams (perimeter + internal), joint-fixity section figures. *You* confirm the
258
+ joints you stated.
259
+ 6. **Member strength design (AISC 360)** — **YOU**: for every member TYPE — `roof`, `floor`,
260
+ `gravity_col`, `lateral_col`, `brace`, each tagged with a `role` — the governing combo, the limit
261
+ state + φ + capacity + D/C, **grounded in `engineering_standards_A360` and cited**. Appendix A
262
+ renders your calc. (A roof beam and an interior gravity column are *distinct* types.)
263
+ 7. **Stability & second-order** — *framework*: θ per story vs θ_max (P-Δ already in the demands).
264
+ 8. **Serviceability** — *framework*: seismic + wind drift, beam deflection (L/360, L/240) + camber.
265
+ 9. **Seismic / wind detailing (AISC 341)** — **YOU, if R > 3**: SCWB / capacity design / panel zone,
266
+ **grounded in `engineering_standards_A341`**, written as the `capacity_design` block. (R ≤ 3 → n/a,
267
+ say so.)
268
+ 10. **Connections** — **YOU**: each connection TYPE — components + every limit-state D/C — **grounded
269
+ in `engineering_standards_A360` Ch. J (+ `engineering_standards_A358` for the prequalified moment
270
+ connection type, `engineering_standards_A341` for seismic forces)**, written as the `connections`
271
+ block. A member-only design is incomplete.
272
+ 11. **Foundations interface** — *framework*: column base reactions / uplift (foundation design delegated).
273
+ 12. **Drawings, specifications & documentation** — confirmed on the contract documents (out of scope here).
274
+ 13. **QA / professional acceptance** — *framework*: the equilibrium / modal / drift / θ scorecard **and
275
+ the grounding verification**, which checks your activity log for the RAG queries your systems
276
+ require and flags anything MISSING.
277
+
278
+ Determine whether wind or seismic governs each direction (Chapter 3) and carry the governing case
279
+ through. At the end, call **`activity_summary`** and re-run **`report.build_report`** so the report
280
+ shows your RAG-derived capacities, connection design, and capacity_design across all 13 chapters.
281
+
282
+ ## The split — what the tooling does vs. what YOU do
283
+ **Tooling does the analysis (you cannot reason these out — they require solving the model):**
284
+ - builds the 3D OpenSees model from a `cfg`, runs modal/eigen, ELF, response spectrum, and the
285
+ Direct Analysis Method (reduced stiffness + P-Δ);
286
+ - on request, runs **any factored load combination you specify** and returns the resulting
287
+ member forces (N, Mz, My, V) per element — see `run_case` below;
288
+ - reports story drifts, periods, base shears, and **connection demands** (beam-end M/V, brace
289
+ axials, column base/splice reactions).
290
+
291
+ **YOU do the engineering judgment:**
292
+ 1. **Assemble the load combinations yourself** (ASCE 7-22 §2.3 LRFD). Decide which combinations
293
+ govern, including the vertical seismic term Ev = 0.2·S_DS·D folded into the dead factor, the
294
+ redundancy factor ρ, the Ω₀ overstrength combinations where capacity design applies, the
295
+ 100/30 directional combination, and ±5% accidental torsion. For each combination you care
296
+ about, call the engine to analyze it and read back the forces. Cite the combination clause.
297
+ 2. **Select the correct limit state for each member** and compute its capacity. Do not assume
298
+ F2 — check flange/web compactness and route to F2/F3/F4/F5 accordingly; check slender
299
+ elements (E7) in compression; pick the real Lb and Cb. Ground each in the RAG and cite the
300
+ Section + equation.
301
+ 3. **Design the connections** (see the CONNECTIONS section below) — also yours to reason.
302
+
303
+ ## Work only the unique member & connection TYPES
304
+ A building has hundreds of members but only a handful of distinct **types** (e.g. "perimeter
305
+ MF beam", "interior gravity column", "N-S brace"). Do NOT design members one-by-one. Instead:
306
+ 1. Get forces for your governing combinations across all elements.
307
+ 2. **Group** elements by (section, role/system, approximate length), and for each group take the
308
+ **governing** element (worst D/C-driving demand across your combinations).
309
+ 3. Reason carefully through that one representative per group, then propagate the result to the
310
+ group. ~6–12 representatives typically covers the whole building. The same applies to
311
+ connection types (e.g. "typical MF beam-to-column", "brace-to-gusset", "column base").
312
+ 4. **Cover these member types at minimum, each with an explicit `role`** in its `inputs` so the
313
+ report places it: `roof` (roof beam/girder), `floor` (typical floor beam/girder), `gravity_col`
314
+ (interior gravity column), `lateral_col` (moment-frame / braced-frame column), and `brace` (if a
315
+ braced system). A **roof beam and an interior gravity column are distinct types** — design them
316
+ separately, do NOT fold the roof beam into the floor beam or the interior column into the lateral
317
+ column. (The report's Chapter 6 has a section per role and shows "no member with this role" when
318
+ you omit one.)
319
+
320
+ ## Hard rules
321
+ 1. **Ground every code check in the RAG — this is mandatory, not optional.** The RAGs exist for
322
+ reliability; never recall code values from memory. Use `search_engineering_standards`, apply the
323
+ exact equation/φ/limits returned, and **cite Section + equation number**. Confirm you pulled the
324
+ *design* provision, not an appendix. **Required grounding by system (the report's Chapter 13
325
+ verifies this against your activity log and flags anything MISSING):**
326
+ - **`engineering_standards_A360`** — REQUIRED for every member limit state (tension, compression,
327
+ flexure, shear, interaction) *and* every connection (Chapter J bolts/welds/block-shear, Chapter K
328
+ for HSS). **Connections must be grounded too** — query Chapter J and write a `connections` block;
329
+ a member-only design is incomplete.
330
+ - **`engineering_standards_A341`** — REQUIRED whenever the seismic system uses **R > 3** (SMF/IMF,
331
+ SCBF/OCBF, EBF/BRBF, dual). Query it for the ductile detailing and capacity design (SCWB,
332
+ expected strength, capacity-limited columns, protected zones, demand-critical welds) and write the
333
+ `capacity_design` block. (For **R ≤ 3** "not specifically detailed for seismic" systems, AISC 341
334
+ does not apply — design per AISC 360; say so explicitly.)
335
+ - **`engineering_standards_A358`** — REQUIRED to SELECT the prequalified moment-connection type
336
+ (RBS/WUF-W/BFP/end-plate) whenever a moment frame is detailed for seismic (R > 3).
337
+ 2. **Loads are computed, not retrieved.** ASCE 7 is not in the RAG. Use the engine's load
338
+ routines for the seismic/wind *magnitudes and patterns*, then spot-check Cs, V, and the
339
+ vertical distribution by hand. The **pipeline** assembles the ASCE 7-22 §2.3 combinations from
340
+ those patterns automatically.
341
+ 3. **Run the pipeline for the DEMANDS; derive every capacity yourself from the RAG.** The pipeline
342
+ (`design_pipeline`, via `pipeline.design_and_report`) computes the per-member **demand envelope
343
+ only** and writes `calc_package.json` (demands) + `member_demands.md`. It computes **NO capacity** —
344
+ there is no coded E3/F2-F6/G2/H1, no B2, no SCWB anywhere in this repo. For **each governing
345
+ member** you MUST: query the AISC 360 (and 341) RAG, select the correct limit state for that
346
+ section/condition (e.g. compact vs noncompact flange → F2 vs F3, weak-axis F6, HSS F7/F8, slender
347
+ E7), implement that exact equation with its φ and limits, compute the capacity and D/C, cite the
348
+ Section + equation, and write `limit_state` / `cited` / `capacity` / `DC` into each member of
349
+ `calc_package.json`. Use `design_post.run_case` only to pull demands; `sections.props` for
350
+ properties. Then re-run `report.build_report` so the report shows your checks.
351
+ 4. **Check serviceability + drift the code way:** amplified story drift δ = Cd·δ_elastic/Ie
352
+ (§12.8.6) and beam vertical deflection (live L/360, total L/240).
353
+ 5. **Do NOT read `eval_tests/answer_key/`** — off-limits and blocked.
354
+
355
+ ## CONNECTIONS — design these by reasoning (AISC 360 Ch. J / Ch. K, AISC 341, AISC 358 prequalified connections)
356
+ The analysis model does not include connection detail; the engine gives you the **demands**
357
+ (`connection_demands.csv`: beam-end moment & shear, brace axial, base/splice reactions). For
358
+ each unique connection **type**, you design the joint:
359
+ - Identify the connection and its required strength from the governing combination (for seismic
360
+ systems use **capacity design** — the expected strength of the connected member / Ω₀ demand,
361
+ per AISC 341, not just the analysis force).
362
+ - Work the limit states from **AISC 360 Chapter J**: bolt shear/tension and combined (J3),
363
+ bearing/tearout (J3.10), weld strength (J2), block shear (J4.3), and the strength of connecting
364
+ elements/plates (J4). For HSS use **Chapter K**. Cite each clause.
365
+ - For seismic **moment-frame** connections, first **SELECT the prequalified connection type from
366
+ AISC 358** — query `engineering_standards_A358`: e.g. RBS (reduced beam section), WUF-W, bolted
367
+ flange plate (BFP), or extended end-plate. Verify the section/bolt/span **prequalification limits**
368
+ for your members, then follow that connection's design procedure. Apply the **AISC 341** seismic
369
+ requirements that govern (demand-critical welds, protected zones, continuity/doubler plates,
370
+ panel-zone shear; for braced frames the gusset/brace connection forces from the **expected brace
371
+ strength**). Only if the demanded detail is genuinely outside A358's prequalification do you design
372
+ to the capacity-design force and note that qualification testing is confirmed separately.
373
+ - Choose real components (bolt size/grade & count, weld size/length, plate thickness) and show
374
+ each limit-state D/C. Aim for efficient, constructible details.
375
+
376
+ ## Economy — design for the LIGHTEST sections/details that pass
377
+ A safe design isn't the goal — an efficient one is. Deliver a sensibly proportioned passing design
378
+ (governing members roughly **D/C ≈ 0.85–0.95**, drift just under its limit; re-run the analysis after
379
+ any resize, since forces change with stiffness). **Do NOT run an exhaustive member-size optimisation
380
+ automatically** — that is a separate, **OPT-IN** step the user must request (see *Optimisation* below),
381
+ which you always OFFER at the end of the run.
382
+
383
+ ## Optimisation — OPT-IN, never automatic
384
+ Optimisation drives the member sizes down to the lightest sections/details that still pass every limit
385
+ state. It is **opt-in and never triggered automatically.**
386
+ - **End EVERY run with the VERBATIM closing note the pipeline prints in its NEXT_STEP** — it tells the user the
387
+ OFF-by-default report figures exist, and invites them to try different lateral restraint locations or systems or to
388
+ request an optimisation run. Do not reword it and do not add other offers. If the user then opts in, act on it:
389
+ set the requested figure flag(s) — `force_diagrams`, `force_summary`, `mode_figures`, `deformed_shape_figure`,
390
+ `section_color_figure`, `appendix_case_figures` — and re-render `report.build_report`, or run the optimisation /
391
+ system change they describe. End with the note even if the design is already efficient.
392
+ - **If the user opts in, follow their guidance.** If they leave it undirected, optimise by common-sense
393
+ structural engineering:
394
+ - columns get **lighter up the height**, but change in **GROUPS of levels** (e.g. every 2–4 storeys),
395
+ **not every level** — splice/fabrication economy favours repeated sizes;
396
+ - columns may take **different sizes within a level by demand** (exterior vs interior, corner vs typical);
397
+ - keep beams to a small set of repeated sizes; prefer consistent member depths and standard shapes
398
+ (constructability);
399
+ - every limit state must still pass: D/C ≤ 1.0 (governing ≈ 0.85–0.95), amplified drift ≤ limit,
400
+ deflection, SCWB / ductility, and connections.
401
+ Each optimisation iteration: edit the `cfg` (a `custom_build` section-map keyed by level-group and
402
+ exterior/interior is the usual tool), **re-run `pipeline.design_and_report`** for fresh demands, then
403
+ re-derive the capacities and re-check.
404
+ - **After an optimisation run, ALWAYS present the new solution to the user** (new sizes by group, weight
405
+ saved, governing D/Cs and drift) and ask whether they want to **try something different or commit to the
406
+ report**. **ALWAYS WAIT for the user before updating / finalising the report** — do not overwrite the
407
+ report until they confirm. Repeat the loop as long as they want to try alternatives.
408
+
409
+ ## What to deliver (end your run with this)
410
+ - Lateral system + final member sizes (columns, beams, braces).
411
+ - Periods vs Ta; ELF base shear per direction; wind base shear where it governs; which governs.
412
+ - Max amplified inter-story drift vs limit; beam serviceability ratios.
413
+ - **Per member TYPE:** section, governing LRFD combination (with the combo you assembled),
414
+ demand (P, Mx, My, V), capacity (φPn, φMnx, φMny, φVn) with the **cited clause and the limit
415
+ state you selected and why**, and D/C.
416
+ - **Per connection TYPE:** demand (and whether capacity-design governed), the components chosen,
417
+ each AISC 360/341 limit-state check with cited clause, and D/C.
418
+ - **Seismic capacity design / ductile detailing** (any R-based system) — write a `capacity_design`
419
+ block in `calc_package.json`, grounded in `engineering_standards_A341` (and A358 for the connection
420
+ type). For a **moment frame**: the strong-column-weak-beam ratio ΣM\*pc/ΣM\*pb at the governing
421
+ joint (AISC 341 §E3.4a, must be > 1.0) and the panel-zone shear / doubler check. For a **braced
422
+ frame**: the brace expected strength (RyFyAg in tension, 1.1RyPn in compression), the
423
+ capacity-limited column force, and brace slenderness / width-thickness ductility. Chapter 9 of the
424
+ report renders this block; if you omit it the chapter shows "pending".
425
+ - Confirmation the model passes the sanity-check suite.
426
+ - **You MUST write `calc_package.json` yourself** (`write_file("calc_package.json", ...)` in your
427
+ workspace — the reviewer reads it from there). It must contain both a `members` list and a
428
+ `connections` list. Each entry carries: inputs/demand, the **cited clause + the limit state you
429
+ selected**, capacities, and D/C. For each **connection** give the actual sized components (bolt
430
+ size/grade & count, weld size & length, plate thickness) and the D/C of every limit state you
431
+ checked — demands-and-basis alone is NOT a completed connection design. Schema example:
432
+ `{"building":"...",
433
+ "members":[{"id":"roof-beam-...","inputs":{"role":"roof","section":"...", ...},"cited":"...","limit_state":"...","DC":...},
434
+ {"id":"floor-beam-...","inputs":{"role":"floor",...},...},
435
+ {"id":"grav-col-...","inputs":{"role":"gravity_col",...},...},
436
+ {"id":"mf-col-...","inputs":{"role":"lateral_col",...},...},
437
+ {"id":"brace-...","inputs":{"role":"brace",...},...}],
438
+ "connections":[{"id":"MF-beam-col","demand":{...},"capacity_design":true,"components":"...","cited":"AISC 360 J... / 341 ... / 358 ...","checks":[{"limit_state":"bolt shear J3.6","DC":...}, ...]}],
439
+ "capacity_design":{"system":"SMF","SCWB":{"joint":"...","ratio":1.34,"cite":"AISC 341 E3.4a"},"panel_zone":{...}}}`
440
+ - The reviewer-grade figures (`plot_model.figures(...)`).
441
+
442
+ Show your reasoning and the cited clauses, not just final numbers — every capacity must trace to
443
+ an AISC 360 section/equation you pulled from the RAG.
444
+
445
+ > ✅ **COMPLETION GATE — do NOT declare the design done until ALL of these are in `calc_package.json`:**
446
+ > 1. **Members** — every type tagged with a `role` (roof, floor, gravity_col, lateral_col, brace),
447
+ > each with limit state + capacity + D/C, cited to A360.
448
+ > 2. **Connections** — a non-empty `connections` list: each connection TYPE (beam-to-column,
449
+ > brace-to-gusset, column splice, column base) with sized components and every limit-state D/C,
450
+ > grounded in A360 Ch. J (+ A358/A341 where seismic). **A member-only package is INCOMPLETE — do
451
+ > not skip connections, they are a required deliverable, not optional.**
452
+ > 3. **Capacity design** — a `capacity_design` block **if R > 3** (SCWB/panel zone for moment frames,
453
+ > brace expected strength + capacity-limited columns for braced frames), grounded in A341.
454
+ > 4. **Numerical self-consistency** — run the self-consistency check (`import consistency;
455
+ > consistency.check("<building>")`) and resolve **every** flag before declaring done. The SAME quantity
456
+ > must carry the SAME value everywhere (a plate thickness, capacity, or D/C quoted in your narrative must
457
+ > equal the one in `calc_package.json`); every reported **D/C must equal demand ÷ capacity** to tolerance;
458
+ > no member/connection may be missing `limit_state` / `capacity` / `DC`; and no D/C may exceed 1.0. If two
459
+ > of your scripts produced different numbers for one quantity, reconcile them — do not report both.
460
+ >
461
+ > The report's **Chapter 13 grounding verification reads your activity log and marks any of these
462
+ > MISSING** — if you finish with connections or required RAG grounding absent, your own deliverable
463
+ > will say so. Re-run `report.build_report` after writing them.
464
+
465
+ **Finalise.** Keep your final `cfg` saved at `jobs/<name>/cfg.py` (a top-level `cfg = dict(...)`). After
466
+ filling `calc_package.json`, run `import consistency; consistency.check(name)` and fix every flag (Completion
467
+ Gate #4), then re-render with **`report.build_report(name)`** -- NOT `design_and_report`, which regenerates
468
+ the DEMAND package and would drop your filled capacities (it backs them up to `calc_package.json.filled.bak`
469
+ and warns). Figures land in `jobs/<name>/figs/` and are referenced, so `report.html` stays small; set
470
+ `cfg["appendix_case_figures"]=True` for ALL per-combo Appendix-B diagrams.
471
+
472
+ ## Analysis API
473
+ `pipeline.design_and_report(name, cfg)` is the turnkey path (model + ASCE 7-22 loads + §2.3 LRFD combos through
474
+ P-Delta + per-member DEMAND envelope + figures + report). It computes **NO AISC capacity** — you derive every
475
+ φPn/φMn/φVn/interaction/B2/SCWB/Ω0 from the RAG and cite it (see "What to deliver"). Hand-check helpers:
476
+ `engine3d.CFG["B07"]` (schema to copy), `sections.props("W24X55")` (properties), `design_post.run_case(...)`
477
+ (quick one-combo demands; the OFFICIAL envelope is the distributed static model, girder moment per
478
+ `cfg['floor_system']` = "one-way" default / "two-way").
@@ -0,0 +1,51 @@
1
+ # AISC 360-22 — Specification table of contents (query aid)
2
+
3
+ Use this to phrase **clause-anchored** RAG queries against `engineering_standards_A360`
4
+ (e.g. "Section E3 flexural buckling Pn = Fn Ag", "Section F2 lateral-torsional buckling Lp Lr",
5
+ "Section H1-1 combined axial and flexure interaction"). Confirm the retrieved text is the
6
+ *design provision*, not an appendix (e.g. Appendix 4 is fire). Member-design chapters are
7
+ D, E, F, G, H; connections are J; serviceability is L; stability is C + App. 7/8.
8
+
9
+ ## Chapters
10
+ - **A — General Provisions** (A1 scope, A2 referenced standards, A3 material, A4 drawings)
11
+ - **B — Design Requirements** — B1 general; B2 loads & load combinations; B3 design basis
12
+ (B3.1 LRFD, φRn ≥ Ru; B3.2 ASD); **B4 member properties** (B4.1 classification of elements:
13
+ compact / noncompact / slender, width-to-thickness λ, λp, λr; Tables B4.1a/B4.1b)
14
+ - **C — Design for Stability** — C1 general; C2 required strengths; **C3 Direct Analysis
15
+ Method** (reduced stiffness 0.8τb, notional loads)
16
+ - **D — Tension** — D1 slenderness; **D2 tensile strength** (yielding D2-1 = Fy·Ag, φt=0.90;
17
+ rupture D2-2 = Fu·Ae, φt=0.75); D3 effective net area Ae; D4 built-up; D5 pin-connected; D6 eyebars
18
+ - **E — Compression** — E1 general; E2 effective length (KL/r); **E3 flexural buckling**
19
+ (Pn=Fn·Ag E3-1; Fn E3-2/E3-3 with limit 4.71√(E/Fy); Fe=π²E/(Lc/r)² E3-4; φc=0.90); E4
20
+ torsional & flexural-torsional; E5 single angles; E6 built-up; E7 slender-element members
21
+ - **F — Flexure** — **F1 general** (φb=0.90; Cb F1-1); **F2 doubly-symmetric compact
22
+ I-shapes, major axis** (yielding Mp=Fy·Zx F2-1; LTB F2-2/F2-3/F2-4; Lp F2-5; Lr F2-6);
23
+ F3 compact web/noncompact-slender flange; F4 other I-shapes; F5 slender-web I-shapes;
24
+ **F6 I-shapes minor axis** (Mn=min(Fy·Zy, 1.6·Fy·Sy) F6-1); F7 square/rect HSS & box;
25
+ F8 round HSS; F9 tees & double angles; F10 single angles; F11 rect bars & rounds;
26
+ F12 unsymmetrical; F13 proportioning (holes, etc.)
27
+ - **G — Shear** — G1 general; **G2 I-shapes & channels** (Vn=0.6·Fy·Aw·Cv1 G2-1; for most
28
+ rolled I-shapes φv=1.00 and Cv1=1.0 when h/tw ≤ 2.24√(E/Fy)); G3 tension-field action;
29
+ G4 single angles; G5 rect HSS; G6 round HSS; G7 weak-axis shear
30
+ - **H — Combined Forces & Torsion** — **H1 doubly/singly-symmetric members, flexure+axial**
31
+ (interaction H1-1a for Pr/Pc ≥ 0.2, H1-1b for < 0.2); H2 unsymmetric; H3 torsion &
32
+ combined torsion; H4 rupture with combined forces
33
+ - **I — Composite Members** (I1 general; I2 axial; I3 flexure; I4 shear; I5 combined;
34
+ I6 load transfer; I7 diaphragms/collectors; I8 steel anchors)
35
+ - **J — Connections** — J1 general; J2 welds; J3 bolts (J3.2 min pretension/Table J3.2;
36
+ J3.6 spacing; J3.7 bearing & tearout); J4 affected elements (J4.1 shear yield/rupture,
37
+ **J4.3 block shear**); J5 fillers; J6 splices; J7 bearing strength; J8 column bases &
38
+ anchor rods; J9 stiffeners; J10 flanges/webs with concentrated forces
39
+ - **K — HSS & Box-Section Connections** (K1–K5)
40
+ - **L — Serviceability** — L1 general; L2 camber; **L3 deflections**; **L4 drift**;
41
+ L5 vibration; L6 wind-induced motion; L7 thermal; L8 connection slip
42
+ - **M — Fabrication & Erection**; **N — Quality Control / Quality Assurance**
43
+
44
+ ## Appendices (NOT primary design clauses)
45
+ 1 Design by Advanced Analysis · 2 Ponding · 3 Fatigue · **4 Fire conditions** (elevated-temp;
46
+ do not use for ambient design) · 5 Existing structures · 6 Member stability bracing ·
47
+ **7 Alternative methods for stability (Effective Length Method)** · **8 Approximate
48
+ second-order analysis (B1/B2 amplifiers)**
49
+
50
+ > Seismic system rules (R, Cd, Ω0, ρ; SMF/SCBF/EBF/BRBF detailing) are in **AISC 341** —
51
+ > query `engineering_standards_A341`. Worked numeric examples are in `steel_design_examples`.
@@ -0,0 +1,36 @@
1
+ # AISC Design Examples — quick index for `steel_design_examples` queries
2
+
3
+ For **every member and connection you design**, pair your `engineering_standards_A360`
4
+ (spec) query with a `steel_design_examples` query (`collection="steel_design_examples"`)
5
+ for the matching worked example below, and **mirror its check sequence — the method, not
6
+ its numbers.** Example hits return inline. Phrase the example query with the AISC clause +
7
+ member type, e.g. `"E3 W-shape column compression flexural buckling Pn worked example"`.
8
+
9
+ ## Members
10
+ - **W-shape beam, major-axis flexure (Ch. F2):** F.1-1A/1B continuously braced;
11
+ F.1-2A/2B braced at third points; F.1-3A/3B braced at midspan (Lp/Lr, Cb, LTB).
12
+ - **W-shape beam shear (Ch. G2):** G.1A / G.1B.
13
+ - **W-shape column compression (Ch. E3):** E.1A pinned, E.1B intermediate bracing,
14
+ E.1C/E.1D available-strength calc, E.4A/E.4B moment-frame column.
15
+ - **Beam-column, combined axial + flexure (Ch. H1):** H.1A/H.1B (braced frame),
16
+ H.2 (§H2 method), H.4 (compression + flexure); use the H1-1a/H1-1b interaction.
17
+ - **HSS brace/column compression (Ch. E):** E.9 rectangular HSS (no slender elements),
18
+ E.10 rectangular HSS with slender elements, E.11 pipe.
19
+ - **Brace in tension (Ch. D):** D.4 rectangular HSS, D.5 round HSS, D.1 W-shape tension.
20
+ - **HSS flexure (Ch. F6-F8):** F.6 square HSS compact, F.7A/B noncompact, F.8A/B slender.
21
+ - **Composite floor (Ch. I), only if specified:** I.1 composite beam, I.2 composite girder.
22
+
23
+ ## Connections (Manual Part II + Spec Ch. J / K)
24
+ - **Simple shear tab / single-plate** (typical gravity beam-to-column or -girder):
25
+ II.A-17A conventional single-plate, II.A-18 to a girder web, II.A-19A extended.
26
+ - **Double-angle shear connection:** II.A-1A all-bolted, II.A-2A bolted/welded, II.A-3 welded.
27
+ - **FR moment connection** (the E-W moment frame): II.B-1 bolted flange-plate,
28
+ II.B-2 welded flange-plate, II.B-3 directly-welded flange (prequalified detailing → A358).
29
+ - **Brace / gusset connections (CBF):** II.C-1, II.C-2 truss/bracing support connections.
30
+ - **Column base plate:** J.6 base plate bearing on concrete; HSS column base → K.9.
31
+ - **Weld / bolt building blocks (Ch. J):** J.1/J.2 welds, J.3 bolts in tension + shear.
32
+
33
+ ## Building-scale method
34
+ - **Moment-frame stability by the Direct Analysis Method:** Example **C.1A** — the building-
35
+ level recipe that III-1 Step 2 follows.
36
+ - The whole worked four-story building (method + answer key) is the **III-1 reference above**.