Distributed Systems Playground Open the Playground

Contributing#

Thanks for your interest. Bug reports, examples, library modules, documentation fixes and interface improvements are all welcome.

Setting up#

You need Node.js 18 or later and nothing else: the project has no dependencies.

git clone https://github.com/engineering87/distributed-systems-playground.git
cd distributed-systems-playground
npm test

The suites that need a page are separate, because they need a browser:

pip install -r test/browser/requirements.txt && playwright install chromium
npm run build && npm run test:browser

DSP_BROWSER=firefox or DSP_BROWSER=webkit runs the same suites on another engine.

Both run in CI on every push. npm test covers the engine, the runner, the language, the documentation and the translations; npm run test:browser covers the interface. Details in test/browser/README.md.

Open index.html in a browser to use the application.

How the code is organized#

FileContentRule
src/core.jslexer, parser, checker, interpreter, simulation engine, causal coneno access to the page, so it runs under Node
src/runner.jsbatch runs over many seedsno access to the page, so it runs under Node
bin/dsp.mjscommand line toolno dependencies; every command covered by a test
src/library.jslibrary modules written in Uponeach module documented and tested
src/examples.jsexample scenarios and timing presetseach example documented and tested
src/ui/the interface, one file per areathe parts share one scope: the build concatenates them in name order and wraps them once, so nothing is exported between them
src/i18n.jsItalian translation of the interfaceadd a translation for every new interface text
src/style.cssstyles for both themescheck light and dark
src/template.htmlpage structure
scripts/build.mjsbundles src/ into index.html
scripts/build-docs.mjsgenerates the documentation site in manual/no dependencies; supports the Markdown used in docs/
test/Node tests: engine, library, examples, guards, translations, documentation
test/browser/Playwright suites for the interface, one file per area
docs/documentationsee Writing documentation

index.html and manual/ are generated but committed, so that GitHub Pages can serve the repository as it is. After changing anything in src/ or docs/:

npm run build
npm test
npm run check

CI runs the tests and npm run check, which fails if index.html or manual/ does not match the sources.

Making changes#

Engine. Keep runs deterministic: every random choice must come from a named stream, and the order in which a stream is consumed must not depend on events that happen later (see How the engine works). Add a test for any change in behavior. If the change affects what the simulator models, update Assumptions and simplifications.

Language. New syntax needs a parser rule, checker rules with clear messages, interpreter support, tests, an entry in the language reference, and the grammar in the specification.

Library modules. Follow the steps in Writing your own. The test must check the module's guarantee under the conditions it is meant to survive. Document every difference from the textbook version.

Examples. Add the scenario to src/examples.js, a test that checks what the example is meant to show, and a section in Examples. Quote only numbers you obtained from the engine with the stated seed.

Diagrams. The diagrams of the documentation are drawn by scripts/make-diagrams.mjs, in a light and a dark version, with the palette of the application: four that explain the project, and one schematic per algorithm, drawn from the descriptions in scripts/protocols.cjs: roles, phases, messages and the reason it works. A new example needs an entry there, and the build warns when one is missing. The generator records every label as it draws it and refuses to write a picture whose text leaves the frame, so a long sentence fails the build instead of spilling over the edge. Edit the script, never the SVG: npm run build redraws them and npm run check fails when a file on disk is not what the script draws.

Badges. The ones that carry a number — algorithms, properties, documentation pages — are checked against the repository by the test suite. Adding an example or a page means updating the badge, and the tests will say so.

Commit messages. They follow the conventional shape, because the changelog is written from them:

type(scope): what changed, in lower case, no full stop

Types: feat, fix, perf, refactor, docs, test, build, ci, chore, style, revert. The first line stays under 72 characters; the body explains why, wrapped at 100. Pull requests are checked by node scripts/check-commits.mjs --range origin/main..HEAD, and npm run hooks installs a local hook that checks each message as you write it, plus a pre-push hook that runs the Node tests.

Security. Never match or clean up HTML with regular expressions, in the application or in the tooling: build markup safely, with an allowlist of elements and attributes and escaping per value, and read it by walking the text. A guard test enforces this, and another one fails if a regular expression is built from data: compare strings, or write the pattern as a literal. Data that comes from outside the page (imported files, shared links, local storage) is parsed without keys that could reach a prototype.

Interface. Work inside the part that owns the area, and add a new part only for a new area; the build fails if the bundle does not parse. Every new text shown to the user needs an Italian translation in src/i18n.js: an exact phrase, or a pattern when the text contains numbers or names. The test suite checks the texts of examples, presets and library modules. Check the change at a narrow width (about 375 pixels), on a laptop screen (1280 by 720) and on a large monitor, in both themes, with mouse and with touch emulation. Keep keyboard access working.

Writing documentation#

The documentation is part of the product. A few rules keep it useful.

Be exact. Every behavior described must match the code. When you quote a result, run it and state the seed. Programs in upon code blocks are compiled by the test suite; use text blocks for fragments.

Say what is simplified. If a feature approximates reality or departs from a textbook, say so where it is described and add it to Assumptions and simplifications.

Write for someone learning. Explain why before how. Prefer a concrete example to an abstract rule. Use the second person and the present tense.

Keep the tone plain. Short sentences, common words, no marketing. Avoid filler openings ("In this section we will…"), stacked adjectives, rhetorical questions, and phrases such as "powerful", "seamless" or "it's worth noting". Do not use emoji. Use bold for terms being defined and for controls the reader must find, not for emphasis in general.

Link rather than repeat. Each fact should live in one place. Relative links and anchors are checked by the test suite.

Write in English, with American spelling.

Changelog#

Add a line under Unreleased in CHANGELOG.md for every change a user would notice.

Reporting a problem#

Please include:

License#

By contributing you agree that your contributions are released under the MIT License.