Economy as code + the why layer (loops, attribution, phase portraits); relicense to AGPL-3.0#38
Merged
Merged
Conversation
Full-codebase lint sweep. Two findings fixed: - test/smoke.js accepts a SMOKE_CHROMIUM env var to point the launch at a pre-installed Chromium binary, for sandboxes where Playwright's browser download is unavailable. Default behavior (and CI) unchanged. - js/app-props.js queue-metrics comment still described the old em-dash placeholder; the code shows "n/a". Everything else came back clean: syntax on all JS files, no curly-quote delimiters, em dashes only in code comments (user-facing copy clean), no console.log/debugger/TODO leftovers, no trailing whitespace or tabs, CSS uses tokens outside :root, index.html script order intact (mixins after app.js), model/engine still DOM-free. 197/197 unit tests and the browser smoke test pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BTK8CoB2M6ofpYRXpQEVVL
Three DOM-free additions that make an economy a first-class code artifact, documented in docs/ECONOMY_AS_CODE.md: - js/dsl.js: the .econ text format. dslSerialize/dslParse round-trip the diagram JSON losslessly (serialize-parse-serialize is a byte-identical fixpoint; normalizeEconJSON defines semantic equality up to id renaming). Sugar for the common cases, generic key=value attrs diffed against constructor defaults for everything else, so new model fields serialize automatically. File menu: Save as text (.econ); Open file now reads both formats. - js/assertions.js: design tests over a run. Quantifiers always / never / eventually / at end / at step N over the existing formula language, with node labels (sanitized), diagram variables and step in scope. CLI flags --assert, --assert-file, --pass-rate; exit code 2 on failure. Monte Carlo trials are checked individually via new perStep/onTrialEnd hooks in runMonteCarlo. - js/codegen.js: buildEconomyModule bundles model + engine + diagram into a dependency-free UMD file with a createEconomy() API (step/run/get/set/ fire/values/onStep, seed + param overrides). File menu: Export as JS module; CLI: --emit out.js. CLI also converts formats with --to-dsl / --to-json and accepts .econ input everywhere. Docs: README economy-as-code sections, CLAUDE.md architecture + commands, three KB articles. Tests: 15 new unit tests (round-trip kitchen sink, fixpoint, sugar, assertions semantics, generated-module runs under Node, CLI end-to-end including exit codes) and a smoke check for the in-page round trip, codegen fetch path, menu items and KB category. 212/212 unit tests and the browser smoke test pass. Also relicense the project from MIT to AGPL-3.0: canonical license text in LICENSE, SPDX id in package.json, License section in README. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BTK8CoB2M6ofpYRXpQEVVL
Assertions graduate from CLI-only flags to a first-class diagram feature: - Diagram.assertions (array of assertion strings) serializes with the file, round-trips through .econ as `assert "..."` directives, and is covered by the kitchen-sink round-trip fixture. - New Checks rail panel (js/app-analysis.js): edit the saved checks with live parse validation, then verify them against a fresh isolated run (Check once) or inside every trial of a Monte Carlo batch (Check batch, async with progress). Results render as PASS/FAIL rows with failure details and per-assertion fail counts across runs. The live canvas state is never touched; a seeded clone never leaks its RNG stream into the session. - cli.js --check runs the suite saved in the diagram (plus any --assert extras), so a .econ file carries its own tests: `node cli.js economy.econ --check` is a complete CI job. - KB article updated for the panel, docs (README, ECONOMY_AS_CODE.md, CLAUDE.md) extended. Tests: unit coverage for the assert directive, Diagram serialization and --check exit codes (213/213 pass); smoke coverage for the panel render, single + Monte Carlo checking and .econ serialization. Browser smoke passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BTK8CoB2M6ofpYRXpQEVVL
js/loops.js (DOM-free): detectLoops(diagram) enumerates every elementary cycle in the causal graph and classifies it by the system-dynamics polarity rule: reinforcing (R, even negative links), balancing (B, odd), pure resource circulation (F) or unclear (?). The causal graph goes beyond the drawn arrows: flows and triggers are positive links, reverse triggers negative, activators take their operator's sign, modifiers the sign of their amount (mode-aware: step-mode modifiers carry no source influence), and formula reads (register formulas, rate/ weight/modifier formulas, variable conditions) become implicit edges from the publishing node, signed by a numeric probe of the formula with the RNG pinned so stochastic formulas probe deterministically. Parallel edges collapse per node pair; enumeration is a bounded smallest-start DFS with maxLoops/maxLen caps plus an explored-edge budget, reporting truncation. UI: new Loops rail panel lists loops (badge, node chain, per-link signs) and clicking one spotlights it on the canvas via a new renderer emphasis pass that fades non-members; leaving the panel clears it. CLI: --loops prints the same table. KB article, README and CLAUDE.md updated. Sanity-checked against the bundled demos: the business cycle surfaces its deposit-compounding R loops and the GDP-investment accelerator, the auction economy shows its just-in-time production gates as B loops (66 ms on the largest demo). Tests: 8 new unit tests (self-loops by factor sign, sign multiplication, F circulations, operator-signed activators, numeric formula probes both slopes, trigger/reverse-trigger, dedup + caps + truncation, CLI output) and a smoke check driving the panel, spotlight and clear path. 221/221 unit tests and the browser smoke test pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BTK8CoB2M6ofpYRXpQEVVL
…d it) Engine now records the data attribution needs: - Every history entry carries `flows`: resource amounts per connection and applied modifier deltas per connection, accumulated over the entry's whole span. Stride decimation merges dropped entries' flows forward and folds trailing spans into the live accumulator, so the identity delta = inflows - outflows + modifiers + residual holds exactly on long runs. Modifier recording uses APPLIED amounts (capacity clamps, empty takes). Interactive fires between steps accumulate into the open span. - reset() records a step-0 baseline entry, giving charts/scrub the run start and attribution a "from" value for the first step. Checkpoints carry the open span accumulator. js/attribution.js (DOM-free): attributeChange() builds the ranked breakdown with node-type-aware semantics (drains only take, limited sources only give, registers recompute from formulas), a residual line for internal behavior (conversions, queue balk/renege) and float-dust guarding. UI: plain click on the timeline (drag still compares, click still clears a comparison) picks the nearest series point and opens a why-popover: value span, delta, signed rows per contribution, residual, and a canvas spotlight of the contributing connections while open; Esc or click-away closes and restores any prior emphasis. CLI: --why "Gold@120" (repeatable, "Gold" = final step) prints the same table after a single run. Docs: KB article, README analysis bullet, CLAUDE.md. Two pre-existing history-length expectations updated for the step-0 baseline (checkpoint truncation unit test, CSV smoke row count). Tests: 7 new unit tests including the decimation invariant (1500-step run, every entry's flows sum exactly to its snap delta) and CLI --why end-to-end; smoke drives the popover, spotlight and Escape path. 228/228 unit tests and the browser smoke test pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BTK8CoB2M6ofpYRXpQEVVL
New chartType 'phase' on on-canvas charts: the first tracked node is the x axis, the second the y axis, and the run traces a trajectory through state space. Older segments fade (about 12 opacity-ramped chunks, cheap to rebuild), a hollow dot marks the start and a solid one the live end, axis extents show the raw data range and axis labels take their node's series color. Limit cycles read as orbits, equilibria as inward spirals, runaway growth as a curve off the corner. Hover snaps to the nearest trajectory point in 2D (time charts keep their x-only mapping) and reads out step + both values. The chart style picker gains a Phase chip with an explanatory note, and the predator-prey demo now ships a phase portrait beside its time chart, where the limit cycle draws itself as an orbit. Serialization and .econ round-trip come free via the existing chartType field (type=phase). KB and README updated. Tests: unit round-trip for the type through JSON and .econ; smoke renders the portrait (chunks, markers, colored axis labels), verifies the 2D hover snap and that demo 1 includes one. 229/229 unit tests and the browser smoke test pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BTK8CoB2M6ofpYRXpQEVVL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two feature arcs on top of
main, plus a relicense:Economy as code — the diagram becomes a first-class code artifact:
.econtext format (js/dsl.js): readable, diff-friendly, lives in git. Lossless round-trip with the canvas (serialize→parse→serialize is a byte-identical fixpoint; a kitchen-sink fixture covering every node/connection feature guards it). Sugar for the common cases, generickey=valueattrs diffed against constructor defaults for everything else, so new model fields serialize automatically. File menu: Save as text / Open reads both formats.js/assertions.js):always gold < 500,eventually score >= 100,at step 25: queue <= 3, checked per step. Saved with the diagram (Checks rail panel,assertlines in.econ), run in-app against a single run or every Monte Carlo trial, and in CI viacli.js --check/--assert(exit code 2 on failure,--pass-ratefor stochastic tolerance).js/codegen.js): File → Export as JS module (or--emit) bundles model + engine + diagram into one dependency-free UMD file with acreateEconomy()API (step/run/get/set/fire/values/onStep, seed + param overrides). The balanced economy is the shipped economy.--to-dsl/--to-json;.econinput accepted everywhere.The why layer — the app explains behavior, not just plots it:
js/loops.js): every elementary cycle in the causal graph (flows, triggers, activators, modifiers, plus implicit formula-read edges signed by numeric probing with a pinned RNG), classified reinforcing / balancing / circulation / unclear. Loops rail panel with canvas spotlight;cli.js --loops.js/attribution.js): click any timeline point to see why it changed — per-connection inflows/outflows, applied modifier deltas, honest residual. The engine now attaches per-span flow records to history entries, merged forward through stride decimation sodelta = in − out + mods + residualholds exactly on long runs (unit-tested across 1500 steps and two stride doublings). History gains a step-0 baseline.cli.js --why "Gold@120".License: relicensed MIT → AGPL-3.0 (canonical text in LICENSE, SPDX id in package.json, README section).
Architecture
All six new modules (
dsl,assertions,codegen,loops,attribution+ engine hooks) follow the repo's DOM-free contract: same files load in the browser,cli.js, andtest/run.js. Docs indocs/ECONOMY_AS_CODE.md; CLAUDE.md and KB articles updated alongside.Tests
🤖 Generated with Claude Code
https://claude.ai/code/session_01BTK8CoB2M6ofpYRXpQEVVL
Generated by Claude Code