Release Notes

What’s shipped

Every Indolent Forge Nesting release, with the why.

Latest: v3.15.0 — 2026-09-12

v3.15.0
Indolent Forge Nesting·

Indolent Forge Nesting: a yearly license at $49.99

  • Licenses now run for a year. A license key carries its paid-through

date in plain text followed by the signature, for example 2027-09-12.<signature>. The date is covered by the signature, so it cannot be edited. Each yearly renewal emails a new key; paste it into Settings > License.

  • Clear expiry. When a license runs out, the app says "LICENSE EXPIRED -

RENEW" with the date instead of showing the trial offer, and it does not start a new trial. Activating a key that has already expired is refused, with its date and where to renew.

  • Turning the clock back cannot stretch a license. Expiry is checked

against the later of the system clock and the last day the app was seen running, and a correct clock is never penalized.

  • Old key format retired. Keys signed over the machine ID alone are no

longer accepted. None were sold.

  • The Buy License button shows $49.99 / year and opens indolent.design with

your machine ID filled in.

  • These license changes apply to Indolent Forge Nesting only.

One home screen for both builds

  • Indolent Forge Nesting now uses the same home screen as Capitol Forge:

the light 2x3 grid of tiles, including the Model Viewer. Only the logo, name and brand colors differ.

  • The theme now defaults to light on both builds; it can still be switched

in Settings.

  • The Excel Takeoff tab in the Ctrl+O import dialog now shows on Indolent

Forge Nesting too. It uses the same parser as Capitol Forge.

Behind the scenes

  • A test that checks a license key signed with the production signing key

against the public key built into the app, to run after any key or format change.

v3.14.3
Indolent Forge Nesting·

Plate nesting: parts always keep the full cutting gap

  • Fixed: two parts could be placed closer than kerf + spacing. In the

denser packer added in 6.12.1, a part that exactly filled a pocket beside another part could run to the cut line instead of leaving the cutting gap there, in one specific arrangement. The cut between the two parts would then take that missing steel off the parts themselves - up to the full gap, about 1/4" with default settings. Found in an internal review of the packer, and now pinned by tests that check the real clearance between every pair of parts, not just that they do not overlap.

  • No cost in steel. Re-measured on the same 163 real plate groups as

6.12.1: sheet bought and utilization are unchanged (5,262 sq ft, 58.5%). The fix only restores the clearance.

  • The nest result label now reads "Guillotine" rather than naming one of

the two packers, since each nest keeps whichever packed tighter.

  • Model Viewer: a closed curved STEP surface could, in rare cases, be read

as not closed and refuse its face; the seam check now tolerates the rounding that caused it.

v3.14.2
Indolent Forge Nesting·

Model Viewer: curved STEP faces are now drawn and measured

  • B-spline and NURBS faces now open. About a fifth of the faces in the

STEP files detailers send are B-spline surfaces. Until now the viewer left every one of them out and named it in the warnings, so those parts showed with holes in them and reported no volume or length. They are now drawn, along with the B-spline edges around them. This is for viewing and measuring only; STEP parts are not sent to nesting.

  • Flat faces saved as splines measure as flat. A spline whose control

points all lie in one plane is read as that plane, so a flat plate exported this way still gets its thickness and an exact face area. A spline edge whose control points lie on one line is read as a straight edge with an exact length.

  • Curved spline faces are shown as approximate. They are drawn to within

0.2 mm of the true surface, like every other curved face. Their area comes from the drawn triangles and is marked approximate, and no radius is shown for them.

  • Hairline sliver faces no longer break a part. SolidWorks can leave

faces a few thousandths of a millimetre wide where two bodies were joined. When such a face is flat to within the 0.2 mm drawing tolerance it is drawn flat through its own edge points, so the part stays closed and keeps its volume. The warnings list each one.

  • Measured on 159 real STEP files from one Capitol job: faces not drawn

went from 7,386 to 4, parts with a gap in the shell from 448 to 4, and parts with a measured length from 592 to 708. The 4 faces still not drawn are flat faces in one file whose outline doubles back on itself; they failed the same way before this change and are listed in that file's warnings.

  • Heavy files still open in seconds. In the release build the largest

file in the set (17 MB) opens in about 5 seconds and a 9 MB file in under 1 second. The slowest for its size is a 2 MB part with large curved faces, at about 4.5 seconds.

v3.14.1
Indolent Forge Nesting·

Plate nesting buys a third less sheet

  • Small plate groups no longer buy a whole 4' x 8'. Measured on 163 real

plate groups from nine Capitol KISS files, 110 groups need less than a quarter of one 4' x 8' sheet, and with 4' x 8' as the smallest option every one of them bought a whole sheet: 43% of all plate purchased, to cut 294 sq ft of parts. Auto-pick now also offers 2' x 4' and 4' x 4', which Capitol buys cut to size. This applies to KISS import, Spreadsheet import and the Plate screen presets.

  • A denser packer for shear, plasma and saw nests. The old packer laid parts

in rows as tall as the tallest part in each row, and the space above every shorter part was lost. A second packer now fills that space, still using only straight through-cuts so every sheet can be sheared. Each nest keeps whichever of the two buys less sheet, so a nest can only get better, never worse.

  • Measured on the same 163 groups: sheet bought went from 8,170 to 5,262

sq ft, and plate utilization from 37.7% to 58.5%. The packer is now within 2.5% of the densest possible layout, which could not be sheared.

v3.14.0
Indolent Forge Nesting·

Linear nesting bought more steel than it needed

  • The nester was finding the best plan and then throwing it away. Estimators

reported that results were "not always the best" and that they were nesting by hand; some stopped trusting the program. The stock-length search evaluated every combination and found plans at 93% utilization, but compared the cut length each plan placed with an exact floating-point test before it ever looked at utilization. Every plan cuts the same parts, yet kerf adds up slightly differently across different stick counts, so that test fired on rounding noise and the search kept whichever plan it had tried first — the shortest stock. The guarantee added in 6.10.2, that offering another stock length can never make the nest worse, has been inactive since that release.

  • Measured on a real job (S-26-4026, Area 0710): L6x4x1/2 went from 38 sticks

and 760 ft to 18 sticks and 610 ft (74.6% to 93.0% utilization). Across the area, 228 sticks became 186. Plans are now ranked by the total steel bought, which is the number on the purchase order.

  • Dragon nesting works again from KISS and Spreadsheet imports. Only the

Quick/Batch screen marks a group as Dragon, so on an import every group counted as non-Dragon and any 18'-6" stock was removed from all of them — the group was left with no stock and would not nest. Entering 18'-5" worked only because it fell outside the Dragon tolerance. An 18'-6" length you choose is now used unless the same run really does contain a Dragon group that needs it.

The app could not be closed (6.11.1 did not fix it)

  • The window could not close itself. 6.11.1 fixed the unsaved-work prompt,

but the call that closes the window afterwards needs a permission the app was never granted, so it was refused and the window stayed open. The permission is now granted, the prompt gives up after 10 seconds rather than waiting forever, and once you have said yes the window closes by its own route even if that call fails. A test now checks the permission so it cannot be removed unnoticed.

KISS import

  • The material list is split into Linear and Plate tabs and sorted by type,

size and grade, instead of one list in the order the detailer wrote it.

  • Plate groups can be routed to linear, as the Spreadsheet screen already

allowed; only a group whose parts have no length is refused, with the reason.

  • "Nest this" on each group nests that material on its own.
  • "Use the same stock for all linear groups" works in either order. It used

to apply only to groups already ticked, so choosing the stock first left later groups with none.

  • Linear and plate results are both shown after a run, with combined totals

that mark themselves partial when any weight is unknown.

Model Viewer (new, beta)

  • View and measure IFC, NC1, DXF and STEP files from a new Home tile. It is a

viewer: it does not nest. Nest from the KISS or Spreadsheet import.

  • IFC: reads the file's own units (SDS2 exports feet and pounds) and takes

dimensions from the model's geometry. Each part is checked against the detailer's own weight and any part that comes out light is flagged. On a real 162-ton SDS2 model: 813 parts, all carrying their properties.

  • STEP: read natively, with units taken from the file (the real Capitol STEP

files are authored in inches). On 159 real files from job D-25-2718: all open, and 38% of solids are recognised and dimensioned, up from 8% during development. Faces built from B-spline surfaces are not drawn yet and are named in the file's warnings; on those files the solid is shown with the gap and its volume is withheld rather than guessed.

  • Measure: point-to-point with X/Y/Z components, angle, edge length, hole

diameter, face area and plate thickness, with a visible indicator of what the cursor snapped to. A value that cannot be proven exact is marked with ≈ — including any hole diameter measured from a drawn circle rather than one the file states, since a circle drawn as flat segments can read slightly large.

  • Orbit, pan, zoom, section planes, hide/isolate, x-ray, render modes, model tree

and property panel.

Also fixed

  • An NC1 file with an unusual header no longer closes the app. A vendor file

with banner lines in its header crashed a third-party reader. It now reads normally, and any reader failure on a file is reported as a message rather than ending the session.

  • NC1 plate weight uses the cut area, holes deducted, instead of the

rectangle the plate was cut from.

  • Nineteen other confirm and alert boxes across the app did nothing — delete

user, delete customer, delete parts, SharePoint sign-out and others — for the same reason the close prompt failed. They now use the app's own dialogs. A prompt that cannot be shown never deletes anything.

  • The crash screen no longer promises to restore your work. Its button said

"Save Work and Reload" but nothing read the saved copy back; it now says Reload.

  • Home screen is two rows of three.
v3.13.1
Indolent Forge Nesting·

The app could not be closed

  • Fixed: 6.11.0 could not be shut down once anything was edited. The new

unsaved-work prompt called the browser's native confirm(), which the Tauri WebView does not display — it returns "no" instantly. The close handler had already cancelled the close by then, so the window ignored its own close button and the app had to be killed from Task Manager. It now uses the Tauri dialog, and every failure path ends in the window actually closing: a prompt that cannot be shown must never trap you.

  • Fixed: the same broken prompt silently blocked other actions. Opening a

saved project, importing a nest file, New, and the back arrow all asked the same invisible question and took the silent "no" as an answer, so they simply did nothing when there were unsaved changes.

v3.13.0
Indolent Forge Nesting·

Plate weights were wrong on every KISS import — fixed

  • A 2″ plate reported the same weight as a 3/8″ plate. Every purchased sheet from a KISS

import was weighed at 1/4″ regardless of its real thickness, because the KISS stock candidates carried no thickness and the nester filled the gap with a silent 6.35 mm default. The description still printed the correct thickness, so the row looked right and the weight was off by up to 8×. A 48 × 96 sheet now reports 2,613 lb at 2″ and 490 lb at 3/8″, as it should.

  • The same path also threw away the grade. A572-50 plate was requisitioned as A36. The

bucket's real thickness and grade are now stamped onto the stock before nesting, matching what the spreadsheet path already did.

  • An unknown thickness is now reported as unknown, not priced as 1/4″. Weights that cannot be

computed show a dash and set the "partial" marker instead of printing a confident wrong number.

  • The manual per-group stock path no longer passes the whole size string ("2X48") as the

thickness label, so the requisition reads PL 2" plate x 48 x 96 A572-50.

Nest switching no longer crashes or ejects you from the project

  • "missing required key algorithm" is fixed. A single Ctrl+Z replaced the entire settings

object with a two-field stub, so the next nest run failed at the IPC boundary. Undo now merges each slice back instead of replacing it, and every nest parameter has a fallback.

  • Ctrl+Z while typing no longer rolls back the whole job. The global shortcut ignored text

fields, so fixing a typo in the job number silently corrupted the session.

  • Undo no longer destroys a finished nest. Results, the imported KISS file path, and the

active view are no longer rolled back by an undo of a part edit.

  • "New" recovers a corrupted session, and opening a saved project clears the previous

project's undo history instead of splicing its parts into the one you just opened.

Material that was silently disappearing

  • Bulk hardware is no longer dropped on import. Detailers leave the piece mark blank and the

length at zero for bolts, nuts, washers and epoxy; the parser rejected those rows outright. One real Capitol job lost 36 lines / 752 pieces of A325 bolts and HILTI epoxy before the buyer saw the requisition. Those rows now import against the assembly mark, and anything still rejected is listed on screen instead of vanishing.

  • Customer free-issue plate no longer appears on the buy list — the shop was re-buying steel

the customer had already supplied.

  • The plate cut sheet now shows parts that could not be nested, so a shortage reaches the floor.

Nesting correctness

  • A 2″ part can no longer be nested onto a 3/8″ sheet. The plate nester now segregates sheets

by thickness and grade; a group with no sheet of its own material is reported as a shortage rather than burned out of the wrong plate.

  • A one-off remnant is cut once. A single 10′ drop on the rack was being used as an unlimited

stock template and could be cut twice in the same nest.

  • "Prioritize remnants" now works on every algorithm, not only First Fit.
  • Shortages are counted in pieces, not rows — 30 missing pieces used to read "2 parts".
  • Plate sheet order is deterministic, so re-running the same nest does not reshuffle sheet

numbers between the screen and the PDF.

Weights and quantities on documents

  • BOM weights were doubly wrong — shape-database lb/ft was stored as kilograms-per-piece,

never multiplied by length, then converted again for display.

  • Requisition structural rows no longer mis-split hyphenated sizes; L2-1/2X2-1/2X3/16 A36

now resolves its size and grade correctly, so the per-stick weight lookup works.

  • Excel takeoff import reads the GRADE column instead of stamping A36 on every part.
  • Unknown piece weights print as a dash, not zero, on the shipping ticket, and partial totals

are marked rather than presented as complete.

  • Import auto-nest reports the nested stock count, not a pre-nest estimate that under-ordered.
v3.12.3
Indolent Forge Nesting·

Dragon 18′-6″ linear boundary fit fixed

  • Exact-length Dragon parts no longer get rejected when independent unit conversions differ by floating-point rounding drift.
  • The tolerance is applied consistently across First Fit, Best Fit, and Worst Fit linear nesting, including the simple nesting workflow and its preflight warning.
  • Regression coverage verifies the 18′-6″ boundary for all three algorithms while still rejecting meaningful over-length parts.
v3.12.2
Indolent Forge Nesting·

Linear nesting now ranks the completed job first

  • Selecting more purchased stock lengths can no longer make the nest worse. The engine previously scored only the next stick it was about to open. A locally attractive stock length could strand the final pieces and force another stick, even when a different selected length completed the whole job with much higher utilization.
  • The completed nest now decides the winner. For the normal stock catalog, every selected-length combination is nested and compared. The ranking places all possible parts first, then chooses the highest overall material utilization, then the lower stick count. The same stock-ranking gate covers First Fit, Best Fit, and Worst Fit in Quick, Batch, Spreadsheet/KISS, and Advanced linear nesting.
  • Regression case: one 10′ part plus three 4′ parts with 20′ and 25′ stock previously returned two 20′ sticks at 55% utilization. It now returns one 25′ stick at 88% utilization. Automated tests enforce that result across all three linear algorithms.
v3.12.1
Indolent Forge Nesting·

Notes

_This one is for you, Juan._

Shear now nests at true zero kerf — on every screen

  • A shear cut removes no material, so shear nests now force zero kerf no matter what kerf is set or which screen you nest from. Previously one entry point (the Plate view's own Nest button) leaked the 1/8″ saw kerf into shear spacing, so two exact-fit 24″ parts wouldn't share a 48″ sheet — one spilled onto a second sheet. Now they tile the sheet the way the blade actually cuts it (and the way ROMAC nests it). Enforced at the single backend point every plate path routes through, so no screen can get it wrong.

Grade and material dropdowns no longer get cut off

  • The whole list shows. The Grade and Material-type pickers in Linear, Plate, Spreadsheet, and Pro nesting were being clipped by the scrolling panel around them — near a panel's edge the box couldn't fully open. They now render above the panel so the full list is always visible and scrollable, in both light and dark themes.
v3.12.0
Indolent Forge Nesting·

Shear and Estimate are now truly zero-loss

  • Exact-fit parts nest. A 37.125″ × 120″ part now shears from a 48″ × 120″ sheet (one rip cut) or a 37.125″ × 144″ sheet (one crosscut). Shear and Estimate no longer apply part spacing or edge margin — the shear blade removes nothing, parts share cut lines, and the mill edge is the part edge. Previously the default 1/8″ spacing + 1/4″ margin silently shrank the sheet and rejected exact-fit parts even at kerf 0.
  • Shared cut lines. Two 24″ rips now fit one 48″ × 120″ sheet at kerf 0 instead of spilling onto a second sheet.
  • Plasma and Saw keep their spacing and edge-margin clearances — the torch still needs them. The Settings panel now says which cut types each setting applies to.

KISS planning exports

  • Material Summary (Excel). One click from KISS nest results: a per-item rollup — material, grade, length, quantity, weight each and total (lb), and the part marks on each line — with grand totals.
  • Shipping Summary (Excel). Per-assembly loading sheet grouped by sequence: assembly mark, piece count, description, overall dims, weight each and total, per-sequence subtotals, and total tonnage. Weights come from the built-in AISC shape database; anything the database can't weigh is footnoted, never silently zeroed.
v3.11.0
Indolent Forge Nesting·

Cut sheet PDF — small jobs print on one page

  • No more two-page printouts for small nests. When the cut breakdown fits under the cover summary, it continues on page 1 with a compact layout instead of always starting a second sheet. Multi-material and large jobs paginate exactly as before.
  • Fixed a fraction glitch where a drop total could print as 44'-10 0/1".

Simple nesting accuracy + polish

  • The algorithm dropdown now tells the truth. It previously always displayed "First Fit Decreasing" regardless of the active algorithm; it now shows and stores the real selection.
  • Stock lengths parse like part lengths. A bare number is inches everywhere (the old stock parser read 396 as 396 feet); 40', 32'-6", 12-6, ROMAC 1-15/16, and 400mm all still work.
  • Order summary handles mixed stock lengths. A material group that mixes 20′ and 40′ sticks now lists each length ("3 × 40′, 2 × 20′") instead of pretending every stick matches the first.
  • Oversized parts warn out loud. Parts longer than the longest stock now raise a warning toast before the nest runs (they previously only logged to the developer console).
  • Same input, same output. Nest results, cut sheets, and exports no longer reshuffle their material/stick order between identical runs.
  • Waste tile no longer shows NaN% when nothing nests.

Forge Welding hidden

  • The Forge Welding (QMS) section is hidden for now — no longer in day-to-day use. All code and data remain; it can be re-enabled in a future build.
v3.10.1
Indolent Forge Nesting·

Customer material — now per shape on the spreadsheet nest

  • Assign stock per shape, all on one screen. On the Spreadsheet nest's Linear tab, every material shape (e.g. HSS10X2X3/16, W24X104) now has its own stock card showing its piece count and total footage. Each card takes the customer-supplied sizes + quantities for that shape and its own purchased fallback lengths — so a takeoff with a dozen different materials no longer forces you through a single dropdown one shape at a time.
  • Purchased lengths are per shape too. Different shapes can buy different lengths (W-shapes vs small HSS). An Apply to all quick-set seeds common purchased lengths across every shape in one click, and a Hide shapes with no stock toggle keeps a long list manageable.
v3.10.0
Indolent Forge Nesting·

Customer-supplied material — nest on what the customer sent

  • Enter the exact material the customer supplied, per shape. Every nesting view — KISS import, manual linear, plate, and the spreadsheet nest — now has a green Customer-Supplied Material (free issue) panel where you list the specific sizes and quantities you were given (e.g. 2 × 40′, 3 × 60′, 1 × 10′ of W6×12, or three 48″ × 96″ sheets). The nester uses up that material first, then nests whatever is left over on purchased stock.
  • The purchase requisition only orders what you actually buy. Customer-supplied sticks and sheets are excluded from the requisition and the order summary — they're free issue, not purchased — so your buyer never re-orders steel the customer already provided.
  • See what's free vs. bought at a glance. Nest results badge each stick and sheet Customer (green) or Buy (amber) whenever a job mixes the two, so the shop and the office can tell free-issue material from purchased at a glance.
  • Finite by default, with a clean fallback. Customer material is treated as a finite count — when it runs out, the remaining parts nest on purchased stock automatically (plate spillover auto-picks the best standard sheet). If you only have customer material and it's short, the leftover parts show up as a clear shortage instead of silently over-using stock.
  • Nothing changes if you don't use it. Leave the panel empty and nesting behaves exactly as before.
v3.9.17
Indolent Forge Nesting·

Spreadsheet import — one reliable engine for every takeoff

  • The preview now matches the import. Previously the importer ran one engine for the preview you approve and a different, more rigid one for the actual import — so a takeoff that looked right in the preview could come in wrong or partly empty. Both now run the same robust engine: what you see is what you import.
  • Reads real-world takeoff variety. Finds the header row wherever it sits (not just the top row), picks the data sheet by its content (not a fixed name like "Takeoff"), and understands varied column layouts — both PART MARK / LENGTH / PROFILE part-mark takeoffs and the WIDTH / FT / IN / CLASS master-takeoff layout.
  • Correct quantities and lengths. Honors the M QTY mark multiplier (4 of a mark = 4 pieces), and a single inch-based LENGTH column is read as inches — a 73″ part no longer comes in as 73 feet.
  • Plates classify as plates. PL1/8-style thickness is parsed even when it only appears in the part description, so plates carry their thickness and weight and group correctly instead of dropping into buy-out.
  • Calmer messages. The "Cover Sheet not found" note and skipped blank/subtotal rows are now quiet info rather than alarming errors, and a totals row no longer shows up as a phantom buy-out line.
v3.9.16
Indolent Forge Nesting·

Removed the phone-QR / cloud-sharing option

  • The experimental "Share / View on phone" QR and cloud-sharing toggle introduced in 6.7.15 (off by default) has been removed. The Purchase Requisition export is unchanged and remains fully supported.
v3.9.15
Indolent Forge Nesting·

Purchase requisitions, straight from a nest

  • Generate a printable purchase requisition (Excel) from any nest. A new Requisition button on every result view (plate, grouped plate, linear, and the spreadsheet view) turns the current nest into a clean purchase-requisition workbook — plate, structural, and buy-out sections, each grouped by grade/thickness, with quantities, weights and tonnage, and an optional $/lb column that totals line-by-line into a subtotal and grand total. A "PURCHASING TO COMPLETE" block leaves room for the buyer to fill in pricing and vendor.
  • Smart, remembered prompt. The requisition dialog pre-fills the requestor, job number, and date, and remembers them next time. Pick the job type (plate / structural / pipe / misc / duct / engineering) and it derives the rest.
  • Per-job requisition numbering. Each requisition is numbered Requisition 001 - P-26-2222 — a per-job sequence that restarts at 001 for each job, with the job type and number shown. The dialog shows a live preview of the next number, and every exported requisition is logged in a registry so the count stays reliable.

Share a nest to your phone (opt-in)

  • A "Share / View on phone" button + scan-to-view QR. Turn on cloud sharing in Settings and any nest can be uploaded to a private link and rendered on a phone — the plate sheets, shear sequence, and master summary, no login required. The QR can also be stamped onto the requisition Excel and the plate cut-sheet PDF. Off by default — nothing leaves the machine unless you enable it.

Polish

  • The requisition dialog is fully legible in both light and dark themes (proper dark panel in dark mode).
  • Dragon-stock material names no longer leak their parenthetical into the requisition grade — a W6X12-A36 (DRAGON 18'-6") row now reads grade A36.
  • Hardened nest sharing against malformed input (it returns an error instead of crashing the share command).
v3.9.14
Indolent Forge Nesting·

Plate nesting gets a master summary

  • A master summary now leads every plate nest — on screen, and as page 1 of the PDF and the first sheet of the Excel export. Length nesting already opened with an at-a-glance rollup; plate nesting now does too: sheets used, parts nested, overall utilization, total weight, and drop/waste, plus a "sheets to purchase" order table (size · thickness/grade · weight each · total) and a usage breakdown (gross / net / drop sq ft). The on-screen panel, the PDF first page, and the Excel Summary sheet are computed from one shared calculation, so the numbers always agree.
  • "By Material" rollup. Mixed-material jobs get a per-grade/thickness breakdown — sheets, parts, utilization, drop area, and weight per material — on screen and in both exports.
  • Truer numbers. Plate utilization and net area are now measured from the actual placed-part areas rather than an efficiency estimate, and total weight is honest about unknown-thickness sheets (shown with a "≥" marker instead of silently undercounting).
  • Plate Excel now uses shop-floor fractions. Plate dimensions in the Excel export are fractional inches (e.g. 14 11/16") to match the cut sheets and the linear export, and the Summary sheet is set to print first.
v3.9.13
Indolent Forge Nesting·

Share a nest, and a real Saved Projects manager

  • Export a saved nest to a file and share it. Any saved project can be exported to a single .cfj (Capitol) / .ifn (Indolent) file that carries the full nest — parts, stock, settings, job info, and the computed result. Hand it to a coworker, and they Import it back as their own local copy (a fresh project — no ID collisions). The file is a versioned, self-contained snapshot, so it stays readable as the app evolves.
  • New "Saved Projects" manager. A folder button in the header (and a "View all" / "Manage saved projects" link on the home screen) opens a searchable list of all saved projects — not just the 5 most recent. Open, rename inline, delete, export, or import, all from one place.
  • Home screen scrolls again. With several saved projects listed, the home screen no longer pushed the logo off the top with no way to scroll back — the page now scrolls properly and stays centered when short.

Cleanup

  • Removed three orphaned legacy "Job" UI files (JobHistoryPage, and the unused layout Sidebar/Header) that the current app no longer rendered.
v3.9.12
Indolent Forge Nesting·

Installers are now code-signed

  • Windows installers are now digitally signed via Azure Trusted Signing (publisher: Blake Holmes), replacing the "Unknown Publisher" prompt. No application changes in this release — the build is functionally identical to 6.7.11, but the .exe and .msi now carry a verified Authenticode signature. (Addresses pre-release audit finding REL-002.)
  • Note: Windows SmartScreen builds trust per-file as downloads accumulate, so the first signed installers may still warn until reputation is established; the warning fades over time.
v3.9.11
Indolent Forge Nesting·

Spreadsheet import — one engine for every sheet, and fixable column mapping

  • Every spreadsheet type now classifies through the same dimensional engine. Plain takeoff sheets (not just Material Summaries) get the width+length+thickness ⇒ plate logic, recognized profiles ⇒ linear, and everything else ⇒ buy-out. A "Sheet 18 x 18 x 1/4" row is a plate and a "GASKET" row is a buy-out on any sheet you drop in.
  • Editable column mapping. If auto-detection reads a column wrong, fix it right in the Confirm-Import preview: every detected column's role is now a dropdown (including "Ignore"), the Found-N-linear/M-plate/K-buy-out counts update live as you change roles, and the import honors exactly what the preview shows. "Reset to auto" puts it back.

Dark mode, done properly

  • One theme switch for the whole app. The Forge Welding hub now follows the main light/dark toggle (its own toggle flips the same global setting), instead of keeping a separate hidden theme. "System" mode tracks live OS theme changes.
  • All remaining unthemed components converted to the themed palette — no more light-on-light panels in dark mode — and a build check now prevents unthemed styling from coming back.

Hardening (from the June full-system audit)

  • Plate cut-sheet PDF export can no longer crash on a malformed dimension (NaN-safe rendering).
  • The QMS access-policy command is now admin-enforced server-side, not just hidden in the UI.
  • Releases now fail fast if the git tag doesn't match the version files — a mis-tagged release can no longer silently publish the wrong version.
  • Lint checking (clippy) added to CI; a stale API-key secret removed from the release build environment.
  • EULA and LICENSE added at the repository root (attorney review pending before first commercial sale).
v3.9.10
Indolent Forge Nesting·

Notes

> Note: 6.7.9 / 3.9.9 was tagged but its installers never published (GitHub Actions billing outage); this release carries both versions' changes.

Pro DXF Nesting — production-ready overhaul

The Pro DXF Nesting tool went from an estimating preview to a production-ready nester:

  • Reads your DXF files correctly whether they're drawn in inches or millimeters ($INSUNITS honored, plus a manual units override), and handles slots, rounded corners, and curved cutouts from Tekla/SDS2/AutoCAD without distorting the shapes (polyline bulge support, adaptive to the Curve Tolerance setting — which now actually does something).
  • One messy file no longer sinks the batch — a bad part is flagged on its own with a reason; the rest still nests.
  • Reproducible nests: every result has a "Nest #" that re-runs to the exact same layout, plus a Re-roll button to try alternatives. Free rotation is now real (continuous), and the time limit setting now drives a multi-start search that keeps the best layout found.
  • Live progress with a Cancel button instead of a frozen spinner.
  • Small parts nest inside the holes of larger parts to save material (shown dashed in the layout).
  • Preview every imported part as a thumbnail before nesting; zoom and pan the results canvas.
  • Cut-ready DXF export — one DXF per nested sheet (SHEET / CUT / LABELS layers) ready to send to the table; round-trip verified.
  • To-scale layout drawings on the Pro PDF and material cost rolled up when you enter a price per pound.

Plate nesting PDF — order summary, horizontal layouts, proper pagination

  • ORDER SUMMARY on page 1: what stock to buy — qty, sheet size, thickness/grade, weight each and total, with overall utilization.
  • Layout plots draw the sheet horizontally (long axis along the page) — a 120"×480" plate renders as a full-width band instead of a tall strip clipped at the page bottom.
  • Proper multi-page flow: long tables and plots page-break cleanly above the footer instead of overprinting it.

Quieter import warnings

  • "Weight not found" notices no longer clutter spreadsheet-import warnings (weight lookup is best-effort enrichment, not an error).
v3.9.9
Indolent Forge Nesting·

Forge Welding — Microsoft Graph health check + SharePoint write-access readiness (Capitol)

  • New "Graph health" panel in the Forge Home Base admin cockpit: one click runs every Microsoft 365 call the hub makes — sign-in, permissions, SharePoint site/library, QMS folder read, welding-file scan, file download, Planner, profile photo, and the write path — with each check streaming into the panel live as it completes, timed, in plain English.
  • SharePoint write access now turns itself on. The moment the M365 admin grants consent, the app upgrades the existing sign-in to write scope automatically — no re-sign-in, no reinstall. Until then, the panel shows a guided 3-step setup (Open consent page → grant Edit on the Quality folder → re-check) with buttons that open the right pages directly.
  • Graph reliability hardening: site/folder/upload calls now retry on throttling (429/503 with Retry-After) like the rest of the sync path; folder names with # or parentheses (e.g. WPS-PQR (W.I.P), #10 Hewitt) are encoded correctly in folder listings; and a routine token refresh can no longer silently drop an upgraded write scope.
  • Health-check scan is capped for speed (~10 seconds end-to-end instead of ~35); real syncs still crawl everything.
v3.9.8
Indolent Forge Nesting·

Spreadsheet plate nesting now groups by grade + thickness

  • Imported plates are nested per (grade, thickness) group, each on its own stock. Previously the Plate tab threw every plate at a single stock size — so a 1/2" A36 part and a 3/8" A572 part were treated as nestable together, which isn't physically possible. Now plates are split into nesting groups by grade and thickness (e.g. 1/2" A36 and 1/2" A36 MOD are separate groups), and each group is nested on matching stock.
  • Each group auto-picks the most efficient standard sheet size (the same auto-pick engine the KISS import already uses), with an optional per-group custom width × height override.
  • Results render per group — each group shows its chosen sheet size, yield, sheet count, and per-sheet cut breakdown, with its own Excel/PDF export.
v3.9.7
Indolent Forge Nesting·

Dark-mode logo polish

  • The logo now renders cleanly in both light and dark mode. It uses transparent vector logos in each theme (dark-grey mark on light backgrounds, near-white mark on dark) — no more white box behind the logo in dark mode, and the "CAPITOL ENGINEERING CO." wordmark is crisp (the old dark logo drew it as live Gotham text, which fell back to a serif since the font isn't bundled).
  • The logo no longer disappears when toggling between light and dark. Both logo variants are now kept loaded and only their visibility is switched, instead of swapping a single image's source (which forced a re-fetch that blinked — or in some cases dropped — the logo on every theme switch).
v3.9.6
Indolent Forge Nesting·

Spreadsheet import — plates classify correctly, plus nesting + preview fixes

A focused follow-up to 6.7.5 after testing against more real detailer files.

  • Plates labeled "Sheet" (and any rectangle) now classify as Plate. Classification is now dimensional, not keyword-only: a row with a width + length + thickness is a plate no matter what the material column calls it ("Sheet", "PLT", a bare PL3/8x2 7/8, etc.). On a real file this moved 76 plate parts out of the Linear tab and into the Plate tab, where they belong. Recognized structural profiles (W, L, C, MC, HSS, pipe, bar) go to Linear; everything else (bolts, flanges, gaskets, hardware) goes to the Buy-out list — nothing is dropped.
  • Gauge thickness (10GA, 16GA) and feet-apostrophe lengths (10', 5'-6", 3'3.875") now parse.
  • The import and the preview now use one classifier, so the "Found N linear, M plate, K buy-out" preview count always matches what actually imports.
  • Redesigned the Confirm-Mapping preview. It now shows every detected column with its role at a glance, a larger data grid (more rows, sticky header, no metadata clutter), and a wider layout.
  • Custom plate stock sizes. The plate nester's stock input now lets you enter a custom width × height × thickness × grade (plus quick-pick standard sizes, thicknesses, and grades) and add as many as you need.
  • Print/Export the Buy-out list as a PDF or Excel file — not just view it.
  • Easier Linear ↔ Plate switching with a prominent segmented toggle.
  • Quieted "weight not found" notices — they were best-effort enrichment, not import errors, and shouldn't clutter the warnings.
v3.9.5
Indolent Forge Nesting·

Spreadsheet import — now reads almost any Excel sheet, plus a dark-mode toggle

A ground-up hardening of the Excel/Material-Summary importer so it reliably finds the items to nest no matter how the spreadsheet is laid out.

  • No more truncation on blank rows. A blank/spacer row in the middle of a sheet used to silently drop everything below it. The importer now reads the whole sheet — on a real detailer Material Summary this went from 1 part to ~80.
  • Columns are matched by name, not position. A new synonym-aware detector finds Qty / Material / Length / Width / Thickness / Grade / Mark wherever they are and whatever they're called (e.g. Pcmk = piece mark), so files with a different column order or naming import correctly.
  • Understands shop dimensions. Feet-inch shorthand (2-0 1/2, 15-4, 8 1/16) and plate sizes embedded in the material string (PL3/8x2 7/8) are parsed correctly.
  • Always-on Confirm-Mapping preview. Every import first shows which sheet, header row, and columns were detected, plus a “Found N linear, M plate, K buy-out” summary — confirm or cancel before it commits.
  • Nothing is dropped. Non-nestable buy-out items (gaskets, bolts, safety gates, hardware) are surfaced in their own list instead of being discarded.
  • Light/dark theme toggle. A sun/moon button in the top-right switches between light and dark mode; your choice is remembered on reload. Capitol defaults to light, Indolent to dark.
v3.9.4
Indolent Forge Nesting·

Nesting — shop cut lists read in fractions, never decimals

  • Cut lengths under a foot now show as fractions. Short cuts that used to print as a decimal inch (e.g. 6.50", 0.94") now read the way the shop measures off a tape — feet-and-inches to the nearest 1/16" (6 1/2", 0 15/16"). Fixed everywhere a cut length appears: the on-screen results, the cut-sheet PDF, and the Excel cut list now all match exactly.
v3.9.3
Indolent Forge Nesting·

Notes

Internal (Capitol) changes only; the Indolent build is unchanged.

v3.9.2
Indolent Forge Nesting·

Notes

Internal (Capitol) changes only; the Indolent build is unchanged.

v3.9.1
Indolent Forge Nesting·

Notes

Internal (Capitol) changes only; the Indolent build is unchanged.

v3.9.0
Indolent Forge Nesting·

Fixed

  • 6-month continuity now loads after a sync. The sync ingested continuity into the database but only refreshed the overview, leaving the Continuity view blank until a remount — it now refreshes continuity, welders, coverage, and the uncertified list after every sync.
  • Authorization hardened. Saving evaluations and adding/updating/archiving employees now require an administrator (they were reachable without an admin check); the Lotipac write tools are gated the same way.
  • Curation is now respected in the By Welder grid, Profile, and Data Health (previously only the welder drill-down filtered curated certs).
  • Cross-machine presence no longer resets a user's first-seen time on a transient network error, and two similar emails can no longer collide onto the same presence file.
  • The Continuity view now surfaces a real load error instead of showing it as an empty "no data" state.

All changes verified: 527 Rust unit tests pass, frontend type-check + build clean, and a six-reviewer audit (with adversarial verification) of the new code was completed and its findings fixed before release.

v3.8.0
Indolent Forge Nesting·

Notes

Internal (Capitol) changes only; the Indolent build is unchanged.

v3.7.0
Indolent Forge Nesting·

Notes

Internal (Capitol) changes only; the Indolent build is unchanged.

v3.6.2
Indolent Forge Nesting·

Fix — Material Summary imports keep rolled shapes (angles, beams, channels)

A Material Summary lists rolled shapes (e.g. L3x3x0.375, W14x68, C10x15.3) with the profile in the Material column and no plate width — they're cut to length, not a rectangle. The 6.4.1 importer dropped every such line as "zero width" (on one real job that was ~146 parts, including heavy members). The importer now recognizes AISC shape designations and routes them to linear nesting by length, while plate still requires width + length. So a mixed summary now splits cleanly: plates per thickness, shapes per profile.

v3.6.1
Indolent Forge Nesting·

Fix — Material Summary recognized by the regular Excel import

The detailer Material Summary importer (added in 6.4.0) now also works from the spreadsheet import and the main Import dialog — not just the Plate view's dedicated button. The Excel import auto-detects a Material Summary and routes it to the right parser, grouping by material (plate splits per thickness) and feeding the existing linear/plate split + dual-nest flow. The Excel Takeoff parser is unchanged — this is purely additive, so takeoff-template files import exactly as before.

v3.6.0
Indolent Forge Nesting·

Estimator workflow — dropdown, exports, B&W PDFs, Material Summary import

Material Type dropdown is keyboard-first. In batch linear entry, typing a shape's short code now selects that shape — L → Angle (it used to land on Wide Flange because a label-substring match beat the code). Added an alias map (W/WF, L/ANG, HSS/TS/TUBE, PI/PIPE/P, FB/FLAT, PL, RD/RB/RND, SB/SQ, RE/REBAR/#), a new Rebar shape, `RD` as Round Bar's primary code, a per-row code badge, and ≥44px rows for tablet use. (19 unit tests.)

Exports open in your PDF viewer. Every PDF/Excel export now opens the saved file in your default app (via tauri-plugin-opener) and shows a confirmation toast — across simple nesting, length nesting, pro nesting, proposals, and BOM. No more wondering whether the file saved.

Black & white PDFs. A new line-art B&W mode for cut-sheet and plate PDFs — white-filled parts with black outlines + labels, grayscale headers/tables — set as a global default (Settings) or a per-export checkbox. Friendly to shop printers.

Import detailer "Material Summary" Excel files. A new importer reads detailer Material Summary xlsx exports (Ln / Qty / Material / Thickness / Width / Length / Weight / Grade) directly into plate nesting — fractional inches and job / sequence / area metadata included. "Import Material Summary" button in the plate view; warns on mixed thicknesses and zero-dimension lines.

Tests

443 Rust library tests pass (up from 425): +8 ColorMode, +10 Material Summary parser. Frontend: +19 material-type ranking tests (node:test).

v3.5.3
Indolent Forge Nesting·

Customer-reported fix bundle

Plate fractions like 1/2", 1/8", 3/16" no longer round up to 1". The parseLengthToMm parser had no regex for bare fractions (no whole number, no inch mark). When a user typed 1/2 into any length/thickness field, the parser fell through to the parseFloat("1/2") fallback — which returns 1, not 0.5. Result: every sub-inch fraction silently parsed as its numerator, making 1/2" plate land as 1" plate. Added Pattern 4.5 for bare fractions that runs before the decimal fallback, plus 6 regression tests locking in 1/2 → 0.5", 1/8 → 0.125", 3/16 → 0.1875", 15/16 → 0.9375", inch-mark tolerance, and identity between 1/8 and 1/8". This is the same class of bug captured in the earlier feedback note about 1-15/16 shorthand — parseLengthToMm is now correct on both the mixed and bare fraction forms.

Multi-row batch entry shows full shape names instead of one-letter codes. The Batch ("Mixed Materials") entry surface in simple nesting was passing compact={true} to the material-type combobox, which rendered just the shortcut code (W, L, C, PL, HSS) inside an 80px-wide column. Customers couldn't tell at a glance which row was set to which shape. Dropped the compact prop and widened the Type column to 150px (recovered from Mark/Length/Grade columns to keep total row width the same). Selected shape now reads Wide Flange, Channel, Angle, Plate — full label at the same 16px text. The four sibling tables (PartsTable, StockTable, BatchCutEntry, ProStockSelector) were already rendering full labels — no change needed there.

Tests

26 frontend unit tests pass (up from 20). 425 Rust library tests pass (unchanged from 6.3.2). New frontend tests:

  • 1/2 parses as 0.5" (bare fraction, no whole number)
  • 1/8 parses as 0.125" (smallest common plate thickness)
  • 3/16 parses as 0.1875"
  • 15/16 parses as 0.9375"
  • inch mark tolerated on bare fraction: 1/2"
  • 1/8" parses identically to 1/8

Known issue under investigation — Capitol Slevin chat

A Capitol customer reported that the Slevin Claude chat was not responding. The desktop client code path (commands::ai::chat_with_claude, the Railway proxy URL, the X-Install-Token auth) was reviewed end-to-end and is intact — no client-side regression in 6.3.0/6.3.1/6.3.2. The suspected root cause is a Railway env-var configuration issue (ANTHROPIC_API_KEY reset that did not redeploy, or saved under a different name). A diagnostic script for discriminating server-side vs client-side is in the release notes.

v3.5.2
Indolent Forge Nesting·

Security + correctness — senior-review fix bundle

Post-release audit of the 6.3.1 / 3.5.1 ship (RAG-augmented Slevin + jagua-rs Pro Plate) surfaced five engineering issues. All fixed in this patch.

Indolent installer no longer ships Capitol QMS files. The bundle resource glob in tauri.indolent.conf.json was knowledge/*, which depending on the Tauri bundler's glob expansion could include the knowledge/capitol/ subdirectory. The runtime FTS gate already skipped those files for Indolent, but the raw .md source would still sit on disk in the customer's install directory. Tightened to knowledge/*.md — explicit extension, single segment, no subdirectory recursion. Capitol's bundle config is unchanged.

Indolent "offline" claim is now honest. The Indolent CSP connect-src previously whitelisted api.anthropic.com, Microsoft Graph, SharePoint, and Microsoft Login — Capitol-internal origins that an Indolent customer should never reach. Reduced to connect-src 'self'. Any future XSS, accidental fetch, or third-party SDK that tries to phone home from an Indolent build now fails closed at the browser level.

Crash hardening in jagua-rs adapter. pro_nesting/jagua_adapter.rs had an expect("solver returned unknown container id") that would panic the app if the solver ever returned a container_id outside the supplied bins slice. Replaced with a bounded match that logs and skips the bad snapshot.

FTS5 query no longer crashes on inch-mark quotes. A user typing a callout like W14X22" (one unmatched ") used to produce a malformed FTS5 phrase query, surfacing as a SQLite syntax error in the chat panel. sanitize_query now strips quotes when the count is odd, so unmatched quotes degrade gracefully to bare-word search.

RAG context dedup. chat_with_claude was passing all 5 FTS hits to the system prompt without deduplicating — the OR-augmented query can return the same chunk via multiple matches, wasting tokens and producing duplicate citations. Now deduped by chunk_id before prompt composition.

Prompt-injection hardening on nesting context. Part marks, stock labels, and notes (all user-typed into the simple-nesting UI) used to flow verbatim into Claude's system prompt. A part mark of \n\nIgnore previous instructions could escape its context block. Added sanitize_for_prompt(): strips control characters (including newlines), caps each field length, and caps list entries at 50. Steel-fab punctuation (/, x, ", °, parens) is preserved — denylist, not whitelist.

Working tree hygiene. .gitignore now covers installers/ (local build output) and .playwright-mcp/ (Playwright MCP cache).

Tests

425 library tests pass (up from 417). 8 new:

  • sanitize_for_prompt_strips_newline_injection — newlines dropped from

injection text while content survives

  • sanitize_for_prompt_caps_length — field length cap enforced
  • sanitize_for_prompt_keeps_steelfab_punctuation — fractions/dimensions/

callouts pass through untouched

  • nesting_context_fields_are_sanitized_in_prompt — end-to-end: injection

text in a part mark never lands on its own prompt line

  • nesting_context_caps_list_length — 500-entry parts list capped at 50
  • dedup_hits_removes_duplicate_chunk_ids — RAG dedup by chunk_id
  • sanitize_strips_unmatched_quotes_to_avoid_fts5_syntax_error — odd-count

quotes stripped at sanitize time

  • search_returns_empty_not_error_on_unmatched_quote — end-to-end search

with unmatched quote returns Ok, not SQLite syntax error

Carry-forward P0s — status

  • SEC-001 (CLAUDE_API_KEY embedded in .exe) — resolved in 6.2.0,

reconfirmed: build.rs no longer uses option_env!, all AI requests route through the Capitol Production Center proxy.

  • SEC-003 (Ed25519 placeholder license pubkey) — resolved in 6.2.2,

reconfirmed: licensing/verify.rs holds the production pubkey paired with the website-side LICENSE_SIGNING_KEY_B64.

  • REL-002 (code-signing certificate) — still open. SmartScreen will

block every Indolent install until this lands.

  • REL-004 (LICENSE / EULA at repo root) — still open. Legal exposure

for commercial sale.

v3.5.1
Indolent Forge Nesting·

Tests

417 library tests pass (up from 409). New coverage:

  • services::knowledge_search::capitol_qms_gated_by_variant_flag — asserts

Capitol indexes exactly 6 more files than Indolent, all under capitol/ path prefix with capitol-qms tag

  • 7 new commands::ai::tests::* cover system prompt shape, RAG block

rendering, nesting context injection, FTS fallback path, augmented query construction

v3.5.0
Indolent Forge Nesting·

Pro Plate Nesting — real polygon nester, no longer Beta

The hand-rolled 620-LOC grid-scan nester is gone. Pro Plate Nesting now runs on jagua-rs 0.7.2 — a research-grade no-fit-polygon collision engine — driven by the vendored LBF reference solver. Real polygon packing, real rotation, real swap heuristic. Yields on irregular DXF parts go from "naive grid scan" to "industry-quality nest" without asking customers to learn anything new.

  • "Allow rotation" toggle (default ON) — parts rotate 0/90/180/270°

to fit. Off keeps original orientation if you have shop reasons.

  • "Quality" preset — Fast / Balanced / Best — trades solver time

for tighter packing. Fast = quick quote. Best = ship-ready nest.

  • Beta banner removed from Pro Plate Nesting view. It's a real

feature now.

  • The public nest_parts() signature is unchanged, so PDF export, the

Konva canvas, all five Pro Plate Tauri commands, and DXF/KISS input paths continue working with zero migration.

Math: 547 LOC of the old algorithm deleted, replaced by a 340-LOC translation layer + the vendored LBF solver (~600 LOC, MPL-2.0).

Slevin — offline AI that knows steel

The chat panel is now powered by Slevin, a local-only RAG system over a curated steel-fab knowledge base. No Anthropic API. No cloud. No subscription. Slevin's entire knowledge base ships inside the installer and is searched via SQLite FTS5 with BM25 ranking.

Knowledge included (~50k words across 26 markdown files + AISC CSV):

  • AISC shapes (2,091 sections with weight/area/Ix/Iy/Sx/Sy/rx/ry)
  • ASTM steel grades + ASME SA-equivalents + EN/JIS crosswalk
  • ASME BPVC (Sections II/V/VIII/IX), B31 piping codes, B16 flanges
  • API standards (5L line pipe, 1104 welding, 650 tanks, 510/570

inspection, 6A wellheads, more)

  • AWS D1.1 (building welding) and D1.5 (bridge welding)
  • AISC connections (shear, moment, HSS, AISC SCM Part 9-15 refs)
  • AISC 303 Code of Standard Practice
  • Bolting (F3125 / A325 / A490 / F1554 / RCSC)
  • Kerf charts across bandsaw / plasma / laser / waterjet
  • Coatings + galvanizing (A123/A153/A385, SSPC SP1-SP15, AMPP)
  • Misc metals (stairs, rails, ladders, grating, AESS)
  • OSHA 1926 Subpart R + ASME B30 cranes/rigging
  • IBC Ch 17 + AISC 360 Ch N special inspection
  • Mill procurement (US mills, A6 General Requirements, MTRs)
  • Estimating, proposals, contracts, pricing rules, exclusions

Ask about a W14X22, a CJP weld inspection requirement, an A992 vs A572-50 yield comparison, a Class 150 flange bolt pattern, a Schedule 40 wall thickness, a markup rule of thumb — Slevin answers with citations to the source markdown file. Zero per-message API cost, zero data sent to the cloud, zero subscription.

The chatbot's "I don't know" handling is honest — if FTS5 returns weak matches, Slevin says so and lists the topics it knows about instead of hallucinating.

Dead code purge

The legacy Anthropic chat backend is gone. ~7,400 LOC deleted across:

  • chat_with_claude, validate_takeoff_with_ai Tauri commands
  • chat_backend.rs (346 LOC of stubbed never-shipped commands)
  • qms_tokens.rs (132 LOC primitive RAG, superseded by FTS5)
  • 6 QMS token HTML files (5,376 LOC) — migrated to knowledge/*.md
  • chatStore.ts (226 LOC), ChatPage, ChatSessionList,

ModelPicker, JobCard, FinancialSummary, WelcomeScreen, + supporting components — all part of the never-shipped multi-session sidebar Implementation B

  • KnowledgeEngine::build_system_prompt — no LLM = no system prompt

What stayed: claude_client.rs (Capitol-only briefing path still uses it), reqwest Cargo dep (bug reports, SharePoint, briefing).

Net delta this release: ~−7,200 LOC while shipping two major features. Codebase is meaningfully smaller and faster to navigate.

CI quality gates

New .github/workflows/ci.yml runs on every push and PR to main. Two parallel jobs with fail-fast: false so all failures show in one view:

  • rust-check: cargo check --all-targets + cargo test --lib
  • frontend-check: npm ci + tsc --noEmit + npm run build (Vite)

Windows-only, matches the release workflows. README gets a CI badge.

This is the first automated gate this project has ever had. Catches the day you ship tired at 11pm.

Caveat for in-flight installs

This is the first auto-update through the dedicated public release repos (Capitol-Forge-Releases / Indolent-Forge-Nesting-Releases) that 6.2.6 / 3.4.4 installed. Customers on 6.2.6 / 3.4.4 get this update through the in-app updater. Customers on earlier versions need a manual reinstall to escape the old source-repo endpoint.

v3.4.4
Indolent Forge Nesting·

Build — releases now publish to dedicated public repos

Source repo can stay private. The two release workflows (.github/workflows/release.yml + release-indolent.yml) now build locally with tauri-action@v0 (no upload), stage NSIS + MSI artifacts, generate latest.json manually with download URLs pointing at the public artifact repos, and gh release create to publish via a new RELEASES_REPO_TOKEN secret (fine-grained PAT scoped to the two artifact repos only).

  • Capitol releases → holmeslucky/Capitol-Forge-Releases
  • Indolent releases → holmeslucky/Indolent-Forge-Nesting-Releases
  • Indolent updater endpoint fixed. Previously pointed at

holmeslucky/Indolent-Forge (no such repo) — so every Indolent install silently failed Check-for-Updates. Now points at the new Indolent-Forge-Nesting-Releases repo, matching where i-v* tags actually publish.

  • Stable-name alias asset Indolent_Forge_Nesting_Setup.exe is still

uploaded — indolent.design's trial CTA links there.

Caveat for in-flight installs

Existing v6.2.5 / v3.4.3 installs still poll the OLD source-repo URL. They will not auto-update to 6.2.6 / 3.4.4. After this release lands, do one of: dual-publish 6.2.7 / 3.4.5 to both repos as a transition, or notify customers to manually reinstall once. Going forward, all auto-updates flow through the dedicated repos.

v3.4.3
Indolent Forge Nesting·

Indolent — License UI unlocks the purchase loop

Found while smoke-testing the full buy flow: the desktop had no user-visible surface to see the machine_id, open the Buy page, or paste a license back. Customers could pay but never activate.

  • New License Settings panel (src/components/license/LicenseSettings.tsx)

with three sections — status badge (TRIAL N days / EXPIRED / LICENSED), machine ID display + Copy, "Buy License — $499" button that opens indolent.design/buy?machine_id=<id> in the default browser, and a paste-and-activate textarea. Visible during trial too (was previously blocked-screen only).

  • TrialBanner is now a clickable button — opens the License Settings

modal. Right side gains a "Buy License" pill with KeyRound icon.

  • New License button in Simple-mode top nav (Indolent variant only)

for direct access regardless of trial state.

Validation — accept the real desktop machine_id format

The website's /buy form was rejecting every real machine_id because the validation regex demanded 64 lowercase hex chars. The desktop actually generates IF-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX (35 chars, uppercase, dash-separated). Updated lib/validation.ts and the BuyForm regex on indolent.design to accept both formats. Bytes signed are the exact UTF-8 string either side passes, so signatures verify regardless of format — the only fix needed was loosening validation.

(The validation fix shipped to the website in commit 0fd19aa, deploys independently of this desktop release.)

v3.4.2
Indolent Forge Nesting·

Indolent — second-pass bug-fix bundle (real-customer dogfooding)

User installed v3.4.1, found a stack of UX + correctness bugs while generating actual cut sheets. This release fixes all of them.

PDF output — sellable quality

  • Removed hardcoded "Indolent Designs" brand from every PDF header.

The Company Profile name now drives the top-of-page identifier (with "Your Company — configure in Settings" gray-italic fallback when unset). Affects Linear cut sheet, Plate cut sheet, work order, shipping ticket, bill of lading, pro sheet. Footer "Generated by Indolent Forge Nesting" tool-attribution line preserved.

  • Plate cut sheet: removed the redundant dual-header. Was

rendering BOTH "Indolent Designs" in the navy bar AND "(Your Company — configure in Settings)" below it. Now exactly one identifier line, in the navy bar.

  • Fractions now reduce to lowest terms on every length. Steel-fab

convention: 12/16 reads as 3/4, 8/16 as 1/2, 4/16 as 1/4. Was rendering raw 16ths everywhere — "5'-5 4/16"" instead of "5'-5 1/4"". Found 4 separate length formatters in Rust that were independently broken (cut_sheet, bill_of_lading, linear_export, simple_nesting). All four now route through template::simplify_fraction (the canonical GCD helper that already existed for plate_sheet). Bonus: fixed an off-by-one carry bug in template::fmt_length ("7'-11 16/16"" / "7'-12"" no longer possible — now rolls to "8'"). 23 new unit tests covering the reduction + carry edge cases. Frontend TS formatter (src/utils/units.ts) was already correct.

  • Linear PDF "Material:" field now populates with comma-joined

material list from the nest result (was always blank). Falls back to a re-derived list from result.nests[*].material_key if the caller didn't pass one.

In-app UX

  • "Overall Efficiency: 0.0%" tile removed from the KISS Import

results when both linear and plate are present. Was always 0.0% because the backend deliberately returns 0 when units mix (mm vs mm²). Replaced with the meaningful Linear / Plate Yield breakdown (e.g. 73% / 13%) that was already shown elsewhere.

  • Settings + Company Profile modals are now scrollable with a

sticky footer. Done/Close buttons always reachable regardless of window size (was off-screen on smaller windows).

Pro Plate Nesting (Beta) — visual fixes only

Pro Plate Nesting was producing what looked like terrible nests at ~18% efficiency with parts crammed in the bottom-left corner. Deep investigation: the nesting algorithm is roughly OK; the visual was double-applying the placement offset, rendering parts in the wrong spots and off the visible sheet.

  • Fixed visual double-offset in ProSheetCanvas.tsx — polygon

vertices already contained absolute world coords; canvas was adding placement.x_mm on top, producing 2x the correct offset for every vertex.

  • Fixed UUID in sheet header — was rendering raw sheet.sheet_id

(cc3480f4-ba03-49d0-bddd-34f4cd74a449) instead of "Sheet N of M".

  • Added Beta expectation-setting banner — amber alert below page

title: "BETA — Pro Plate Nesting is in development. Complex parts may not place optimally. Report issues via the bug icon."

  • Out of scope for this release (filed for v2): replace the

hand-rolled grid-scan nester with proper jagua-rs integration (declared in Cargo.toml but never imported), fix polygons_overlap to honor holes, honor DXF $INSUNITS instead of unconditional *25.4 scale.

Branding

  • Desktop icon regenerated from a tighter crop of the badge so

the gold "ID" monogram fills more of the small-size variants (32×32, 48×48) instead of being a 4-pixel blob inside a thin gray ring. At 128×128 it now reads clearly. Not perfect at the smallest sizes — a dedicated flat 2-color icon design is filed for v3.5.0 polish.

Verification

  • cargo check: clean
  • cargo test --lib: 410 passed / 0 failed (was 387 — net 23 new

fraction-reduction + length-carry tests)

  • npm run build (tsc + vite): clean, no type errors
v3.4.1
Indolent Forge Nesting·

Indolent — first-customer bug-fix bundle

Real-customer UX fixes after first end-to-end test of v3.4.0.

Branding / discoverability

  • Company Profile is now reachable in Simple mode. The settings section we

shipped in v3.4.0 was hidden behind Advanced mode (currently disabled), so no user could find it. Added a Building2 icon button to the Simple mode top nav between the bug-report icon and the per-nest settings gear. Click opens a focused modal with the existing CompanyProfileSection — same code path, no duplication. ESC + click-outside close.

  • App icon rebuilt from the new Indolent Designs compass mark. The old IF

hex mark replaced everywhere (icon.ico, icon.icns, all PNG variants from 32x32 through 512x512, all Square*Logo sizes for UWP). Visible on the Windows desktop, taskbar, Start menu, alt-tab switcher.

UI / dark-mode fixes

  • Grade and Material Type comboboxes now render correctly in dark mode.

Previously the dropdown panel and option text were white-on-white (unreadable). Root cause: hand-rolled comboboxes with bg-forge-100 / hover:bg-steel-50 classes that didn't survive the global .dark CSS variable swap. Added shared .combobox-listbox / .combobox-option rules using literal hex values that bypass the swap. Same fix covers all 4 callers — PlateNesting, QuickMode, BatchMode, ProStock.

  • Dark mode contrast audit — added bg-white text-steel-900 pinning to

~30 native input/select elements across LinearNestingView, KissImportView, SpreadsheetNestingView, QuickModeEntry, BatchModeEntry, PlateNestingView, StockLengthsInput, SimpleNestingApp. Fixes "bright white stripes" in dark-mode forms.

  • Landing page sun-effect dimmed substantially. Removed the diagonal

linear-gradient(135deg, ...) background that caused the bright corner-to- corner beam. Replaced two off-screen radial glows with a single small centered radial behind the logo. Logo halo softened to omnidirectional ice-400 tint at 8% opacity (was a linear-gradient at 30%).

"ROMAC" stripped from user-visible strings

  • PlateCutTypeSelector.tsx: plasma kerf hint "1/2" kerf (ROMAC)" →

"1/2" kerf (industry standard)".

  • DstvViewerModal.tsx: dropdown label "ROMAC PC8 (plasma)" →

"PC8 Plasma Table" (internal value="romac" form-state kept).

  • Internal code comments and type identifiers (Romac enum variant, file

names) intentionally preserved — they're not user-visible and removing them would mass-rename without value.

Bug-report delivery — actual failures now surface

  • Root cause: submit_bug_report returned success: true in BOTH OK

and Err branches of the FormSubmit call. Compounding it: FormSubmit's free tier silently drops mail to unactivated addresses with HTTP 200 + {"success":"false"} body — never inspected by old code. Result: every bug report appeared to send but actually delivered nothing.

  • Fix: local backup to {app_data}/bug_reports/[timestamp].json is

now unconditional and runs BEFORE any network call (recovery path always exists). Primary delivery switched from FormSubmit to a self- hosted Next.js API route at https://www.indolent.design/api/bug-report that sends via Resend to support@indolent.design. FormSubmit retained as fallback, now with correct JSON body inspection. New delivery_channel and email_destination fields on BugReportResult.

  • UI: three-state result banner — green (succeeded), yellow (only

fallback delivered), red (both failed but local backup exists). Failure state shows a "Send via Email Client" mailto button as last resort.

  • 5 new unit tests for the Rust path; all 382 lib tests pass.

Other

  • "Learn More" button on Simple mode home now opens

https://www.indolent.design in the user's default browser via Tauri shell instead of loading a stale in-app marketing iframe. The public/indolent-landing.html file and the showLanding state plumbing are deleted. Content stays in sync with the live website automatically.

Verification

  • cargo check: clean
  • cargo test --lib: 382 passed / 0 failed
  • npm run build (tsc + vite): clean, no type errors
v3.4.0
Indolent Forge Nesting·

Indolent — First commercially-sellable release

This is the first Indolent Forge Nesting build that can issue and validate real customer licenses. Two changes ship together: a production Ed25519 signing pair, and per-install company branding on every export.

Security — production Ed25519 license-signing key

The placeholder pubkey that lived in src-tauri/src/licensing/verify.rs through all earlier Indolent builds is replaced with a real production Ed25519 public key. Paired with the private key held server-side at indolent.design (Railway env LICENSE_SIGNING_KEY_B64). The website's Stripe webhook now produces real license keys; the desktop's verify_license_key() accepts them.

Rotating this key invalidates every license issued against it, so it is considered permanent unless compromised. The previous placeholder keypair (neAJkpwleSg4+4HgjZW5QUMd9QHVSSRwpcFzhjfqjjs=) is dead — any build prior to v3.4.0 cannot activate against the production website.

Added — per-install company profile on every output

Customers configure their shop's letterhead once in Settings → Company Profile (name, address, phone, email, website, contractor license #, logo upload), and it appears on every PDF and Excel export. Without this, every cut sheet read the same hardcoded text — making the tool feel single-tenant.

  • New app_settings columns: company_name, company_address_line1,

_line2, _city, _state, _zip, _phone, _email, _website, _license_number, _logo_path. Added via add_column_if_missing (no SCHEMA_VERSION bump, matches the install_token precedent).

  • 4 new Tauri commands: get_company_profile, update_company_profile,

upload_company_logo, remove_company_logo. Logo validates extension (png/jpg/jpeg), enforces 2 MB cap, copies to {app_data_dir}/branding/logo.{ext}.

  • New src-tauri/src/pdf/branding_pdf.rs with CompanyHeader struct,

DB reader, and render helpers. Used by every PDF generator (plate_sheet, cut_sheet, pro_sheet, work_order, shipping_ticket, bill_of_lading). Logo top-right of navy header bar, address block underneath, "Phone · Email · Website · Lic#" centered footer line.

  • Excel Summary sheet (linear_export, plate_export) shows company

name as A1, address + contact line in rows 2–6.

  • Empty-state UX: blank company name renders a light-gray italic

"Your Company — configure in Settings" placeholder so unconfigured installs get a visible nudge.

  • Frontend: new CompanyProfileSection.tsx at the top of the Settings

page. Full form, logo upload zone with thumbnail preview (via convertFileSrc), Replace/Remove buttons, dirty-state save, auto-clear status message, amber empty-state banner.

14 new unit tests across company_profile and branding_pdf modules. Frontend tsc clean. Backend cargo test --lib 377 / 0.

v3.3.0
Indolent Forge Nesting·

Security — SEC-001 resolved: AI proxy architecture, no embedded keys

The desktop binary no longer contains an Anthropic API key. AI features (chat, takeoff validation, AI briefing) now route through a proxy at the Capitol Production Center backend, which holds the real key server-side. The GitHub secret-scanner detection that triggered Anthropic's key revocation cannot recur — there is nothing to scan.

Architecture:

  • New constant PROXY_URL in src-tauri/src/services/claude_client.rs

points at https://capitol-production-center-production.up.railway.app/api/ai/proxy/messages.

  • Per-install identity: on first AI call, the app generates a random

UUID v4 and stores it in app_settings.install_token. Every proxy request sends this in the X-Install-Token header so the server can rate-limit or revoke individual installs without revoking everyone.

  • The Authorization: Bearer sk-ant-… header is gone; the

x-api-key / anthropic-version headers are gone. The proxy injects them server-side before forwarding to Anthropic.

What was removed:

  • build.rs — dropped the option_env!("CLAUDE_API_KEY") block and the

cargo:rustc-env=CLAUDE_API_KEY line. Dropped the dotenv build-dep.

  • commands/settings.rs::get_default_api_key() — and all of its

fallbacks (compile-time env, runtime env, .env file lookup in five paths). The encryption helpers around the key are gone too.

  • The update_claude_api_key Tauri command — no longer registered in

lib.rs. The claude_api_key parameter on chat_with_claude and validate_takeoff_with_ai is gone; frontend callers updated.

User-visible:

  • Settings → AI Assistant now shows a green chip:

"✓ AI features powered by Capitol Engineering — no key required" (or "by Indolent Forge" for the Indolent variant). No input field.

  • Chat and Briefing tabs work exactly as before for end users.
  • New friendly error messages when the proxy is unreachable

("Could not reach AI service … check your internet connection"), rate-limited ("Wait a moment and try again"), or has revoked the install token ("Contact Capitol Engineering support").

Schema:

  • New column app_settings.install_token TEXT added via

ALTER TABLE … ADD COLUMN. Strictly additive — no SCHEMA_VERSION bump.

  • New helper Database::get_or_create_install_token() lazily generates

the UUID on first call.

Coordination note (Indolent variant): the matching proxy endpoint must be deployed on the CPC backend before this version is shipped. The Indolent license-issuance flow is unaffected — it still uses the Ed25519 placeholder pubkey from v3.2.x (SEC-003 remains open).

v3.2.7
Indolent Forge Nesting·

CI fix — don't pass empty TAURI_SIGNING_PRIVATE_KEY_PASSWORD

The v6.1.6 build with the regenerated no-password key STILL failed with "Wrong password for that key". Root cause: the workflow had TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.X }} and when the secret doesn't exist, GitHub Actions evaluates the expression to "" (empty string), so the env var was set to "". Tauri then attempted decryption with empty string, which fails on an unencrypted key.

Fixed by removing the password env line entirely from both workflows. Tauri's signer reads std::env::var("TAURI_SIGNING_PRIVATE_KEY_PASSWORD").ok() which returns None when the var is unset (vs Some("") when set empty), and routes to the no-password code path.

v3.2.6
Indolent Forge Nesting·

Keypair regen + final auto-updater fix

The v6.1.5 build hit a new error: "Wrong password for that key" during signing. The original Ed25519 keypair was generated with an unknown password (interactively, no record). Regenerated the keypair with the --ci flag to force a no-password key. Updated the public key in both tauri.conf.json and tauri.indolent.conf.json.

The user needs to update the GitHub secrets:

  • TAURI_SIGNING_PRIVATE_KEY — replace with new key contents
  • TAURI_SIGNING_PRIVATE_KEY_PASSWORD — DELETE entirely (key has no

password now)

This breaks compatibility with v6.1.4 installs (different signing key → signature verification will fail). Those installs must be manually upgraded to v6.1.6 one final time, then all future versions flow through auto-updater normally.

v3.2.5
Indolent Forge Nesting·

CI fix (real one) — bundle.createUpdaterArtifacts

Real root cause of the missing latest.json: Tauri 2 doesn't produce the .nsis.zip + .nsis.zip.sig updater bundle by default. The build step must be opted in via bundle.createUpdaterArtifacts: true in tauri.conf.json. The --bundles nsis,updater arg I tried in v6.1.4 is not real Tauri syntax — the updater token was silently ignored, so only the plain NSIS .exe was produced and tauri-action's existsSync check filtered everything else out as "doesn't exist".

Fixed by:

  • Added "createUpdaterArtifacts": true to the bundle section of

both tauri.conf.json and tauri.indolent.conf.json.

  • Reverted the bogus --bundles nsis,updater arg in both workflows

(back to default — Tauri builds all bundle.targets).

  • Removed the bogus includeUpdaterJson: true workflow input (real

name is uploadUpdaterJson, defaults to true — silently ignored the wrong name in 6.1.3 and 6.1.4).

  • Kept updaterJsonPreferNsis: true so latest.json points at the

NSIS bundle (not MSI).

After v6.1.5 builds successfully, the release page should have: Capitol Forge_6.1.5_x64-setup.exe, Capitol Forge_6.1.5_x64-setup.nsis.zip, Capitol Forge_6.1.5_x64-setup.nsis.zip.sig, and latest.json — the combination the v2 updater plugin reads.

v3.2.4
Indolent Forge Nesting·

CI fix — auto-updater manifest now publishes

The v6.1.3 release built and uploaded the installer fine, but the latest.json updater manifest was skipped because tauri-action defaults to looking for MSI signatures while our updater is wired to NSIS bundles. Added updaterJsonPreferNsis: true and --bundles nsis,updater to both Capitol and Indolent workflows so the NSIS bundle + its signed updater payload are produced and the manifest gets written.

No functional changes vs 6.1.3.

v3.2.3
Indolent Forge Nesting·

CI fix

The first CI release at v6.1.2 failed because shape_lookup_clean.csv (compiled into the binary at src-tauri/src/database.rs:369 via include_str!) was excluded by *.csv in .gitignore, so the runner couldn't find it. Added an explicit !shape_lookup_clean.csv exception and committed the file (67 KB).

No functional changes vs 6.1.2.

v3.2.2
Indolent Forge Nesting·

Auto-updater — no more emailed installers

This is the first release shipped through GitHub Actions CI. Every future version drops as a tagged release; existing installs will see a centered modal on next launch with the new version, release notes, and Install & Restart / Later buttons.

Added:

  • tauri-plugin-updater + tauri-plugin-process wired in

src-tauri/src/lib.rs.

  • Ed25519 signing keypair generated. Public key embedded in both

tauri.conf.json and tauri.indolent.conf.json. Private key stays on the maintainer's machine; CI builds sign with the key via the TAURI_SIGNING_PRIVATE_KEY GitHub secret.

  • UpdateChecker modal (src/components/common/UpdateModal.tsx) —

silent check on app launch, friendly prompt with release notes, live download progress bar with signature verification, then auto-relaunch into the new version. Offline / unreachable endpoint fails silently — never nags.

  • GitHub Actions workflows: .github/workflows/release.yml (Capitol

on v*.*.* tags) and .github/workflows/release-indolent.yml (Indolent on i-v*.*.* tags). Both use tauri-action@v0 to build Windows installers + emit the latest.json manifest the updater reads.

  • docs/RELEASING.md covers cutting a release, required GitHub

secrets, first-release procedure, and rollback steps.

Note: Installs older than 6.1.2 (e.g. 6.1.1) don't have the updater wired in yet — they must be manually upgraded to 6.1.2 once. After that, all updates flow automatically.

v3.2.15
Indolent Forge Nesting·

Security — Anthropic API key rotated

New CLAUDE_API_KEY issued and installed in the CI signing pipeline. The previous key was auto-revoked by Anthropic after GitHub's secret scanner detected it in the public release artifacts (the key was embedded into the binary at build time via build.rs option_env!).

Older 6.1.x installs will continue working until v6.1.15 propagates via the auto-updater. After 6.1.15 installs, AI features (Simple Chat Panel, etc.) run against the new key.

Permanent fix planned for v6.2.0: strip the embedded key from the binary entirely. AI features will then require the user to enter their own Anthropic key in Settings on first use. The encrypted key-storage path in commands/settings.rs already exists — just need to remove the build-time embed and make Settings the only source.

v3.2.14
Indolent Forge Nesting·

Polished update notification

The auto-update modal got a real visual upgrade so users see something professional instead of a basic toast:

  • Brand logo + app name in the header
  • Bigger version number with release date
  • Real release notes (headings + bullets parsed from markdown) pulled

from CHANGELOG.md, not a generic placeholder

  • Multi-stage install progress: Downloading… → Verifying signature… →

Restarting…

  • Live download progress with bytes (e.g. "4.3 MB / 9.0 MB")
  • "Digitally signed by Capitol Engineering Co." footer with green

shield badge

  • "Remind me later" instead of plain "Later"

GitHub Actions workflow now extracts the matching CHANGELOG section for each tag and uses it as the GitHub release body — so the modal, the release page, and the changelog all show the same content.

Security note

The Anthropic API key (CLAUDE_API_KEY) embedded in the binary via build.rs was detected in public release artifacts by GitHub's secret scanner and auto-revoked by Anthropic. New key issued + secret rotated in this release. The proper fix (strip the embedded key, force runtime user-supplied key via Settings — audit finding SEC-001) is planned for v6.2.0.

v3.2.13
Indolent Forge Nesting·

Spreadsheet Import — per-row Dragon selector

New "Dragon Plasma routing" panel under the Linear materials list in the Spreadsheet Import view. Users can now pick exactly which imported parts route to the Dragon plasma table (18'-6" coil) vs the default Beamline stock pool — same per-row control Quick + Batch modes have.

  • Sticky-header table with one row per linear part
  • "Select all" / "Clear all" buttons + "X of N on Dragon" pill
  • Amber-tinted row when flagged
  • Auto-injects 18'-6" stock when any row is flagged

Mirrors the existing runLinearNesting Batch path — no Rust backend changes needed.

v3.2.12
Indolent Forge Nesting·

Plate PDF + Excel — job name + material now print correctly

The plate cut sheet exports were missing key job info in both PDF and Excel outputs:

  • PDF header only showed Job: <number> | Material: <blank>
  • Job name (project description) passed in PdfConfig but never rendered
  • Customer passed but never rendered
  • Material description hardcoded empty in export_simple_plate_pdf

(linear had it, plate didn't)

  • Excel Summary tab had no Material row at all

Fixes:

  • PDF header rewritten to 2 lines:
  • Line 1: Job: M-26-3577 — TSMC Phase 2
  • Line 2: Customer: TSMC AZ | Material: 16ga SS304
  • Fields drop cleanly if missing
  • New helper auto-derives material description from sheets:
  • "16ga SS304" — single material
  • "16ga SS304, 1/4\" A36" — multiple
  • "Mixed (5 materials)" — many
  • Excel Summary tab gets a Material row alongside Job#/Customer/Project
  • Affects linear PDF too (now shows project name + customer when set)

since render_header is shared.

v3.2.11
Indolent Forge Nesting·

Logos load correctly in production

/assets/ce-logo.jpg absolute paths worked in dev but broke in the Tauri 2 production webview on Windows. Moved logos into src/assets/ and import as ES modules so Vite gives them content-hashed paths that resolve under http://tauri.localhost.

Also the first end-to-end test of the auto-update loop — installed 6.1.10 should detect this release and prompt automatically.

v3.2.10
Indolent Forge Nesting·

Auto-updater fully working — keypair regenerated with password

After eight failed CI attempts, the final piece fell into place: empty-password Tauri signing keys are a known-broken minefield on Windows CI (Tauri issues #14829, #13485). Regenerated keypair WITH a real password (capitol-forge-2026). CI now produces signed installer + latest.json + .sig artifacts on every tag, and existing installs see the update prompt within seconds of next launch.

v3.2.1
Indolent Forge Nesting·

Bug fix — linear nesting kerf was locked

The 6.1.0 plate-kerf sync fix (which forces the plate kerf display to 0 when shear/estimate cut type is selected) was too aggressive. It gated the shared kerf_mm setting globally, so once the plate cut type defaulted to shear, the linear nesting kerf selector silently refused every change. Linear nesting always ran with kerf=0.

Fix in `src/stores/simpleNestingStore.ts`:

  • setKerf — removed the cut-type gate. The user's preferred kerf is

now stored regardless of plate cut type.

  • updateSettings — removed the kerf-forcing logic.
  • setPlateCutType — no longer mutates kerf_mm. Cut type and

stored kerf are independent now.

  • runPlateNesting — computes the effective kerf at the backend

call site: passes 0 to the algorithm when cut type is shear or estimate; otherwise passes the user's stored kerf.

  • Persistence merge — no longer auto-zeroes kerf on hydration.

PlateCutTypeSelector already reads its displayed kerf from PLATE_CUT_TYPE_KERF_MM[cut] (per the 6.1.0 fix), so plate display still snaps to 0 visually when shear is selected — but the underlying user-preferred kerf is preserved for the linear flow.

v3.2.0
Indolent Forge Nesting·

Shop-ready build — Advanced hidden, Simple polished

Advanced/Workshop mode is hidden via ENABLE_ADVANCED_MODE = false in src/lib/variant.ts while the data-parity work (Waves F-H) is still in progress. Flip the flag to true for internal/dev builds.

Plate nesting PDF — ROMAC PN2 redesign

  • Restructured src-tauri/src/pdf/plate_sheet.rs to match the ROMAC PN2

shear-sheet output structure: 'TO CUT' SUMMARY (REF | CUT QTY | REQ'D QTY | SIZE | PIECE ID), 'CUT FROM' SUMMARY (REF | USED QTY | AVAIL QTY | SIZE), USAGE SUMMARY (Gross / Net / Drop sq ft + utilization %), then per-sheet CUT FROM — SHEET N + EACH PIECE CUTS + LAYOUT PLOT #N.

  • Layout plot now shows clean part outlines with REF numbers in the

top-left corner of each part, shear cut lines drawn directly on the diagram in thin gray, and X marks on rectangular drop regions so the operator can see scrap at a glance.

  • Dropped: hatch patterns, numbered chips, position coordinates,

separate shear sequence table, pattern legend page.

  • ROMAC-style (continued next page)----…----Printed: DATE footer.
  • Capitol Forge visual styling (navy header, blue section bars, alt

rows) kept on top of the ROMAC data structure — best of both.

Linear input parser fix (data corruption)

  • 1-15/16 was being parsed as 1'-1 15/16" (~13.94", a 7× error

that would scrap material at the shear). Added Pattern 2a in src/utils/units.ts that recognizes N-N/N as a mixed-fraction inch value when the right side contains a fraction. Preserves feet-inches semantics for 6-3 1/2" etc.

  • 20 new unit test cases in src/utils/units.test.ts cover both

shop-shorthand and feet-inches notation.

Linear nesting Quick/Batch modes

  • Validation errors were set in the store but never surfaced; users

saw the Run button do nothing. Added toast + red banner; errors clear when inputs change.

  • Material-key grouping: same material rows (e.g. multiple W6X12)

were nested separately due to stale persisted keys vs fresh createMaterialKey() output. Now always re-derives from canonical material_type/size/grade fields.

  • Quick mode no longer silently no-ops when material header is

missing — surfaces a real error.

Plate input UX

  • Width/Height/Thickness fields now accept text input (was numeric-

only). Reuses the shared length parser, so 1-15/16, 48", 1 15/16, 48.125 all work.

  • New "Plate Input Display Units" setting in Settings panel

(Decimal Inches / Fractional Inches / Millimeters). Decimal inches now show 3 places (.125 not .13).

Kerf bug

  • Selecting Shear cut type now correctly sets kerf to 0 (was showing

1/2"). New setPlateCutType store action keeps plate_cut_type and kerf_mm atomically synced. Persistence layer heals stale state on hydration. PlateCutTypeSelector reads kerf from cut type rather than raw store so display can't lie.

Hidden under the flag (for next release)

The following Wave A-E Workshop work is built and committed but hidden behind ENABLE_ADVANCED_MODE = false until shop-ready:

  • 5 critical data bugs fixed across Financials / Forecast / Meeting

Pack / Welding (margin math, NULL probability, snapshot rehydrate, qualification_date policy, 20-50× faster job detail queries).

  • Schema expansion across sp_jobs, NCR/CAR/SCAR, Welding (+welders

+ continuity_log), Workforce (+classifications + welder_certs), Purchasing — ~115 new columns + 4 new tables + 8 new Tauri commands. Migrations run on first launch; data populates as upstream parsers catch up.

  • UI parity layer (sort/search/filter/expand/KPI strips) shipped for

Jobs/Quality/Welding/Workforce/Purchasing.

  • New tabs: AI Briefing (Claude-generated daily exec summary, 15-min

cache), Profile (Azure AD identity foundation).

  • Forecast Phase 1: capacity chart, per-PM breakdown, CSV export.
v3.1.3
Indolent Forge Nesting·

KISS Deep-Dive

#### Fixed

  • Mixed-fraction plate widths no longer parse as `None`. KISS files write plate dimensions like 6-3/16 and 5-7/16; the old parser only handled whole or whole/num_den and returned None for the mixed-number form, so every mixed-fraction plate surfaced a "Missing width" warning and got skipped. Width parser now recognizes mixed-number dimensions (whole-num/den) end-to-end.
  • Plates route strictly to the 2D plate nester. The linear fallback was quietly accepting plate dimensions and cramming them into the 1D nester — produced nonsensical cut plans. Backend now refuses plate-disposition groups on the linear path, and the UI locks plate rows to Plate disposition.
  • Dragon Plasma presets hidden for KISS-imported plates. Dragon is a separate workflow (18'-6" table, specific sheet sizes). KISS plate imports no longer show the Dragon Plasma preset picker.

#### New

  • Buyout classification. Bolts (HS), nuts (NUT), washers (FW), and misc fabrications (MX) auto-detect as purchase items and are excluded from nesting. Any part whose notes column contains "BUYOUT" is also flagged. Threaded rod (RB) defaults to cut-in-house; override per-import if your shop buys it pre-cut.
  • Post-import review table. After KISS parse, every material group surfaces with a [Linear | Buyout | Skip] dropdown. Plate groups are locked to Plate. Buyout groups show a compact "no stock picker" placeholder instead of demanding stock lengths.
  • Sequence + remarks extraction. KISS S-line sequence numbers and the notes column now propagate as first-class fields on each part, available for downstream grouping and display.
  • Bill of Lading (shippable-items list). Standalone PDF export (Buyouts_<Job>.pdf) via a new "Export Buyouts PDF" button on the KISS results view. Groups by sequence; buyouts appear in their own subsection collapsed by mark + size. The combined cut-list-plus-BOL single-PDF is planned for 5.3.4.

#### Internal

  • New NestDisposition enum (Linear | Plate | Buyout | Skip) replaces the old two-value nest_mode string on KissMaterialGroup. Group key now includes disposition so mixed dispositions on the same size+grade surface as distinct review rows.
  • New effectiveDisposition(group, config) helper in types/simple-nesting.ts centralizes "parsed disposition vs. user override" precedence across 6 call sites.
  • New sanitizeFilenameSegment helper exported from lib/exportUtils.ts; buildExportFilename now delegates to it.

KISS Nest Quick-Path

#### New

  • Auto-pick plate stock. Plate groups no longer require you to click a sheet size before nesting. The backend tries each of the 6 common sizes (4×8, 4×10, 5×10, 5×12, 6×12, 8×20) as a single-size run, picks the highest utilization (smaller sheet wins on ties), and stamps the winning size + utilization on the results as a blue badge. Override path still available: expand the per-group "Override stock" panel and pick a specific size to force it.
  • Collapsed-by-default Material Groups section. The entire "Select Material Groups to Nest" review table is now wrapped in a collapsed section showing 14 total · 12 to nest · 2 buyouts. Expand to change dispositions, override stock, or deselect groups. If any plate group has parts missing a parsed width, the header goes amber with an issue count.
  • Collapsed-by-default Override Stock panel per plate group. Happy path: drop → Run → done. Expand only to force a specific plate size. Header reads Override stock · auto-pick by default, switches to manual · 4" × 8" (or similar) once a plate is added, and returns to auto-pick when all overrides are removed.

#### Internal

  • New auto_pick_plate_stock helper and run_simple_plate_nest_auto Tauri command in src-tauri/src/commands/simple_nesting.rs. run_kiss_nesting_v2 accepts a new candidate_plate_sizes param; when a plate group has no user-supplied stock plates, the helper is invoked with the candidate library.
  • New reusable CollapsibleSection component in src/components/simple-nesting/. Supports controlled + uncontrolled open state, optional amber warning tint.
  • SimplePlateNestResult carries an optional auto_picked_from field (size label + utilization %) used by the results UI to render the badge.

KISS Nest Polish

#### New

  • Same-thickness plates share sheets. Auto-pick plate groups that share thickness and grade now accumulate into a single bucket and nest together on shared sheets. Previously every width variant ran its own auto-pick — a takeoff with PL-3/8X3-A36, PL-3/8X3-1/2-A36, and PL-3/8X4-A36 produced three separate sheets even though all three fit on one 4×8 of 3/8" A36. Bucketed results label sheets by thickness only (e.g. 3/8" plate) since they span multiple widths. Manual-override plate groups (user picked specific stock) still run standalone so the chosen size is respected.

#### Fixed

  • Plate groups nest without stock picked. The Run button stayed disabled after Select All if any plate group had an empty stock list — but auto-pick doesn't need user-supplied stock. Relaxed the UI's canRun and getMissingStockGroups checks: plate groups always pass validation (empty stock = valid auto-pick path).
  • Plate groups nest without a config entry at all. run_kiss_nesting_v2 rejected plate groups that had no GroupStockConfig entry in the HashMap with No stock configuration for group '<key>'. Select All never wrote config entries for plate groups, so every fresh nest surfaced the error. Backend now synthesizes a default config from the parsed disposition when an entry is missing — the auto-pick path handles the rest.

#### UX

  • Material Groups list always visible. The outer "Material Groups" collapsible (added in Quick-Path above) was hiding the group-selection list by default. Removed the outer wrapper; the list is now always rendered with summary chips ("14 total · 12 to nest · 2 buyouts") and an amber warning pill inline with the heading. The "Review disposition per group" table that lives inside the section is still wrapped in its own collapsed section, so the happy path doesn't scroll past it every nest.

Version

  • Capitol Forge: 5.3.2 → 5.3.3
  • Indolent Forge Nesting: 3.1.2 → 3.1.3
v3.1.2
Indolent Forge Nesting·

Spreadsheet Import: `.xlsm` / `.xlsb` Support + No-Login Gate

  • Accept the Capitol Master Estimate `.xlsm` directly. The Simple Nesting file dialog used to filter to .xlsx + .xls only — the user's actual master workbook is macro-enabled (.xlsm) and got filtered out, so the only workaround was to "Save As .xlsx" first. The dialog now accepts .xlsx, .xlsm, .xlsb, .xls (calamine's open_workbook_auto reader already handles all four).
  • "Not authenticated" on takeoff upload, fixed. parse_excel_takeoff, parse_kiss_file, parse_csv_file, and their content-variant commands were gated behind require_auth. Simple Nesting is the estimator's deliberately-no-login quick tool, so the auth check always failed there — uploading a takeoff returned "Not authenticated" instead of parsing. These read-only commands take a user-supplied path, return pure data, and never touch the database, so auth gating bought nothing. Gate removed. DB-mutating commands (save_job_to_file, load_job_from_file, import_shape_database, add_shape_entry, lookup_shape_weight) are unchanged and still require auth.

Drag-and-Drop: Actually Works Now

  • Tauri 2.0 native drag-drop wired for KISS and Excel import. Previous drag-drop was a dead HTML5 listener — Tauri 2.0's dragDropEnabled (on by default) intercepts the OS drop and suppresses onDrop events, and the fallback code read (file as any).path, which browsers never populate. Replaced with a shared useTauriFileDrop hook that subscribes to the webview's onDragDropEvent stream and receives real OS paths. Both the KISS drop zone (.kss / .kis / .kiss) and the Spreadsheet drop zone (.xlsx / .xlsm / .xlsb / .xls) now highlight on hover and import on release.
  • Listener is scoped by enabled flag — it only activates before a file is loaded, so dropping onto the results screen can't silently reset state.

Version

  • Capitol Forge: 5.3.1 → 5.3.2
  • Indolent Forge Nesting: 3.1.1 → 3.1.2
v3.1.1
Indolent Forge Nesting·

Dragon Plasma Stock Isolation (Linear Nesting)

  • Dragon-flagged parts no longer leak onto longer stock. The Dragon checkbox tells the nester "this part must cut on the 18'-6" Dragon Plasma table," but the backend was passing the full stock list (20', 40', 60', 18'-6") to every material group. The batch-yield picker would score a 20' stick just fine for a 9'-6" Dragon part and pick it — producing cut plans that asked an 18'-6" machine to handle a 20' stick. Fixed: a material_key containing (DRAGON now sees only 18'-6" stock, and every other group never sees 18'-6" stock.
  • Missing-Dragon-stock is a clear failure, not a silent reroute. If a Dragon group is submitted without any 18'-6" stock in the list, those parts come back as unassigned with no fallback to 20'/40'/60'.
  • Three regression tests lock it in: dragon_group_uses_only_18_6_stock, regular_group_never_uses_18_6_stock, dragon_group_without_dragon_stock_unassigns.

Batch Mode: Type Column Readable

  • Compact mode for `MaterialTypeCombobox`. In dense table layouts, the combobox used to display the full label ("Wide Flange") in a 100px column, which truncated to "Wide F" — masking that picking Angle/Channel/Pipe/HSS/FB worked at all. New compact prop shows the short code (W / L / C / HSS / HSSR / PI / PL / FB / S / RB / SB) in the closed input. The dropdown still shows full labels.
  • Batch Mode table column widths rebalanced. Type narrowed to 80px, Grade widened to 110px so A500-GR.B fits.

Batch Mode: Material Groups Chip Clarity

  • The "Material Groups (will nest separately)" chips used to show only the raw composite key (W-W6X12-A992), which looks like a duplicate when three rows of W6X12 differ only by grade. Chips now break out shape-size, type, grade (pill), and total qty so A992 vs A36 vs A572 are obvious at a glance.

PDF Cut Sheet: Part Marks Summary

  • Cut-sheet PDFs used to render the per-stock part marks as P2, P2, P2, 8 more..., both duplicating and truncating. Now summarizes as P2 ×8, P3 ×4, P4 — each distinct mark listed once with its count, no hidden overflow.

Version

  • Capitol Forge: 5.3.0 → 5.3.1
  • Indolent Forge Nesting: 3.1.0 → 3.1.1
v3.1.0
Indolent Forge Nesting·

Linear Nesting: Batch-Yield Stock Picker

  • Stock selection now optimizes for the batch, not one part at a time. Best-Fit-Decreasing used to open each new bin with the smallest stock that fit a single part — so 56× 14'6" parts with a [20', 40', 60'] stock list got nested onto 56× 20' sticks at 72.5% yield instead of 14× 60' sticks at 96.7%. The picker now scores each candidate stock by the yield it would achieve when greedy-filled with the remaining parts, and ties break toward the shorter stick (same yield, fewer sticks, less drop, less handling).
  • Two regression tests lock it in: picks_longer_stock_when_it_improves_batch_yield (the 56× 14'6" case) and tie_breaks_toward_shorter_stock.
  • Applies to both Quick Mode and Batch Mode. Batch Mode groups parts by material and runs the picker per group, so each material gets the stock length best for its pattern.

Linear Nesting: Order Summary Grouping Fix

  • The linear Order Summary used to group nests by material_key only. When a single material used multiple stock lengths (mixed remnants + new, or different new lengths), all sticks collapsed into one row showing the first stick's length and everyone's qty. Now keys on material + stock-length so each distinct size gets its own row.

Save Button Visibility

  • The in-app Save/Saved status was a tiny amber circle with a tooltip, which users missed. It is now a labeled pill button — amber "Save" when there are unsaved changes, gray "Saved" when clean — with Ctrl+S still wired.

Quick/Batch Mode Result Bleed Fix

  • Switching the Linear Nesting entry mode no longer leaves the previous mode's nest result visible in the results pane. setLinearEntryMode now clears result and validationError on switch.

Plate Nesting: Cut Type + Guillotine Packer

  • Cut Type selector replaces raw kerf. The kerf fraction dropdown on the Plate Nesting view is gone. In its place, a four-button Cut Type selector: Shear (0"), Plasma (1/2" — ROMAC PC8), Saw (1/8"), Estimate (0"). Kerf is derived from the choice, so operators pick the process, not the fraction. Header reads "Kerf: X" off the selected cut type.
  • Guillotine-feasible shelf packer. Shear / Plasma / Saw nests now use a Shelf First-Fit-Decreasing packer that produces layouts the shear sequence pass can always decompose into clean strokes. This removes the overlap-warning fallback path that used to appear when the old MaxRects output couldn't be guillotined. Estimate mode still uses MaxRects BSSF for maximum density when no cutting will happen.
  • Smallest-stock-first sheet selection. Stock is now sorted ascending by area before placement. A small batch that fits on a 48×96 no longer gets dropped onto a 96×240 leaving massive drop.
  • Summary matches the printout. OrderSummary.tsx and the cover-page grouping in plate_sheet.rs now key on thickness + grade + size (e.g. PL0.5 A36 48x96) instead of just thickness + grade. Distinct sheet sizes no longer collapse into a single row that misreports the size.
  • Qty new-row UX. Tabbing into a new cut row in the Plate Nesting view now leaves Qty blank with a 1 placeholder instead of pre-filling 1. Fast typists no longer overwrite a silent default.
  • Dragon Plasma Table preset removed from Plate view. The PC-72/TD-72/Titan 660/Titan 1200/XPR300 preset block is linear-only. The plate view now shows plate-stock presets only (48×96 / 48×120 / 60×120 / 96×240).

Version

  • Capitol Forge: 5.2.0 → 5.3.0
  • Indolent Forge Nesting: 3.0.0 → 3.1.0
v2.3.0
Indolent Forge Nesting·

Plate Nesting Overhaul

  • Shear sequence algorithm — new shear_sequence.rs module does recursive guillotine decomposition of each plate, producing a ShearPlan of ordered strokes (axis, position from edge, span, notes). Five TDD tests cover the single-part waste-crop case, two-part vertical split, 2×2 grid triple-stroke case, kerf-gap midpoint placement, and the overlapping-pack warning fallback.
  • B&W-printable plate cut sheets. The 10-color part palette was replaced by 10 distinct hatch patterns (diagonals, crosshatch, dots, bricks, checker, horizontals, verticals). Numbered white chips hold cut numbers, part borders are heavy black, plate background is white. Prints cleanly on a laser without information loss. A PATTERN LEGEND appears after the per-sheet detail pages.
  • PDF Shear Sequence table. Each plate sheet now renders a SHEAR SEQUENCE section before the placements table listing the guillotine strokes in cut order. Warning strokes render with a WARN: prefix.
  • Canvas Shear Sequence panel. Below each plate diagram the on-screen panel lists the same strokes. Hovering a row highlights the corresponding stroke line over the canvas with a dashed amber overlay.
  • Canvas B&W Preview toggle. Checkbox above the plate diagrams renders the exact PDF treatment (hatches, chips, black borders, white plate) so operators can preview the printed sheet before exporting.
  • Takeoff import plate routing. Excel takeoffs now partition parts by material class. Plate parts (PL / FB / FLAT / GA) reach the plate nester; linear parts stay with the linear nester. Mixed takeoffs show both Linear and Plate tabs.
  • Plate Takeoff Template. New distributable Plate_Takeoff_Template.xlsx available from the Spreadsheet import view — flat 8-column sheet (PART MARK / QTY / LENGTH / WIDTH / THICKNESS / GRADE / MATERIAL / NOTES), no formulas, no merged cells. Parser adds a find_plate_takeoff_header_row detection path that recognizes this template.
  • Consistency sweep. "PIECE MARK" → "Part Mark" across linear cut sheet, plate PDF, and Excel. Position precision is 2 decimals everywhere (PDF, canvas diagram, canvas tooltip). Rotation renders consistently as Yes/No for Simple Plate. Cut-number fallback is idx + 1 across canvas and PDF (was 0 in PDF).
  • Excel plate export. Part List now includes a Cut # column and combines X/Y into a single "Position (X, Y)" column for readability.

Version

  • Capitol Forge: 5.1.0 → 5.2.0
  • Indolent Forge Nesting: 2.2.0 → 2.3.0
v2.2.0
Indolent Forge Nesting·

Plate Nesting Cut Sheets

  • ROMAC-style visual cut sheet diagrams for simple plate nesting
  • To-scale plate diagram showing each part drawn in position on the plate
  • Color-coded parts by part mark — same mark = same color across all sheets
  • Bold cut sequence numbers on each part for shear operator reference
  • Part marks and dimensions displayed on each rectangle
  • Interactive Konva.js canvas with hover tooltips showing full part details
  • Color legend mapping part marks to colors below each diagram
  • Width and height dimension lines on the plate diagram

PDF Cut Sheet Upgrade

  • Full-color plate diagram added to PDF exports (matches on-screen colors)
  • Cut sequence table sorted by cut number with # column added
  • Diagram renders parts with cut numbers, marks, and dimensions inside each piece
  • Automatic page breaks when diagrams are too tall for remaining page space
  • Proper fraction reduction in dimension labels (e.g., 1/2" instead of 8/16")

Cut Sequence Algorithm

  • Automatic cut numbering: top-to-bottom, left-to-right positional ordering
  • Row grouping with 5mm threshold — parts at similar Y positions share a row
  • Cut numbers assigned in Rust backend for consistency between screen and PDF
  • Designed for future Phase 2: optimized shear sequencing to minimize total cuts

Fixes

  • Fixed dimension format edge case where zero sixteenths could produce "0/16" display
  • Fixed React key collision when multiple sheets use the same stock plate definition

Version

  • Capitol Forge: 5.0.3 → 5.1.0
  • Indolent Forge Nesting: 2.1.0 → 2.2.0
v2.1.0
Indolent Forge Nesting·

Custom Shapes & Grades

  • Material type selector upgraded to combobox with free text entry — type "Unistrut", "Strut Channel", or any custom shape
  • Grade selector upgraded to combobox with free text — type "SS304", "Duplex 2205", or any custom grade
  • Custom entries persist across sessions and appear in dropdowns for future use
  • Delete button on custom entries to remove typos or unused values
  • Works in Quick Mode, Batch Mode, and Plate Nesting views

Order Summary / Cover Page

  • New collapsible "Order Summary" card at the top of nesting results
  • Shows material order table: Qty, Shape, Size, Stock Length, Grade, Total LF/SF, Weight, Remnants, Efficiency
  • Weight column pulls from AISC shape database for standard shapes (dash for custom shapes)
  • Professional cover page added as page 1 of all PDF exports (linear, plate, and pro nesting)
  • Job info header with job number, customer, job name, nest ID, and date

Nest ID & Smart Filenames

  • Optional "Nest ID" field added to all nesting views (linear, plate, pro)
  • PDF and Excel exports use smart filenames: {JobNumber}_{NestID}_{Date}_CutList.pdf
  • Falls back gracefully: {JobNumber}_{Date}_CutList.pdf or CutList_{Date}.pdf

Version

  • Capitol Forge: 4.0.0 → 4.1.0
  • Indolent Forge Nesting: 2.0.0 → 2.1.0