simcon-toolkit 0.1.0__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.
- simcon_toolkit/__init__.py +40 -0
- simcon_toolkit/__main__.py +7 -0
- simcon_toolkit/_kit/LICENSE +202 -0
- simcon_toolkit/_kit/NOTICE +37 -0
- simcon_toolkit/_kit/assets/parts/clip_frame.stl +0 -0
- simcon_toolkit/_kit/assets/parts/simple_plate.stl +0 -0
- simcon_toolkit/_kit/packages/.ruff.toml +10 -0
- simcon_toolkit/_kit/packages/cadmould_cloud/__init__.py +8 -0
- simcon_toolkit/_kit/packages/cadmould_cloud/auth.py +681 -0
- simcon_toolkit/_kit/packages/cadmould_cloud/client.py +235 -0
- simcon_toolkit/_kit/packages/cadmould_geometry/__init__.py +5 -0
- simcon_toolkit/_kit/packages/cadmould_geometry/mesh.py +210 -0
- simcon_toolkit/_kit/packages/cadmould_geometry/stl.py +168 -0
- simcon_toolkit/_kit/packages/cadmould_results/__init__.py +30 -0
- simcon_toolkit/_kit/packages/cadmould_results/loader.py +288 -0
- simcon_toolkit/_kit/packages/cadmould_scoring/__init__.py +7 -0
- simcon_toolkit/_kit/packages/cadmould_scoring/metrics.py +519 -0
- simcon_toolkit/_kit/pyproject.toml +232 -0
- simcon_toolkit/_kit/templates/_shared/AGENTS.base.md +101 -0
- simcon_toolkit/_kit/templates/gate-study/.gitignore +18 -0
- simcon_toolkit/_kit/templates/gate-study/AGENTS.md +46 -0
- simcon_toolkit/_kit/templates/gate-study/GATING_STUDY_PLAYBOOK.md +219 -0
- simcon_toolkit/_kit/templates/gate-study/INITIAL_PROMPT.md +26 -0
- simcon_toolkit/_kit/templates/gate-study/README.md +137 -0
- simcon_toolkit/_kit/templates/gate-study/main.py +344 -0
- simcon_toolkit/_kit/templates/gate-study/pipeline.py +281 -0
- simcon_toolkit/_kit/templates/process-window/.gitignore +20 -0
- simcon_toolkit/_kit/templates/process-window/AGENTS.md +49 -0
- simcon_toolkit/_kit/templates/process-window/METHOD.md +155 -0
- simcon_toolkit/_kit/templates/process-window/README.md +176 -0
- simcon_toolkit/_kit/templates/process-window/configs/simple-plate.yaml +116 -0
- simcon_toolkit/_kit/templates/process-window/doe_spec.schema.md +249 -0
- simcon_toolkit/_kit/templates/process-window/main.py +82 -0
- simcon_toolkit/_kit/templates/process-window/process_window/__init__.py +5 -0
- simcon_toolkit/_kit/templates/process-window/process_window/centre.py +298 -0
- simcon_toolkit/_kit/templates/process-window/process_window/design.py +144 -0
- simcon_toolkit/_kit/templates/process-window/process_window/economics.py +367 -0
- simcon_toolkit/_kit/templates/process-window/process_window/emit.py +591 -0
- simcon_toolkit/_kit/templates/process-window/process_window/guardrails.py +153 -0
- simcon_toolkit/_kit/templates/process-window/process_window/harness.py +360 -0
- simcon_toolkit/_kit/templates/process-window/process_window/identity.py +92 -0
- simcon_toolkit/_kit/templates/process-window/process_window/inspect_part.py +184 -0
- simcon_toolkit/_kit/templates/process-window/process_window/kpis.py +355 -0
- simcon_toolkit/_kit/templates/process-window/process_window/material_card.py +163 -0
- simcon_toolkit/_kit/templates/process-window/process_window/probe_proxy.py +169 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_confirm.py +403 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_epsilon_floor.py +198 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_feedback.py +322 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_refine.py +279 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_screening.py +370 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_sweep.py +166 -0
- simcon_toolkit/_kit/templates/process-window/process_window/setup_campaign.py +312 -0
- simcon_toolkit/_kit/templates/process-window/process_window/surrogate.py +201 -0
- simcon_toolkit/_kit/templates/process-window/process_window/test_centre.py +169 -0
- simcon_toolkit/_kit/templates/process-window/process_window/test_design.py +113 -0
- simcon_toolkit/_kit/templates/process-window/process_window/test_guardrails.py +157 -0
- simcon_toolkit/_kit/templates/process-window/process_window/test_surrogate.py +127 -0
- simcon_toolkit/_kit/templates/process-window/process_window/units.py +152 -0
- simcon_toolkit/_kit/templates/quoting/.gitignore +24 -0
- simcon_toolkit/_kit/templates/quoting/AGENTS.md +58 -0
- simcon_toolkit/_kit/templates/quoting/INTERVIEW.md +147 -0
- simcon_toolkit/_kit/templates/quoting/METHOD.md +256 -0
- simcon_toolkit/_kit/templates/quoting/PROMPT.md +46 -0
- simcon_toolkit/_kit/templates/quoting/QUOTING_PLAYBOOK.md +245 -0
- simcon_toolkit/_kit/templates/quoting/README.md +158 -0
- simcon_toolkit/_kit/templates/quoting/main.py +484 -0
- simcon_toolkit/_kit/templates/quoting/parts/.gitkeep +0 -0
- simcon_toolkit/_kit/templates/quoting/quoting/__init__.py +11 -0
- simcon_toolkit/_kit/templates/quoting/quoting/costing.py +725 -0
- simcon_toolkit/_kit/templates/quoting/quoting/geometry.py +398 -0
- simcon_toolkit/_kit/templates/quoting/quoting/shop.py +193 -0
- simcon_toolkit/_kit/templates/quoting/quoting/state.py +260 -0
- simcon_toolkit/_kit/templates/quoting/quoting/study.py +577 -0
- simcon_toolkit/_kit/templates/quoting/quoting/toolkit.py +50 -0
- simcon_toolkit/_kit/templates/quoting/shop/README.md +43 -0
- simcon_toolkit/_kit/templates/quoting/shop/commercial.md +86 -0
- simcon_toolkit/_kit/templates/quoting/shop/lessons.md +94 -0
- simcon_toolkit/_kit/templates/quoting/shop/machines.md +68 -0
- simcon_toolkit/_kit/templates/quoting/shop/materials.md +92 -0
- simcon_toolkit/_kit/templates/quoting/shop/shop-profile.md +87 -0
- simcon_toolkit/_kit/templates/quoting/shop/tooling.md +145 -0
- simcon_toolkit/_kit/templates/run-one-simulation/.gitignore +16 -0
- simcon_toolkit/_kit/templates/run-one-simulation/AGENTS.md +41 -0
- simcon_toolkit/_kit/templates/run-one-simulation/README.md +133 -0
- simcon_toolkit/_kit/templates/run-one-simulation/main.py +216 -0
- simcon_toolkit/_kit/templates.toml +83 -0
- simcon_toolkit/choices.py +11 -0
- simcon_toolkit/cli.py +381 -0
- simcon_toolkit/generate.py +590 -0
- simcon_toolkit/instructions.py +152 -0
- simcon_toolkit/manifest.py +86 -0
- simcon_toolkit/project.py +356 -0
- simcon_toolkit/wizard.py +160 -0
- simcon_toolkit-0.1.0.dist-info/METADATA +48 -0
- simcon_toolkit-0.1.0.dist-info/RECORD +97 -0
- simcon_toolkit-0.1.0.dist-info/WHEEL +4 -0
- simcon_toolkit-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Quoting playbook — the method, the cost model, and every gotcha
|
|
2
|
+
|
|
3
|
+
How this example turns a geometry and a cavity count into a defensible tool price and piece price,
|
|
4
|
+
what each number rests on, and what breaks. Read this before adapting it to your own shop.
|
|
5
|
+
|
|
6
|
+
> TL;DR: read the shop context → derive the cost drivers from the geometry (projected area, wall,
|
|
7
|
+
> undercuts) → simulate the gating options on the cloud → price each one end to end → pick on total
|
|
8
|
+
> cost of ownership → write the quote → take the estimator's corrections back into `shop/lessons.md`.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 0. Why a quote needs a simulation at all
|
|
13
|
+
|
|
14
|
+
A moldmaker's quote is decided long before anyone runs a mold-flow analysis, and three of the
|
|
15
|
+
decisions that set the price are exactly the ones a filling simulation answers:
|
|
16
|
+
|
|
17
|
+
| Decision | What it costs | Who normally decides it | When |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| **Gate count** | one hot-runner nozzle **per cavity**, plus a weld line each | the mold designer | after the order |
|
|
20
|
+
| **Cavity pressure** | clamp force → press class → hourly rate for the tool's whole life | a rule of thumb | at quotation |
|
|
21
|
+
| **Fill time** | the fill share of the cycle; the shear ceiling | a guess | at quotation |
|
|
22
|
+
|
|
23
|
+
The second one is the expensive one. Press class is a decision you live with for 500k shots, and
|
|
24
|
+
it is normally taken from a number somebody remembered. A filling run costs about nine seconds.
|
|
25
|
+
|
|
26
|
+
The point of this example is not that the simulation is more accurate than the estimator — on
|
|
27
|
+
absolute pressure it demonstrably is not (§5.2). It is that the *ranking* it provides is sound, and
|
|
28
|
+
ranking is what a gate-count decision needs.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 1. What the geometry alone decides (`quoting/geometry.py`)
|
|
33
|
+
|
|
34
|
+
All offline, all free, all in seconds.
|
|
35
|
+
|
|
36
|
+
| Quantity | How | Feeds |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| **Projected area** | summed \|projected\| facet area / 2 (exact for a closed surface) | clamp force |
|
|
39
|
+
| **Draw direction** | the axis with the largest shadow | projected area, undercuts |
|
|
40
|
+
| **Wall thickness** | largest sphere that fits inside the material, touching each sampled facet | cooling time, complexity |
|
|
41
|
+
| **Undercuts** | facets that release in neither draw direction, clustered | slides / lifters |
|
|
42
|
+
| **Shape factor** | part surface ÷ bounding-box surface | cavity machining complexity |
|
|
43
|
+
| **Volume** | closed-surface volume | shot size, material, barrel fit |
|
|
44
|
+
|
|
45
|
+
Three of those have a non-obvious implementation, each because the obvious one is wrong:
|
|
46
|
+
|
|
47
|
+
- **Sampling is area-weighted, not per-facet.** An STL's rim is meshed with many tiny triangles.
|
|
48
|
+
Sampling facets uniformly puts most rays on the rim, and a ray cast inward from the 1.5 mm edge
|
|
49
|
+
of a plate measures the plate's 150 mm *span*. Weighting by area also happens to be the quantity
|
|
50
|
+
you want: "how much of the surface is thin", not "how many triangles are thin".
|
|
51
|
+
- **Thickness is the largest inscribed sphere**, not a ray cast inward. A single inward ray
|
|
52
|
+
over-reads at every rim, where it measures the plate's *span* rather than its wall; the
|
|
53
|
+
inscribed sphere reads 1.5 mm from the face and from the rim alike. The p95 wall sets the
|
|
54
|
+
cooling time, so that error would go straight into the cycle and the price.
|
|
55
|
+
|
|
56
|
+
⚠️ **This replaced a bundle of tilted rays cast through a VTK OBB tree, and the reason is
|
|
57
|
+
worth keeping.** That tree was rebuilt non-deterministically: the same file measured between
|
|
58
|
+
1 and 461 usable samples run to run, aborting outright below 10, and it reported a 31 mm
|
|
59
|
+
median wall on a part 21.9 mm deep. The measurement now comes from trimesh and is identical
|
|
60
|
+
on every run of the same file. If anyone proposes going back to ray casting for speed, this
|
|
61
|
+
is what they are buying back.
|
|
62
|
+
- **Complexity uses the shape factor, not surface-to-volume.** Surface-to-volume looks like a
|
|
63
|
+
complexity measure and is mostly a thinness measure: a plain 1.5 mm plate scores 15 cm⁻¹ and
|
|
64
|
+
would be priced like a ribbed housing (it was, in the first run of this example — the tool came
|
|
65
|
+
out 28 % too expensive). Shape factor is ≈1 for a flat part and climbs with real features.
|
|
66
|
+
|
|
67
|
+
**Known limits.** Wall thickness under-reads at edges and corners, where a genuinely smaller
|
|
68
|
+
sphere fits — read the median as the nominal wall, not the p05. The undercut count is geometric:
|
|
69
|
+
it cannot know that a feature will be moulded with a hand-loaded insert instead of a slide. If
|
|
70
|
+
the cadmould mesher's own thickness/w2w data becomes reachable from the SDK, prefer it over this
|
|
71
|
+
geometric estimate. ⚠️ **The numbers have not been validated against a part of known wall
|
|
72
|
+
thickness** — they are physically plausible and reproducible, which is not the same as correct.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 2. The simulations (`quoting/study.py`)
|
|
77
|
+
|
|
78
|
+
One cloud project per quote, one group per batch, a project note per decision. The part is meshed
|
|
79
|
+
and uploaded once.
|
|
80
|
+
|
|
81
|
+
**Batch Q1 — gate count.** One run per gate count at a fixed nominal process. This is the batch
|
|
82
|
+
that pays for itself.
|
|
83
|
+
|
|
84
|
+
**Batch Q2 — process window (optional).** A flow-rate sweep at the chosen gating. Worth it when
|
|
85
|
+
fill time is a real share of the cycle; on a thick-walled part cooling dominates and the sweep
|
|
86
|
+
tells you nothing you will use.
|
|
87
|
+
|
|
88
|
+
**Nominal flow rate** comes from the SDK's own `estimate_fill_time`, which accounts for wall
|
|
89
|
+
thickness and the material's rheology. Do not derive it from a guessed fill time — a hand-picked
|
|
90
|
+
"fill it in 1 s" has been measured 3.5× wrong on a thin part, which moves the entire process
|
|
91
|
+
window and everything downstream of it.
|
|
92
|
+
|
|
93
|
+
**The material lookup is worth more than it looks.** `GET /material-versions/{id}` carries not just
|
|
94
|
+
the recommended melt and mould temperatures but the thermal data the cooling model needs —
|
|
95
|
+
`lambda_W_mK`, `cp_J_kgK`, `melt_density_kg_m3`, `no_flow_temperature_K`,
|
|
96
|
+
`ejection_temperature_K`. So the cycle-time estimate is built from *this grade's* physics rather
|
|
97
|
+
than a textbook constant. If the payload lacks them, `FAMILY_THERMAL` supplies family defaults and
|
|
98
|
+
the material is marked `family-default`.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 3. The cost model (`quoting/costing.py`)
|
|
103
|
+
|
|
104
|
+
### 3.1 Clamp force
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
F[kN] = p_mean[bar] × A_projected[cm²] / 100 (1 bar = 0.1 N/mm²)
|
|
108
|
+
p_mean = max(p_peak_simulated × sim_peak_to_mean, material rule of thumb)
|
|
109
|
+
F_required = F × clamp_safety_factor
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Both factors live in `shop/lessons.md`. The `max()` is the important part and §5.2 is why. On a
|
|
113
|
+
cold-runner tool the runner's own projected area is added (15 % of the cavity area); on a hot
|
|
114
|
+
runner it is not, because the melt channel is inside the manifold rather than in the parting line.
|
|
115
|
+
|
|
116
|
+
### 3.2 Press selection
|
|
117
|
+
|
|
118
|
+
Smallest press clearing **clamp** (≤ 80 % utilisation), **tie-bar opening**, and the **shot window**
|
|
119
|
+
(20–80 % of barrel). The three are not equally hard, and treating them as if they were produces
|
|
120
|
+
"nothing fits" on ordinary parts. Clamp and tie-bar are hard constraints — too little tonnage is
|
|
121
|
+
flash, and a mold that does not fit does not fit. The shot window is soft: a small shot is a melt
|
|
122
|
+
residence problem to be managed, not a reason to refuse the job. So the search relaxes the shot
|
|
123
|
+
window last and names the constraint it bent.
|
|
124
|
+
|
|
125
|
+
### 3.3 Cycle time
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
cycle = fill + max(hold, cool) + handling
|
|
129
|
+
cool = h²/(π²α) · ln[ (4/π) · (T_melt − T_mould)/(T_eject − T_mould) ] · cooling_time_factor
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
with `h` the half **governing** wall (p95 — the slowest-cooling section governs ejection) and
|
|
133
|
+
`α = λ/(ρ·c_p)` from the grade's own data. Holding time is `pack_time_s_per_mm_wall × nominal`
|
|
134
|
+
wall, because gate freeze follows the wall the melt flows through, not the thickest section.
|
|
135
|
+
Holding and cooling run concurrently, hence the `max()`.
|
|
136
|
+
|
|
137
|
+
**This is an analytic estimate, not a cooling simulation** — the filling solver has no cooling
|
|
138
|
+
phase. Its virtue is that a process engineer can redo it on paper from a datasheet, and an estimate
|
|
139
|
+
the customer can check beats a black box. Its known weakness is ribs and bosses, which is exactly
|
|
140
|
+
what `cooling_time_factor` exists to absorb (see L-001 in `lessons.md`).
|
|
141
|
+
|
|
142
|
+
### 3.4 The tool
|
|
143
|
+
|
|
144
|
+
Base + cavities × complexity + side actions + feed system + cooling + ejection + finish +
|
|
145
|
+
engineering + sampling, then project management, risk and margin. Every rate is in
|
|
146
|
+
`shop/tooling.md`. The gate count enters as `cavities × gates_per_cavity` hot-runner nozzles.
|
|
147
|
+
|
|
148
|
+
### 3.5 The piece price
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
material + machine + labour + secondary + setup → manufacturing
|
|
152
|
+
+ overhead (on material and labour ONLY) + margin → price
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Overhead is not applied to the machine line.** The machine rates in `shop/machines.md` are loaded
|
|
156
|
+
rates that already recover fixed cost; applying overhead again is the classic double count.
|
|
157
|
+
|
|
158
|
+
Only two things move along the volume ladder: **setup amortisation** (capped by the minimum
|
|
159
|
+
economic batch — nobody sets up twelve times a year for 800-part runs) and the **material price
|
|
160
|
+
break** on annual tonnage. A ladder that comes out nearly flat between two rungs is therefore a
|
|
161
|
+
correct answer, not a missing discount.
|
|
162
|
+
|
|
163
|
+
### 3.6 Choosing the gating
|
|
164
|
+
|
|
165
|
+
`compare_options()` prices every gating option end to end and ranks by **tool + piece × volume** at
|
|
166
|
+
the reference volume. That is the whole reason the study runs before the quote. If the winner is
|
|
167
|
+
within a couple of percent of the runner-up, the model cannot tell them apart — say so.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 4. The quote document
|
|
172
|
+
|
|
173
|
+
`python main.py cost` writes `quote.json` — the chosen option, every option it was chosen against,
|
|
174
|
+
the machine and cycle basis, and the reference volumes. That file is the deliverable.
|
|
175
|
+
|
|
176
|
+
Turning it into a document is your assistant's job, and the format should be yours rather than
|
|
177
|
+
ours. What the document must carry, however it looks:
|
|
178
|
+
|
|
179
|
+
**The basis, stated plainly** — surrogate solver, one cavity, no runner, analytic cooling,
|
|
180
|
+
geometric weld-visibility. That is not decoration: it is what makes the quote defensible when the
|
|
181
|
+
first article disagrees with it.
|
|
182
|
+
|
|
183
|
+
**Honest comparisons.** If the winner is within a couple of percent of the runner-up, the model
|
|
184
|
+
cannot tell them apart and the document must say so. One measure per chart; never one chart with
|
|
185
|
+
two y-scales.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 5. Things to know (each cost a real mistake)
|
|
190
|
+
|
|
191
|
+
### 5.1 The offline path is not a quote
|
|
192
|
+
`--offline` exists so the flow can be demonstrated and tested without credentials. Everything it
|
|
193
|
+
produces is marked `estimated` through to `quote.json`. Do not send it.
|
|
194
|
+
|
|
195
|
+
### 5.2 Never size the clamp from the simulation alone
|
|
196
|
+
The AI model is **one cavity with no runner system** and under-reads absolute pressure on
|
|
197
|
+
multi-gate parts. Cavity pressure at the end of *pack* — which is what actually opens a tool — is
|
|
198
|
+
not modelled at all, because the solver models filling only. The rule-of-thumb floor per material
|
|
199
|
+
family in `shop/materials.md` is what keeps a tool from flashing at trial. Use the simulation to
|
|
200
|
+
rank gating options; use the rule of thumb to size the press. `quote.json` records which governed.
|
|
201
|
+
|
|
202
|
+
### 5.3 The endpoint sheds load
|
|
203
|
+
`max_workers=2` with retry and backoff. Everything timing out means the model went cold — one lone
|
|
204
|
+
request warms it. Never run a second batch concurrently with a running one.
|
|
205
|
+
|
|
206
|
+
### 5.4 Determinism
|
|
207
|
+
Identical configuration → identical result. Re-running for confidence buys nothing; spend every run
|
|
208
|
+
on a new configuration.
|
|
209
|
+
|
|
210
|
+
### 5.5 Weld lines are located, not judged
|
|
211
|
+
The detector finds where flow fronts meet. Whether that position is acceptable depends on the
|
|
212
|
+
part's functional and visible faces, which are on a drawing you were probably not given. It goes on
|
|
213
|
+
the assumptions slide as a flag, never as a silent pass.
|
|
214
|
+
|
|
215
|
+
### 5.6 Result-file details
|
|
216
|
+
Handled by the reused `metrics.py`, but worth knowing: `Degree_of_filling` is a sharp 0→1 front
|
|
217
|
+
(arrival = first crossing of 0.5, *not* `isfinite`); `Pressure` honours a `unit` attribute (Pa now,
|
|
218
|
+
bar in older files); the `geometry3DF` group name has a trailing space; the result mesh is
|
|
219
|
+
re-centred on the origin while your gate coordinates are not.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 6. Adapting it to your shop
|
|
224
|
+
|
|
225
|
+
1. **Replace `shop/` wholesale.** Keep the file names and the fenced JSON block names; change
|
|
226
|
+
everything else. The prose is read by the agent and matters as much as the numbers.
|
|
227
|
+
2. **Re-derive the tooling rates** against your last ten tools. The shipped numbers are invented.
|
|
228
|
+
3. **Set the calibration block to neutral** (`1.00` everywhere, `clamp_safety_factor` to whatever
|
|
229
|
+
you use today) and let it move only through `learn`. Starting from someone else's corrections
|
|
230
|
+
is how you inherit someone else's mistakes.
|
|
231
|
+
4. **Quote three parts you already know the answer to**, and run `learn` on each. Three corrections
|
|
232
|
+
is roughly where the cycle-time and tool-price factors stop moving much.
|
|
233
|
+
5. **Check the side-action count** on every one of those three. It is the estimate most likely to
|
|
234
|
+
be wrong and the most expensive when it is.
|
|
235
|
+
|
|
236
|
+
## 7. Limitations
|
|
237
|
+
|
|
238
|
+
- Filling only. No packing, cooling or warpage simulation — cooling is analytic, packing is a rate
|
|
239
|
+
per mm of wall.
|
|
240
|
+
- One cavity is simulated; cavity-to-cavity imbalance on a multi-cavity tool is not represented
|
|
241
|
+
even in principle.
|
|
242
|
+
- Undercut detection is geometric and cannot distinguish a slide from a hand-loaded insert.
|
|
243
|
+
- The tool model covers a 2-plate mould with a hot or cold runner. Unscrewing cores, 2K tools and
|
|
244
|
+
conformal cooling are explicitly out and are flagged rather than priced.
|
|
245
|
+
- Tolerances are not modelled at all. Nothing here guarantees a dimension.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Template · Agentic quoting (`quoting`)
|
|
2
|
+
|
|
3
|
+
Give an agent **a geometry and a cavity count** — nothing else — and get back a **quotation**: a
|
|
4
|
+
tool price, a piece price at a volume ladder, a press and a cycle time, written out as a
|
|
5
|
+
`quote.json` your own assistant turns into the document your customer expects. The decisions that drive that price and have to be taken early — **how many gates**,
|
|
6
|
+
**what cavity pressure**, **how fast it fills** — are settled by running filling simulations on the
|
|
7
|
+
Simcon cloud, not by a rule of thumb.
|
|
8
|
+
|
|
9
|
+
Two things make it more than a calculator:
|
|
10
|
+
|
|
11
|
+
- **The agent has its own context.** `shop/` describes a specific shop: its presses, its material
|
|
12
|
+
bias, how it estimates a mould, what it declines. The agent quotes as *that* shop. It ships
|
|
13
|
+
filled in with a **fictional** shop, so the first thing to do is the 20-minute interview in
|
|
14
|
+
[`INTERVIEW.md`](INTERVIEW.md) — until then every quote is watermarked as example data, because
|
|
15
|
+
a precise price built on someone else's invented rates is worse than no price.
|
|
16
|
+
- **It is meant to be corrected.** Every quote ends with a review. The estimator says what is
|
|
17
|
+
wrong and *why*; the agent writes the reason into `shop/lessons.md` and the number into that
|
|
18
|
+
file's `calibration` block, which the cost model reads on the next quote. Expect the first
|
|
19
|
+
handful of quotes to be mostly learning — that is the design.
|
|
20
|
+
|
|
21
|
+
## Run it
|
|
22
|
+
|
|
23
|
+
<!-- simcon-toolkit:setup -->
|
|
24
|
+
**Python 3.12 or newer**, and a virtual environment created *with that interpreter* — a venv
|
|
25
|
+
isolates packages, not the interpreter.
|
|
26
|
+
|
|
27
|
+
**Three sign-ins, each in your browser, and each does a different job.**
|
|
28
|
+
|
|
29
|
+
1. **The package index**, once, in the steps below: `cadmould-sdk-auth` lets pip install the
|
|
30
|
+
licensed `cadmould` wheel from SIMCON's private index. Your company's email domain has to be
|
|
31
|
+
enabled for it: if you can sign in but the browser tab then says `Access denied: your email
|
|
32
|
+
domain is not authorized for this API`, ask SIMCON support.
|
|
33
|
+
2. **Your licence**, the first time the code opens a licence session. It first checks the
|
|
34
|
+
Thales Sentinel run-time on your machine, and prints `License init failed: HASP driver
|
|
35
|
+
version too old` or `... runtime version too old` when that needs installing or updating.
|
|
36
|
+
3. **The cloud**, the first time the code calls it.
|
|
37
|
+
|
|
38
|
+
⚠️ A failed licence sign-in does not stop the script. It prints `License init failed: ...` or
|
|
39
|
+
`License acquisition failed.` to the terminal and carries on, so the error you meet later is `Cadmould API licence (LICENCE_API)
|
|
40
|
+
required`. When you see that one, scroll up to the first.
|
|
41
|
+
|
|
42
|
+
**macOS / Linux (bash):**
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python3.12 -m venv .venv
|
|
46
|
+
source .venv/bin/activate
|
|
47
|
+
pip install --upgrade pip cadmould-sdk-auth
|
|
48
|
+
cadmould-sdk-auth # opens a browser; sign in with your Simcon account
|
|
49
|
+
pip install . # installs cadmould and everything the quoting flow needs
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Windows (PowerShell):**
|
|
53
|
+
|
|
54
|
+
```powershell
|
|
55
|
+
py -3.12 -m venv .venv
|
|
56
|
+
.\.venv\Scripts\python.exe -m pip install --upgrade pip cadmould-sdk-auth
|
|
57
|
+
$env:VIRTUAL_ENV = "$PWD\.venv" # tell the login CLI which venv to configure
|
|
58
|
+
.\.venv\Scripts\cadmould-sdk-auth.exe # opens a browser; sign in with your Simcon account
|
|
59
|
+
.\.venv\Scripts\python.exe -m pip install .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The Windows route never activates the environment. `Activate.ps1` is blocked by the default
|
|
63
|
+
execution policy on many machines; naming the interpreter outright avoids it.
|
|
64
|
+
<!-- /simcon-toolkit:setup -->
|
|
65
|
+
|
|
66
|
+
Only the `study` stage needs the licensed wheel; `intake`, `cost` and `learn` run offline. No
|
|
67
|
+
graphics stack is involved: the geometry measurements are trimesh's, and the only dependency
|
|
68
|
+
beyond the shared ones is `rtree`, the ~2 MB spatial index behind them.
|
|
69
|
+
|
|
70
|
+
Then, from the project folder:
|
|
71
|
+
|
|
72
|
+
```powershell
|
|
73
|
+
# 0. ONCE: make shop/ describe YOUR shop, not the shipped fictional one
|
|
74
|
+
python main.py setup
|
|
75
|
+
|
|
76
|
+
# 1. what the geometry alone decides (offline, seconds)
|
|
77
|
+
python main.py intake --cavities 4 # uses the bundled sample/
|
|
78
|
+
python main.py intake --part my.stl --cavities 4
|
|
79
|
+
|
|
80
|
+
# 2. the simulations that settle the cost drivers (cloud; --offline to skip)
|
|
81
|
+
python main.py study --gate-counts 1,2,3
|
|
82
|
+
|
|
83
|
+
# 3. price every gating option, choose on total cost
|
|
84
|
+
python main.py cost
|
|
85
|
+
|
|
86
|
+
# 4. the review: apply the estimator's corrections to the shop context
|
|
87
|
+
python main.py learn --quote <key>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Every stage takes the same `--part`, defaulting to the bundled sample. The last one takes
|
|
91
|
+
`--quote` instead: it corrects a quote that already exists and never opens the geometry.
|
|
92
|
+
|
|
93
|
+
**A quote is keyed on the part's contents, not its file name.** `intake` prints a key such as
|
|
94
|
+
`clip_frame-655b895fd2b5` and every later stage derives the same key from the same file — so
|
|
95
|
+
re-exporting a part starts a new quote rather than silently pricing the new shape against the
|
|
96
|
+
old one's mesh, uploaded geometry and decisions.
|
|
97
|
+
|
|
98
|
+
Bookkeeping lands in `cache/<key>/` (`state.json`, `decisions.md`); the quote itself lands in
|
|
99
|
+
`output/<key>/quote.json`. Both are safe to delete, and only the cache costs time.
|
|
100
|
+
|
|
101
|
+
**No cloud access?** Add `--offline` to step 2: gating comes from a rule of thumb instead of the
|
|
102
|
+
solver and every artefact is marked `estimated`. The other three stages need neither a licence
|
|
103
|
+
nor a token.
|
|
104
|
+
|
|
105
|
+
## But mostly: point an agent at it
|
|
106
|
+
|
|
107
|
+
The commands above are what the agent runs. The way this is meant to be used is
|
|
108
|
+
[`PROMPT.md`](PROMPT.md) — one plain-English ask, in a session opened in this folder. The
|
|
109
|
+
assistant reads the method from [`METHOD.md`](METHOD.md); there is no skill to load.
|
|
110
|
+
|
|
111
|
+
## What's here
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
quoting/
|
|
115
|
+
├── PROMPT.md # the prompt to give the agent
|
|
116
|
+
├── INTERVIEW.md # the 20-min setup interview that builds YOUR shop context
|
|
117
|
+
├── QUOTING_PLAYBOOK.md # the method, the cost model, every gotcha (read before adapting)
|
|
118
|
+
├── AGENTS.md # how an assistant drives this template
|
|
119
|
+
├── METHOD.md # the quoting procedure, stage by stage
|
|
120
|
+
├── shop/ # THE AGENT'S OWN CONTEXT - replace with your shop
|
|
121
|
+
│ ├── shop-profile.md # what we sell, what we do in-house, house quoting rules
|
|
122
|
+
│ ├── machines.md # the press list + how to pick one
|
|
123
|
+
│ ├── materials.md # house grades, prices, the material bias
|
|
124
|
+
│ ├── tooling.md # how a mould is estimated here
|
|
125
|
+
│ ├── commercial.md # rates, scrap, overhead, margin, the ladder
|
|
126
|
+
│ └── lessons.md # corrections from real quotes + the calibration block
|
|
127
|
+
├── quoting/ # the code
|
|
128
|
+
│ ├── geometry.py # projected area, wall thickness, undercuts (offline)
|
|
129
|
+
│ ├── study.py # the cloud filling study
|
|
130
|
+
│ ├── costing.py # clamp, press, cycle, tool price, piece price
|
|
131
|
+
│ ├── shop.py / state.py # context loader; quote state, decision log, the learn loop
|
|
132
|
+
│ └── toolkit.py # reuses the kit's shared REST client + result metrics
|
|
133
|
+
├── main.py # the five stages
|
|
134
|
+
├── sample/ # the default geometry (written when the project is generated)
|
|
135
|
+
└── parts/ # drop your own geometries here
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Making the method discoverable
|
|
139
|
+
|
|
140
|
+
The procedure lives in [`METHOD.md`](METHOD.md) as a plain file, so every assistant can read it
|
|
141
|
+
rather than only the one that loads skills. [`AGENTS.md`](AGENTS.md) points at it, and opening a
|
|
142
|
+
session **in this folder** is enough for a tool that reads either file.
|
|
143
|
+
|
|
144
|
+
## How it relates to the other templates
|
|
145
|
+
|
|
146
|
+
This is the **gate-study one layer up**: that template answers *how should this part be gated*, this
|
|
147
|
+
one answers *what should we charge for it*, and uses the gating study as one input among several.
|
|
148
|
+
It reuses the kit's shared REST client and result metrics directly (`quoting/toolkit.py`) rather
|
|
149
|
+
than copying them, so both stay in step.
|
|
150
|
+
|
|
151
|
+
Prerequisites are the setup and the three sign-ins at the top of this file — and only for the
|
|
152
|
+
`study` stage.
|
|
153
|
+
|
|
154
|
+
## Read before adapting it
|
|
155
|
+
|
|
156
|
+
[`QUOTING_PLAYBOOK.md`](QUOTING_PLAYBOOK.md) — what every number rests on, the three geometry
|
|
157
|
+
estimators that are non-obvious for good reasons, why the clamp force is never taken from the
|
|
158
|
+
simulation alone, and §6 on repointing it at your own shop.
|