Commit Graph

18 Commits

Author SHA1 Message Date
Julien Calixte
382fdddc68 feat(editor): give each Stock a unit
A Stock can carry a display unit (°C, people, $, …): a new optional field, an
inspector text input, validation + round-trip in io, and a readout beside the
live value on the canvas. Equip the demonstrative samples (Water L, Balance $,
Coffee °C, Population/Epidemic people, Yeast cells). Also bumps the fill gauge
opacity for a more vivid level.
2026-06-20 14:47:08 +02:00
Julien Calixte
f0d207c4d5 feat(model): make limits-to-growth a runnable two-flow logistic
Recast the S-curve as a Reinforcing inflow plus a crowding-driven die-off that
grows with Yeast², using only the existing proportional rule. Yeast now climbs
20 → ~1000 as a true sigmoid, and the detector still classifies it R + B — the
balancing loop stays visible, which a single "logistic" rule would have hidden.
Drops the carrying-capacity converter (a faithful one needs a divide rule).
2026-06-20 14:03:43 +02:00
Julien Calixte
40dc9fba43 feat(model): equip the sample gallery with runnable values
Give 10 of 11 samples initial values, rules, and a run window so they simulate
on load: Bathtub (linear), Savings/Escalation/Fixes-that-fail (Reinforcing),
Coffee (Balancing), Population, Epidemic (SIR), Tragedy (overshoot/collapse),
Drift (eroding goal), Predator-prey (damped). Limits to growth is left
diagram-only — its S-curve needs a saturating rule the vocabulary lacks.
2026-06-20 13:56:19 +02:00
Julien Calixte
5b6e830778 feat(model): simulate models from rules over information links
Phase 2 brings Models to life. ADR-0004: behaviour comes from a small fixed
vocabulary of rules (Constant / Proportional / Gap) read over the inbound
Information Links, not free-form formulas — valid by construction.

- types: Rule union, SimSpec, initialValue; replaces the unused equation field
- simulation: forward-Euler engine, dependency-ordered evaluation, algebraic-loop
  detection, non-negative stocks, and a divergence guard
- io: validate and round-trip the new fields (F8)
2026-06-20 13:56:06 +02:00
Julien Calixte
964e621f0e fix(editor): match the flow arrowhead weight to its line
Vue Flow's open arrow renders at 0.625x the edge stroke (its 20-unit
viewBox is squeezed into a 12.5 marker box), so the chevron looked thin
against the 2.5px pipe. A marker strokeWidth of 20/12.5 cancels the
downscale, drawing the head at the line's weight at any width.
2026-06-20 12:43:27 +02:00
Julien Calixte
528fc97c7f refactor(model): polish the coffee and limits-to-growth samples
Rename the coffee outflow "heat loss" to "cooling" so the balancing loop
reads more naturally, and stack carrying capacity above the source in
limits to growth so its link to crowding is a clean horizontal hop.
2026-06-20 11:51:49 +02:00
Julien Calixte
21a459256a feat(editor): dock flow arrows square at any pipe angle
Swap the filled-triangle arrowhead for an open arrow on flow pipes and
information links, and route flow pipes through a custom cubic edge whose
horizontal flatten arm scales with the vertical drop, not just the
horizontal gap. Vue Flow's default arm collapses toward zero when the
valve sits nearly above the stock, so a steep pipe stayed flat only in
its last pixels and the arrowhead detached from the visible line. The
pipe now keeps a real horizontal run into the stock's left edge at any
approach angle.
2026-06-20 11:51:34 +02:00
Julien Calixte
df03012c8b style(model): align every sample layout to the 20px grid
Snap all sample coordinates to multiples of 20 so they sit on the
editor grid and read cleanly. Computed midpoint() valves had to land
on grid points too, so a few endpoints were nudged (e.g. escalation
arsenals 300->280, limits-to-growth source -300->-280). Population is
re-laid as a grid cascade so its links no longer overlap the pipes.
2026-06-20 11:19:37 +02:00
Julien Calixte
27b7a8da5e feat(model): add fixes-that-fail and drift traps to the gallery
Two more Meadows system traps: Fixes that fail (a balancing
road-building fix whose induced-driving side effect reinforces the
congestion it targets) and Drift to low performance (an eroding goal
that spirals actual performance and the standard downward).

Also re-lays-out the coupled-stock samples for readability: predator
and prey and escalation now use aligned two-row layouts, and fixes
that fail stacks its flow valves in one column so the backfire link
reads as a clean vertical.
2026-06-20 11:09:04 +02:00
Julien Calixte
26dd245a94 feat(model): extend the sample gallery with five more models
Add a second tier past the four-model primer: Limits to growth, Predator
and prey, and Epidemic each introduce one structure the primer never
shows, plus two of Donella Meadows' system traps — Tragedy of the
commons and Escalation — to contrast healthy dynamics.
2026-06-20 10:40:55 +02:00
Julien Calixte
5e50b2dfd4 feat(model): add node and link glossary definitions 2026-06-20 10:05:58 +02:00
Julien Calixte
4c55ff9ffa feat(model): add IndexedDB-backed model repository 2026-06-20 10:01:44 +02:00
Julien Calixte
9f71febca0 feat(model): round-trip models as versioned JSON 2026-06-20 10:01:43 +02:00
Julien Calixte
6d03d706a0 feat(model): add a gallery of sample models 2026-06-20 09:37:32 +02:00
Julien Calixte
5c3f467a24 feat(model): detect and classify feedback loops
Loops are derived from the wiring, never stored (ADR-0001): a signed
graph (link polarities plus flows' inherent inflow/outflow) is searched
with Tarjan SCC and a capped enumeration, classifying each cycle R or B
by the parity of its negative links. Both the result count and the
search are bounded so detection can never blow the frame budget.
2026-06-20 09:37:26 +02:00
Julien Calixte
fd94a8b7ed feat(model): guard connections to preserve valid structure 2026-06-20 09:37:19 +02:00
Julien Calixte
8fac6f4694 feat(model): project the model into a Vue Flow graph 2026-06-20 09:37:19 +02:00
Julien Calixte
95990b0d1f feat(model): add domain types and model factory 2026-06-20 09:37:18 +02:00