Commit Graph

40 Commits

Author SHA1 Message Date
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
d7d0966adc feat(editor): snap dragged nodes to the 20px grid
Match Vue Flow's snap grid to the background gap so nodes line up
on the dots they already render against.
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
169dd043c3 feat(editor): explain refused loop-closure drags
Dragging a Flow back onto a Stock it already touches is refused (an
Information Link never targets a Stock), but that gesture is almost
always someone trying to "close the loop" by hand. The Flow's own pipe
already is the link back, so surface a self-dismissing hint saying so
instead of letting the drop die silently (F4: guide, don't nag).
2026-06-20 10:40:49 +02:00
Julien Calixte
9f11d5230d fix(editor): fit the view after a restored model is measured
Restoring on reload fit the view synchronously in onRestore, framing
against unmeasured 0×0 nodes, so the model landed jammed top-left. Arm
the same post-measure onNodesInitialized fit the sample/import loads use.
2026-06-20 10:14:44 +02:00
Julien Calixte
a44f1e7bb1 docs: record the inline glossary as F11 in the design 2026-06-20 10:13:21 +02:00
Julien Calixte
32498d51d1 fix(editor): render the palette above the loop-badge overlay 2026-06-20 10:13:21 +02:00
Julien Calixte
cd276d9d2a feat(editor): add glossary tooltips to the palette 2026-06-20 10:08:30 +02:00
Julien Calixte
e1efa3c823 feat(editor): gloss the selected element in a panel 2026-06-20 10:08:30 +02:00
Julien Calixte
6815b81701 fix(editor): fit the view after loaded nodes are measured 2026-06-20 10:07:59 +02:00
Julien Calixte
5e50b2dfd4 feat(model): add node and link glossary definitions 2026-06-20 10:05:58 +02:00
Julien Calixte
acce53ce47 fix(docker): copy pnpm-workspace.yaml into the install layer
pnpm 11 defaults strictDepBuilds to true, so a dependency build script
that is not pre-decided in allowBuilds becomes a hard error. The install
layer only copied package.json and the lockfile, so the vue-demi build
decision in pnpm-workspace.yaml was absent and the build failed.
2026-06-20 10:03:00 +02:00
Julien Calixte
72ef29413a feat(editor): wire autosave and add JSON import/export 2026-06-20 10:02:42 +02:00
Julien Calixte
75ebb39848 feat(editor): add debounced model autosave composable 2026-06-20 10:01:44 +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
1c571059df chore(deps): add idb for local persistence 2026-06-20 10:01:38 +02:00
Julien Calixte
bc90a9bca9 fix(editor): keep loop badges on nodes while dragging
Badge centroids now read Vue Flow's live computedPosition instead of the
store, which commits positions only on drop — so badges no longer lag a
node drag. Centres use real node dimensions, dropping the hard-coded nudge.
2026-06-20 09:42:37 +02:00
Julien Calixte
37017c1175 docs: align design docs and README with the editor 2026-06-20 09:37:50 +02:00
Julien Calixte
d3119e8a20 feat(editor): wire the canvas and mount the editor 2026-06-20 09:37:50 +02:00
Julien Calixte
03848ae893 feat(editor): add node, edge, palette, and loop-overlay components 2026-06-20 09:37:42 +02:00
Julien Calixte
0416581799 feat(editor): add shared loop-highlight state 2026-06-20 09:37:32 +02:00
Julien Calixte
0aaa4114d9 feat(store): add model store with snapshot undo/redo and loops 2026-06-20 09:37:32 +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
Julien Calixte
2c0d4b842f chore(deps): add Vue Flow and Pinia with pnpm workspace config
pnpm-workspace.yaml opts vue-demi out of build scripts; Vue Flow pulls
it in transitively and pnpm 11 otherwise fails the install on it.
2026-06-20 09:37:13 +02:00
Julien Calixte
aadc157144 docs(design): lead with the House of Quality visual
Move the visual above §1 so the assembled picture serves as an
at-a-glance overview; flip its cross-reference from "tables above"
to "tables below" to match the new position.
2026-06-20 02:26:59 +02:00
Julien Calixte
355c99e797 docs(design): add House of Quality visual
Render goals x functions (with the roof, importance weights, and basement
targets) as a TikZ House of Quality, generated from the existing QFD tables.
2026-06-20 02:20:21 +02:00
Julien Calixte
e76432d3ca docs: cross-link design docs with README
Add a Design & docs section to the README linking CONTEXT, DESIGN, and the
three ADRs, plus a backlink to the README from each of those documents.
2026-06-20 02:20:05 +02:00
Julien Calixte
8b64e8f6b7 docs(readme): drop avoided term "faucet" from tagline
CONTEXT.md lists "faucet" as an avoided term (the canonical word is Flow)
and DESIGN.md records it as dropped; align the README tagline.
2026-06-20 02:19:00 +02:00
Julien Calixte
cbbd61b6f4 docs: add ubiquitous language, QFD design, and ADRs 2026-06-20 02:09:09 +02:00
Julien Calixte
68a8c303d9 chore: initial scaffold 2026-06-20 01:28:32 +02:00