Bell Labs is a private production-management application for a tabletop campaign. It replaces a continuously recalculated spreadsheet with a dated ledger, a seasonal production plan, and history that can be deliberately reopened when the campaign needs a retroactive correction.
The application is a server-rendered Flask utility with a small amount of progressive JavaScript. It is designed for two trusted collaborators rather than separate player and administrator roles.
- Stockpiled and transient resources, dated withheld stock, reusable reservations, and per-block capacity.
- Ordered resource categories and resource-level production and ledger views.
- Versioned production methods with consumed inputs, outputs, reservations, capacity requirements, alternatives, and automatic-supply priority.
- One-off or recurring bundled transactions containing both incoming and outgoing resource quantities.
- Fixed work orders, recurring seasonal work, and production goals which the planner splits into feasible blocks.
- Recursive automatic production of eligible prerequisites, with cycle, deadline, stock, and capacity shortage reporting.
- Seasonal forecasts, stockpile time series, dependency exploration, and chronological resource ledgers.
- A soft-immutable history boundary: recording a season materialises what happened, while reopening history permits intentional corrections.
Bell Labs requires Python 3.10 or newer and uses SQLite through Python's standard library. On Linux:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txt
python run.pyOn Windows, the virtual-environment paths differ:
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe run.pyOpen http://127.0.0.1:8080. An empty installation offers a sample workshop which can be loaded to explore the interface.
Local mode stores its database at instance/bell.sqlite3 by default. Set
BELL_DATABASE to an absolute path to put it elsewhere. Runtime databases,
environment files, logs, and the entire instance/ directory are intentionally
excluded from Git.
Campaign time is displayed as Spring 1, Summer 1, Autumn 1, Winter 1, Spring 2, and so on. Each season contains ten blocks for processes which need finer timing, but normal planning and reporting remain season-oriented.
Production methods are versioned so later efficiency or recipe changes do not rewrite earlier forecasts or recorded history. Inputs are consumed when work starts, reusable assets remain reserved for the work's duration, and outputs arrive when it finishes. Unused transient resources expire after each block. Zero-duration work runs atomically in its explicit within-block order.
Production goals differ from fixed work orders: a goal specifies the desired quantity and time window, then the planner chooses feasible blocks. Fixed work orders retain their exact timing and take precedence. Eligible prerequisite methods may be generated recursively; capacity and reusable-asset requirements are checked but are not themselves expanded as material-production chains.
Quantities use exact Python Decimal values rather than binary floating point.
bell/domain.pycontains the database-independent simulation engine.bell/db.pyowns connection lifecycle, current-schema initialization, common queries, settings, and audit records.bell/schema.pycontains the complete current SQLite schema. Historical prototype migrations have been intentionally squashed;bell/migrations.pyapplies the supported production upgrades in sequence.bell/history.pymaterialises and reopens recorded transactions and work.bell/demo.pycontains the optional sample workshop.bell/projection.pyorchestrates and caches forecasts.bell/projection_data.py,bell/projection_domain.py,bell/projection_planner.py, andbell/projection_view.pyrespectively load consistent snapshots, translate domain inputs, schedule work, and build the rendered projection model.bell/dependencies.pybuilds consumed-input dependency views.bell/web.pycreates the Flask application and enforces authentication, security headers, and shared request behavior.bell/web_helpers.pycontains form parsing and request-level helpers.bell/routes/groups HTTP routes by application area.bell/templates/andbell/static/contain the server-rendered interface and its progressive enhancements.deploy/contains Linux/systemd, Windows, Tailscale, and environment templates.tests/contains domain and web integration tests.
Rendered projections are cached within each application process and keyed by a database revision maintained in the same transaction as planning-data changes. Concurrent requests share work only when they need the same revision and horizon; different horizons can calculate independently. Same-screen forms preserve the submitted record's viewport position after the server redirects, and result messages appear as fixed toasts.
On Linux:
.venv/bin/python -m unittest discover -s tests -vOn Windows:
.\.venv\Scripts\python.exe -m unittest discover -s tests -vThe projection characterization benchmark reports wall time and planner work counters for a short demo, a long horizon, and a goal-heavy automatic-supply chain:
.\.venv\Scripts\python.exe benchmarks\projection_baseline.pyGoal placement optimistically tests the complete remaining quantity at each start tick. It uses binary search only when that quantity is infeasible, while retaining trial results so feasibility and blocker reporting never repeat the same candidate calculation. The last accepted expansion is also the final plan, avoiding a duplicate automatic-supply pass after goal placement. Candidate trials also stop before expanding other prerequisites when they introduce a shortage for which no automatic supply method exists.
The supported production arrangement is Waitress bound only to
127.0.0.1, published privately through Tailscale Serve. Bell Labs then
requires a Tailscale identity and applies its own exact user allowlist.
See DEPLOYMENT.md for the Ubuntu/Debian systemd setup, a Linux foreground runner, the Windows Task Scheduler variant, upgrades, backups, and host migration.
Do not forward port 8080 through a router, bind Waitress to 0.0.0.0, or use
Tailscale Funnel. Funnel would make the application public.