WORLD ECONOMY

DEVELOPMENT JOURNAL  ·  170 entries  ·  current milestone: Dev Loop 7 · Le tableau de bord

A persistent economic world where companies produce, trade, compete, invest and fail, and prices emerge from capacity, costs, supply and demand. This journal records how it is actually being built — what each development loop attempted, why, what broke, what the economy did, and what changed about the design. Newest entry first.

The project sheet

Chantier G's second table, Décider. An option opens its sheet on the phone and in the cockpit: the size and the loan to choose, then the three pictures of the Godot panel — the break-even on the market's month with its verdict, the payback as a curve to the cost line with the crossing dated, the quoted day as the strip — the region's market, the inputs, and Build for the quoted total. project.ts lays them out of the server's quote; tested.

[ read development log ]

Where the money goes

Chantier G opens — the charts, table by table with the owner, Empire first. The hero's line spans 30 days, 90 days or a year, as net worth, cash or debt, with hairline guides and the day under the finger. Under it, where the money goes: the window's sales as one strip eaten by the costs by kind — inputs, operating, variable, loans, tax, other — the margin in green, the overrun in red, a sentence naming the biggest item, and each kind a door to its remedy. Phone and cockpit.

[ read development log ]

The report as a scene, the news in the player's words

Chantier F closes. Rapport laid out for the cockpit: the net and four tiles across the top, what the orders and the markets did on the left, what to decide, what is coming and what the world did on the right. The news in the player's language: newsText says each event from its kind and data — assets online, failures, entrants, forecasts, shocks, contract exits — and keeps the server's sentence otherwise; the nine world events named. Every scene is wide; every gesture of a builder is in HTML.

[ read development log ]

The receiver and the contracts

Godot's Receiver and Contracts tabs under two cards of Décider. The lots the company's sector may buy, cheapest first, each with what it is, costs to keep, has left and how its market stands; the server's preview and one confirmation to buy. The company's contracts with deliveries, earnings and the exit penalty; the open offers that concern it accepted for the free quantity; a form to post one prefilled from the contract context. Every gesture a builder makes in Godot is now in HTML.

[ read development log ]

The credit sheet

Godot's Banks tab folded under Empire's debt tile and Décider's budget line. The company's standing as the lenders read it; debt and monthly service; each loan with prepayment (principal, fee, what is left against the reserve) and refinancing (every lender's take-over offer with the interest saved) at the server's quotes; a request by purpose and amount answered by every lender with an offer or a refusal, one taken.

[ read development log ]

The world as a scene

Godot's Regions, Policy, Leaderboard and Events tabs folded into the cockpit's Monde. The pulse as four tiles; each region as an economy — companies based there, share of demand, output a day and its move, taxes, land used and its price, the local markets with price, move, online and pipeline capacity; the events and the news in two columns; the ranking's top ten with the player's line, the six policy knobs a builder feels, the treasury's position.

[ read development log ]

The asset sheet

Chantier F opens: the depth under the six screens, Godot's tabs folded into sheets the cards open. The asset sheet: earned, margin, book value, the receiver's price today, the thirty-day profit line, the life, the flags; then mothball, sell at the receiver's quote (original cost, depreciated value, price, fee, net) and move at the movers' quote (cost, days offline, day back). Actifs becomes a cockpit scene: four tiles, a three-column grid of asset cards with sparklines, the chantier in two columns.

[ read development log ]

The cockpit on an 8-px rhythm

The owner's reading of the cockpit: better, but not everything seems well aligned. The bench's captures said where. One rhythm of eight pixels: a 24-px gutter shared by the scene, the ribbon and the band; a 32-px head on both columns so their first cards start on one line, the company and the world moved to the ribbon's head; cards 16 px inside and apart; the hero's sentence on its own row; a 72-px gutter for the axis labels, which no longer cross the curve; asset cards that fill their card; the scenes still in the phone's layout held to 760 px; the band's pulse in fixed columns with a rule before the ticker.

[ read development log ]

Decisions, the ticker and the 2K cockpit

The third cockpit loop. The report's data moved into one hook with a pure decisionsOf, so the ribbon opens with what asks for a decision - an output unsold, an input short, a missed instalment, a lot for sale - each a click to its screen, and the phone's report reads the same list. The band's prices run as a ticker, paused under the pointer. From 2400 px wide the stage is the 2560 x 1440 design with a second scene beside the first and a wider ribbon. Photographed at 1920 x 1080 and 2560 x 1440 with a report window open.

[ read development log ]

Marchés and Décider for the scene

The second cockpit loop: the two screens where the phone's column wasted the most room, laid out for the 1920 x 1080 scene. Marches wide: the products on the left - yours first, then the world by region with the tension bars - and the chosen market's big ninety-day chart on the right with its price, its move, the unmet and unsold shares and your share. Decider wide: the question, the cash, the region and the shortages on the left, every affordable option as one comparative table on the right with Build on each row. The data moved into one hook the phone and the scene share.

[ read development log ]

The cockpit on a scaled stage

The owner's asks in turn: a whole other view for the full screen, aimed at 1920 x 1080 and 2K, that shrinks as a whole when windowed rather than reflowing. A mockup at both sizes approved, then the build: from 900 px the HTML client is a 1920 x 1080 stage scaled to the window (floor 0.75, then the window scrolls), centred on black. The rail with the six screens, full screen and the settings; the scene, with Empire laid out wide - the hero with a wide line and axis marks, the four readings on a row, the assets as a grid beside your markets - and the other screens as they are for now; the ribbon with what is coming, the prices on the move and the news; the band with the pulse. The bench at 1366 x 768 caught the cut-off stage and a finished project shown as a chantier; fixed.

[ read development log ]

The desktop, side by side

The owner's first reading of the HTML client the morning after - belle interface, then: could /play-html/ have a full desktop version? A wide window showed a phone's column. From 900 px the pager is now a grid of three columns and two rows, the six screens at once, each a bordered column that scrolls on its own; nothing slides, the dots are gone; a screen the app asks for is brought into view and lit. The same markup as the phone's. Photographed at 1440 x 900.

[ read development log ]

Rapport in HTML, and the home screen

The sixth screen, and what makes the HTML client an application: it sits on the phone's home screen and the morning report reads offline. Rapport from the server's since of loop 147 - the money in one figure and three tiles, what the standing orders did, what asks for a decision with a slide to its screen, what is coming in real time, the failures in the player's markets, mark as read - opened once when a day or more passed. A web manifest, icons and a service worker that keeps the shell and the last reads, caches named by the build; the install offered in the ... sheet. The bench photographs every screen. All six screens of D97 exist in HTML one night after D98; the Godot client stays complete at /play/.

[ read development log ]

Marchés and Monde, in HTML

The fourth and sixth screens of the HTML client (D98), with real charts. Marches: your markets first - what each market did to you over thirty days, the revenue, the price and its move - then the world by region, one row per product with a tension bar (unmet demand amber, unsold offer cyan), a tap opening the ninety-day price chart drawn by Recharts on the card's ground. Monde: the pulse (median price move, companies alive, failures of the last thirty days, events under way), the ranking by net worth with the player's own line, the news. The bench showed a fresh company with cash 0: the founder's grant sits on deposit, so cash and deposits are now counted together where the server counts them together. Five of six screens real.

[ read development log ]

Décider and Actifs, in HTML

The second and third screens of the HTML client (D98), so a new player never needs the older client. Decider, ported from loop 155 as pure tested functions: the question in the player's situation, what the world lacks, the region's options from the doors and a quote each, three cards with Build through an in-page confirmation above $5M - and, with no company on the world, the founding form. Actifs: one card per asset with the state in words, what it earned since built and its margin from the books, a thirty-day profit line, the life bar, the amber unsold or input-short sentence, mothball and reactivate; the chantier as a strip with the delivery in real time on a slow world. Every action: the call, a toast, the state read again. Three of six screens real.

[ read development log ]

The HTML client

D98: a second client, in HTML, on the same server. The owner asked late on 2026-10-27 whether React/HTML could reach the same richness as Godot - maybe better - and answered it themselves: Godot only glues the APIs; leave /play/ as it is and build /play-html/ on the same APIs and back end. web/ is Vite + React + TypeScript, 52 kB of script gzipped against 49 MB: the charter as CSS with the bundled fonts, same-origin API with the bearer token and X-World, the live feed with a backoff, sign-in, the world remembered (casual first), a one-line header, the six screens as a snap-scrolling pager with dots, Empire bound to the company detail with the verdict sentence and the four readings, a company with nothing built opening on Decider. Caddy serves it; the deploy builds it; the bench photographs it. Godot stays complete at /play/ until the web client has caught up.

[ read development log ]

Décider: what to build next

The second of the six screens (D97). A company that has built nothing opened on an empire empty by construction, with Build folded at the bottom; the decision is now the screen. A new panel, second screen of the pager and a tab on a desktop: the question in the player's situation, what the world lacks (unmet demand, then a price above its average, from the market summary), and the region's options from the server's doors and a quote each - ranked shortest payback first, a shortage product ahead, a warning last - as three cards with margin, payback, inputs, a reason line and Build through the usual confirmation. A company with nothing built opens on it once per session. Kind and product names in both languages. No change to the economy or the server.

[ read development log ]

The pager and the one-line header

Chantier E rewritten as six screens (D97) after the owner's phone reading and the mockup they approved. First the visual bench - headless Chromium on the VM photographing the deployed client at 390 x 844, signed in, tab by tab - which showed the chrome taking the top third of every screen, Markets overflowing sideways, the Regions map overlapping and the World table breaking words. Then the frame: a Pager the finger slides between (the first twelve pixels decide the axis, a fifth of the width moves a screen, hidden screens cost no render), four panels as screens on a phone - Empire, Markets, Report, World - the ten others and every setting in the ... sheet, and a header of one line: the day, the company, the live dot. Desktop untouched; Decider and Actifs come in 155 and 156.

[ read development log ]

Founding on the world you are on

Item 16's first finding, an hour after loop 152: the owner pressed the founding button on their phone and nothing seemed to happen. The server log says what did: the founding went through on main, the default world; the switch to casual eight seconds later showed the form again, and every press from then on was refused 409 unknown region 'north' - the region option is re-filled only when the count of regions changes, and every world has two, so casual's form still carried main's ids. The refusals landed on the message line at the bottom of the phone screen, unseen. The client now compares region ids, keeps the selection across worlds, and writes a refused founding's reason in red under the button. Nothing changed on the server. Open for the owner: the game still opens on main, not on casual.

[ read development log ]

Your markets, and the rest folded

Chantier D, items 13 and 14 closed. A card under the four readings, one row per market the company sells on: product and region, what the market did to the company over 30 days (you sold everything you offered; 22 % of your offer went unsold), the price today and its move since the day before, each row a tap to the market. The build, expenses, operations and financing sections open folded - the hero, the tiles and the cards say first what they say - while assets, projects and contracts stay open. My Company now reads, top to bottom: name and state, the hero and its verdict, four readings, your markets, the asset cards, the chantier, the loans, the contracts, and everything else folded. Four loops today from the mockup the owner approved from their phone.

[ read development log ]

The asset cards, the chantier and the debts in real time

Chantier D, item 13, second half. The asset card is a card in the charter's sense: kind and units, id, region and product, the state in words with its dot (online, commissioning, mothballed, short of an input), what the asset earned since it was built with its margin from the server's books, its sparkline, the life bar, and - when the server's 30-day shares say an input ran short or a fifth of the output went unsold - an amber sentence to decide, each a tap to its market; every former figure under a details fold. The project card and the loan card say their day in real time on a slow world (in 1 d 14 h - Thu 14:05) from what the clock already sends, and nothing at all on a fast one. No new server work.

[ read development log ]

The hero and the four readings

Chantier D, item 13, first half: My Company opens on the empire. The server says a company's net worth on every history row and a verdict - profit and expenses a day over the last seven rows, revenue today and yesterday, the 30-day change of net worth, days to cover the debt, runway, what the instalments cost a day and when the next falls, rank by net worth among the living, memoised once per world day. The client draws a card - the figure in the mono face, its change, an 84-pixel line, one sentence in five forms (you earn X a day; at this pace the debt is covered in N days, 12 h of real time) - then four tiles: cash with its runway, revenue today against yesterday, debt with its cost and next instalment, rank. The nine-figure header is one line; the fourteen tiles and charts of loop 66 follow untouched, for loops 151 and 152 to fold.

[ read development log ]

The cockpit charter

The first loop of chantier D, the builder's dashboard, and a decision (D96): the client's one visual language, taken from the mockup the owner approved from their phone. A warm black ground, every reading on a card a shade lighter with a hairline edge, cream text, the four signal colours kept and grey for everything that asks for nothing; Inter for the words and JetBrains Mono for the figures, bundled so the Web build has a face of its own for the first time; headings as small tracked capitals; the tab strip as an amber rule under the current tab. All of it in ui.gd and ChartTheme, so the fourteen tabs changed skin at once. Screenshots could not be taken on the VM (no display); the owner's phone is the review.

[ read development log ]

The Report tab

Chantier B, item 8, the client side of loop 147 and the last loop of the autonomous night. A Report tab, second in the bar, asks /since with the last day the client saw and draws the answer in order: money with cash and debt at both ends of the window, your markets with the unsold share, the inputs that ran short, assets built and retired and being built, loans paid and missed, contracts, the standing orders that played, and the world only where it touches your markets - failures in your sectors, the receiver's lots on your products at today's price, shocks and forecasts. Every line opens the panel it comes from; a market line opens Markets on that product. The client remembers the last day it saw per account, world and company beside the language in settings.cfg; the window stays where the session found it until Mark as read, so the refresh that displays a report does not eat it; when a day or more passed the tab brings itself forward once. Nothing computed on the client. Report sits second rather than first because the shell's tests, the F-keys and the Guide all know My Company as the first tab, and a tab that brings itself forward does not need the slot. Parity with 28 new keys, the smoke rendering a fixture into exactly nine lines, the walkthrough; deployed with a fresh web export.

[ read development log ]

What happened since you left

Chantier B of Dev Loop 7, item 7: the server side of the morning report. At a world day an hour a player sees about one day pass per visit, so the unit of attention becomes what happened since you left. GET /companies/{id}/since?day=N, private, tells the window by subject: money in and out with the expense kinds and the stocks at both ends; per market what was offered, sold and left unsold; which inputs went short; assets built, retired, sold and bought and the projects in flight; loans taken, paid, missed, repaid, refused; contracts signed, completed, ended early; the standing orders that fired; and from the world only what concerns the company's markets - shocks, forecasts, failures in its sectors, the receiver's lots on its products at today's price. Nothing is computed that the dashboards do not already show; the server remembers no visits. The test chained two windows and found the boundary: the day the player last saw was in progress when they left, so its row belongs to the window and the window opens on the row before. Found on the way: each of the night's restarts lost the days since the last periodic snapshot, because the container's thirty seconds of stop grace killed the shutdown snapshot of a 17,000-company world - stop_grace_period 180 s, TimeoutStopSec 240, and the self-deploy refreshes the units. The baseline suite finished: 384 passed, one failure that needs the portable PostgreSQL this host does not run.

[ read development log ]

The casual clock

Chantier A of Dev Loop 7: D95 gets a name, a world and a face. SPEEDS gains casual = 1/3600 days a second, a name PUT /clock accepts where the clock is open and the client labels in both languages, with a button, key 8 and a sentence in the Guide's time topic. WE_EXTRA_WORLDS entries read name[:seed[:speed[:world_gen[:regions]]]] through registry.parse_world_spec, so the first casual world is one line of the playtest settings - casual:20261027:casual:procedural - persisted and selectable beside main, which stays the default: making the casual world the front door is a decision about what every new player lands on, and the night does not take it for the owner. A slow world is read in real time: /world carries seconds_per_day and next_day_in_seconds from the scheduler's own clock, the client's status line says 1 world day ≈ 60 min · next day in 42 min, counted down every thirty seconds, through a Formatting.duration that says 42 s, 42 min or 1 h 05. The engine did not change: it sees whole days and never knew how long one takes. Clock and parity suites, Godot smoke and walkthrough pass; deployed with loop 145 in one release.

[ read development log ]

main2 runs again

The first loop of the autonomous night, chosen because it is the smallest and because the casual world of the next loop will be procedural too. Loop 144's restart surfaced a traceback the previous container had been printing to nobody for nineteen days: KeyError 'north' from consider_entrants through NpcPolicy.choose_region. main2 - a procedural world whose regions are longmead and kingsrea - had stood at day 24,840 since 2026-10-08. choose_region's fallback, returned when every region is skipped for want of land, was the company's home region, and an entrant is built, then asked where to build, then given its home: in between it carries the dataclass default, north, a real region in the baseline and a missing key in a procedural world. The fallback is now a region the world has, an entrant is born in its drawn region, and the banks are at home in the world's first region (north in the baseline, so the golden snapshot is unchanged). A test fills every region of a procedural seed and runs sixty days that used to raise on the first. Not deployed alone: loop 146 restarts the same server.

[ read development log ]

The journal online, and the casual pace

The first loop in six weeks and the first run from the game server itself, the owner driving from a phone. Their direction, in their words: a dashboard-based game - the dashboards are the game - casual and slow, about acquiring assets and building rather than trading. This loop writes nothing an economist would notice: it writes that direction down before any code follows it, and does two small things the owner asked for. The journal is deployed at /devlog/ next to the site and the client (reversing the owner's own loop-119 choice, on their word of today), with the same no-cache rule the site's files got in loop 134, a footer link in both languages and the loops counter corrected from 117 to 144. docs/DEV_LOOP_7.md, Le tableau de bord, states the phase's question - can a player who opens the game once a day, on a phone, for ten minutes, read in one screen what happened and what to decide, and does the company keep running through the orders they left - and seven chantiers: the casual clock, the morning report, standing orders as the way one plays, the builder's dashboard, the phone first, being called, playtest 7. D95 fixes the reference pace of a casual world at one world day an hour: the live worlds age a year a night, which is no pace for a daily visit; the engine never knew how long a day takes, so the pace is a value, not a feature. And thirty-nine scripts stored without their executable bit get it back, because a fresh Linux clone could not run tooling/setup.sh. No Python or GDScript changed; the gate was the site's static check and /devlog/ answering 200 over HTTPS.

[ read development log ]

Four bars, side by side

The owner's feedback on the per-asset view in OPERATIONS: the bars say the right things, but they are stacked one under another, so a wide screen becomes a column of long lines that say little - be compact, put the assets side by side, four clean little bars showing a percentage. That is a layout complaint with an economics consequence: a company owns many assets, and a reading you must scroll to compare is a reading you do not make. A new widget, MiniBars, draws a small card with a title, a line of context and up to four thin bars each carrying its own percentage; one card per asset, in a row that wraps. The four measures all being percentages, they share a scale: what it produced against what it could have, how well the inputs that asset needs were covered, the days it was online, and its margin against its own revenue. The input bar is the new fact - coverage existed before only as a company-wide chart per input market, which said hosting was short but never which asset went hungry; inputs_per_unit on each asset lets it be matched to the market it actually buys on, its region's first and the world market otherwise. Two details decided the implementation: Layout.flow() returns a plain HBoxContainer on a desktop and does not wrap, so the cards use an HFlowContainer directly as the coverage charts already did; and every percentage goes through Formatting rather than a %% template, which is loop 142's narrow-no-break-space lesson applied rather than merely recorded.

[ read development log ]

Where the output is lost

The OPERATIONS section held eight things - a production flow, bullet rows, a day ribbon, a price comparison, coverage per input, per-asset utilisation, supplier reliability, two tiles - all true, none of them answering the question the owner actually asked of this game: I have twenty-nine percent unsold and I cannot understand why. The facts were on the screen, scattered across four widgets that never met. OPERATIONS now opens with one causal chain per output market: capacity, covered by inputs, reserved by contracts, offered, sold, five bars on one scale, so the step that loses is the bar that is short. The sentence underneath names it - supply when the inputs did not cover capacity, demand when what was offered did not sell, expansion when everything that could be made sold - each a statement about the bars above it, never a recommendation. It needed no server change: operations_30d already carried share_obtained and a limiting flag per input, and a recipe being Leontief, the worst-covered input bounds every output. Sell-side contracts are told from buy-side by seller_id, which matters - the smoke company is the buyer of its hosting contract, so its reserved bar is correctly empty. Found on the way: the parity test rejected three new French strings and was right, because French sets a narrow no-break space U+202F before a percent sign and I had copied an ASCII one that looks identical in a terminal; the fix was applied by key, since a count showed five candidates rather than three.

[ read development log ]

A margin per asset

Loop 140 made the panel's figures mean what they say, but they were still the company's figures: one runway, one cost per unit, one margin, for a company that might hold a data center earning well and a fleet earning nothing. The data for the finer reading was already there and had been since loop 81 - every daily row carries by_asset, the revenue, inputs, fixed cost, variable cost, output and state of each asset owned - and in sixty loops it had only ever been used to colour a treemap. It was never read as economics. COSTS now carries one row per asset over five measures, each on its own scale: margin a day, margin against the asset's own revenue, what it produced against what it could have, the share of its cost that is fixed and so paid whether it sells or not, and the days it was not online. The asset card answers whether an asset has been worth it; this answers whether it is earning now, and what holds it back. The arithmetic is checked against the server rather than against itself: the smoke sums the thirty daily rows and asserts the result is the asset's own book_profit_cents, which the engine computes independently. No Python changed, so the gate was the two Godot suites and the parity check rather than the 59-minute suite. Found on the way and recorded as backlog 142: the smoke prints a triangulation error twenty-one times from area_chart.gd and still reports OK.

[ read development log ]

What it costs to run, and what it costs to build

Loop 139 gave the server a statement that keeps operating cost and capital apart; the panel reading it had not been told. Cash runway divided liquid assets by a total that included asset purchases, so one equipment order read as a daily burn and the runway collapsed the moment the owner expanded. Cost per unit sold did the same. Debt coverage and margin per unit did something else again - they rebuilt an operating figure in the client, as revenue less inputs, operating and variable costs, which leaves out the wages the server counts, so panel and server disagreed about the same company. All four now read the statement. The two hover definitions promising 'every expense of the last 30 days' were corrected in both languages rather than left contradicting the number beside them, and one new line under the heading says what it cost to run the business, what was spent buying assets, and the operating profit. The layout is unchanged; that is the next slice.

[ read development log ]

The same screen said both

From one request, the owner's company reported a $165,373 profit over thirty days and, from the same numbers, revenue of $353,653 against expenses of $1,762,289 - a $1.4M loss. Both were correct under their own definition: a day's expenses already leave out what a project paid for its equipment, so profit is an operating figure, while the expense dictionary carried the capital. Underneath sat plain arithmetic: the engine books a project's equipment once under a capex kind and once in the day's capex scalar, and the dictionary summed the kinds then added the scalar, so one order of $579,964 came back as $1,159,929. A statement told once - revenue, operating expenses, operating profit, capital expenditure, what left the bank, tax, and the operating breakdown - is derived from the day's scalars rather than the per-kind dictionary, so it stays exact at thirty days and at ten years, where the breakdown no longer exists. Tax is a component, never an addition; there is no net cash change, because a row's cash is the day's opening figure and the window cannot say what it closed at.

[ read development log ]

A day on, a day off

The owner could not explain 29% of his hosting unsold and a labour coverage that never reached 100%. His data center had not sold a little less every day: it had sold everything one day and nothing the next, eight days out of thirty, in both regions at once, while the wage market sat at its floor with three times the labour anyone wanted. Two defects sat behind it. A bid was valued from the first asset in the company's list, whatever region it stood in, so a thin cloud margin in the north stopped a data center hiring in the south - that is fixed here, and a bid is now valued by the assets that actually buy in that market. The second, valuing output on yesterday's print instead of its five-day average, is what makes a whole sector stop and start every other day; the one-line cure measures well (services volatility 20.0% to 5.0% on seed 7) but fails a real economic property - with the cycle gone, adding a transmission link raises the southern price instead of lowering it, because a link's margin lives on the volatility being removed. An attribution run separated the two halves; the second becomes backlog 140 with the link economics as its subject.

[ read development log ]

The community is open

A Discord server is ready for launch. One static link goes on the public index: after the Persistent Worlds section, so a visitor who has just read who is leading now reads an invitation to join; and in the Development section, closing a promise made months ago that the site would point here when it existed. No new endpoint, no logic, no widget — just a button and a URL.

[ read development log ]

A stock among the flows

The owner read the board an hour after it shipped: net worth matters at least as much as the tax paid, and both should be visible and sortable on a phone as well as a desktop. Net worth becomes a third ordering, computed once on the server like the others so the page still reorders rather than ranks. It differs from the second in two ways that say what it is: nothing is filtered out, because a stock is something every company has; and it names no window, because a stock has none. It immediately disagreed with the tax rank — a bank sits 17th by tax and 3rd by net worth.

[ read development log ]

They cannot be ranked up, only shown

The owner read the window deployed hours earlier: static, no players, no filters. The first of those was not a display problem. The four human companies rank 25 to 44 while the page held eight rows, so no filter could ever find them — and the brief's plan to surface them with a growth ordering was refuted by the data: founded on days 3 to 5, nothing built in a year, two of them holding no assets, they are genuinely last on every number the engine keeps. They are made visible by being carried and counted, never by being lifted. The board now sends fifty rows plus every player whatever its rank, with segments, a second ordering that is also the engine's own, and a rank that is never renumbered.

[ read development log ]

A window onto a running world

The public site said World Economy was a persistent economic MMO and showed four numbers about a world card. It now shows who is leading that world and what its own numbers say is happening: a leaderboard that is the game's own ranking, and five signals that each name the window they were measured over. Behind them one hand-written public projection, cached so a burst of visitors costs the world one walk rather than fifty.

[ read development log ]

The scale comes from the screen

The bar band under the main chart drew one bar per day whatever the window — 1.2 px a bar at a year on a desktop, 0.9 on a phone, a grey picket with no gaps — and its scale was its own maximum rather than the axis beside it, with nothing on screen saying so. A chart's density now comes from the width it was given: four pure functions decide how many bars four pixels apart the frame can hold, what period one bar must cover, how the flow is summed into it, and how finely the stock line may be drawn beside it. Every aggregate names its period in English and in French, and the two thirty-day summaries say they are thirty-day summaries.

[ read development log ]

A day grows lighter instead of disappearing

The dashboard offered windows up to ten years and the server held one, so five buttons out of eight drew the same year under different labels. A day of history no longer disappears at a year: it grows lighter — the breakdowns dropped at ninety days, seven days folded to a row after two years — and ten years now cost less memory than one year used to.

[ read development log ]

The press has to reach the page

The owner could not scroll the web alpha with a finger, though a mouse wheel scrolled it perfectly. Godot's stock web shell leaves the browser nothing to scroll, so every scroll on a phone is the engine's, inside a ScrollContainer that only drags if the press reaches it — and everything in the client that reacted to a press also stopped it. Actions now fire on a release that did not travel, display-only surfaces let the press through, and a rebuild no longer undoes a flick. Not yet confirmed on a phone.

[ read development log ]

The year-zero balance sheet

Loop 129 shipped an hour earlier and production showed its fix was incomplete: Meridian reopened with the catalogue's $67.5M against $30.4bn of deposits and failed again thirty days later, turning a permanent failure into an annual cycle. A recapitalisation is now sized to the economy the lender reopens into — and both dashboards came back identical, because the rule is inert everywhere except the large old worlds it was written for.

[ read development log ]

A bank can fail, none for ever

The owner asked whether the banks were healthy and why Meridian failed so fast in every map. It was the only lender that could fail, it always did, and its failure destroyed the world's deposit facility for good. Solvency is now a rule for every private lender, and a failed one reopens a year later with fresh capital — measured against a control run, because the dashboard reference had gone stale four loops earlier.

[ read development log ]

A world remembers its speed

The fourth defect of loop 127, found by the deploy that fixed the first three: a clock speed set by the administrator did not survive a restart, so a world deliberately slowed to 0.04 came back at the process default. The speed now lives on the world's row, is written whenever it changes and at every snapshot, and beats the environment at startup — a pause included.

[ read development log ]

A deleted world stays deleted

Three defects found by using the thing: a world deleted from the Admin tab left its rows and snapshot and came back at the next restart; loop 126 cached the answer \u201cno birthday yet\u201d for ever, so a world created at runtime stayed ageless; and the speed field read a decimal comma as zero, which silently created a paused world.

[ read development log ]

How old is this world

The world cards on the public site were already live from GET /worlds; they now also say how long the world has run in real time, read from the database's own creation date rather than derived from the day count, and the speed becomes a sentence: a world year every forty minutes.

[ read development log ]

Reading while the world runs

The client stops rebuilding itself every six seconds. A render gate sits between the day-closed signal and the thirteen panels: a panel that is not on screen does not render — it is marked dirty and catches up once, with the latest state, when the player opens it — triggers inside ninety milliseconds become one pass, no rebuild runs while a pointer is held or a field is being typed into, and every scrollable surface is captured before a pass and put back after the layout settles, so the page no longer jumps to the top. Where a rebuild still happens it is a reconciliation: rows keyed by the identifiers the server already gives, a shape signature that rebuilds one row and a value signature that writes the new numbers into the controls that exist. Market charts append the closed day to the arrays they already draw, and the ten-day synchronisation stops re-downloading a hundred kilobytes of history the live feed had already delivered. Measured before and after with the same harness on the same world: on the tab a player is reading, panel renders per world day fall from fourteen to one, containers rebuilt from twenty-eight to zero-to-seven, nodes destroyed from about a thousand to nought-to-nineteen, render time from ~200 ms to 0.3–21 ms and the longest frame from ~150 ms to 38–64 ms; the ten-day synchronisation moves 94 requests instead of 117 and stops re-downloading a hundred kilobytes of market history. The viewport jump the brief reports could not be reproduced on the desktop client at 1400×900 — in either build — and the entry says so. Nothing under src/ changed.

[ read development log ]

The same economy on a smaller screen

The browser client stops being a 1280×720 cockpit clipped to a phone. One responsive system — three bands read from the window's width, a live rebuild when the browser crosses one, carrying the tab, the session, the company and each panel's research — and the shared components adapt once so thirteen panels inherit it: rows that wrap, a theme whose padding makes every control a touch target, one vertical scroll per tab with sideways scrolling confined to tables, tiles that shrink a value before clipping it, charts that read a tap as they read a hover. On a phone the header keeps the day, the cash and FR | EN and puts the world and the clock behind one control; thirteen tabs become one full-width control; the market matrix becomes market cards; the lender comparison and the receiver's lots become cards; the Receiver's filters go behind «Filters (N)» with the state intact; the confirmation is clamped to the window; every hover-only fact opens on a tap. Nothing under src/ changed, and the desktop cockpit is the layout it was.

[ read development log ]

The first business cycle

The tutorial stops being four lines and becomes the first complete business cycle: ten phases — found, financing, read the markets, acquire capacity, feed the asset, watch a day close, read the contracts desk, decide how you sell, read the consequences, you are operating — each satisfied by a field the server already sends (loans, assets, projects, operations, standing orders, contracts, policy), not by a click; the three inspections no DTO can show are recorded where they happen. A compact checklist on My Company carries the guidance, the trade-off and a door per phase, never names a market to buy, never spends the player's money, never walks backwards; skip, resume and progress persist per account and world through a tab change, a language switch and a restart. EN and FR.

[ read development log ]

One language at a time

The client speaks one language at a time: an FR | EN control in the header, the choice remembered (a Godot ConfigFile, IndexedDB-backed on the Web), a deterministic first language (--lang=, the preference, the site's ?lang=, the locale, English), an immediate switch that rebuilds the views and carries the tab, the session, the world, the company, the window and the Receiver's research across without touching the game; 389 keys for the literals the audit found in every panel and widget, the server's enums and error codes as sentences, one formatter for money (1 420 000 $ / 2,50 M$), percentages, days and the calendar in French; a pytest parity and missing-key check; the public site's Play now passes its language to the game.

[ read development log ]

The receiver as a search

The Receiver becomes an acquisition intelligence tool: the lot list is a server query (region, market, price, search, nineteen sort keys, bounded pages), a board with the pool's summary, a region ranking per market and each lot's 30-day market context; every percentage names its denominator; affordability and the purchase preview come from the purchase's own rule; a lot gone reads as a sentence; the partial-purchase floor and a parked lot show on the card and the door (backlog 52).

[ read development log ]

The lender market

D91: financing is a market. Five lenders in the catalogue, each a bank in the world with its own cash and profile (public, conservative commercial, growth, infrastructure, alternative); four products; every lender answers a request with an offer whose rate is explained and what bounded it, or a decline that names its rule and numbers; the Banks tab compares them, shows the debt, the credit profile and the capacity per lender; acceptance is one locked, idempotent step; refinancing; a failed bank is named as an economic event. NPCs borrow through the same market.

[ read development log ]

The front door

The public site becomes the front door of the free public web alpha: PLAY NOW to the browser client at /play/, the MMO economy (the same markets, not seeing each other), the world that doesn't wait, persistent worlds with a directory read from the server, the decision cycle, one developer in the open, the journal at /devlog/, the free alpha and Steam later, a FAQ; one web root in the deploy.

[ read development log ]

Dead markets

D90: a market with no seller still says what it wants. The summary and the Markets tab show the buyers waiting, the silent days and what they bid; a quote on a dead market is priced at the neighbours' price and says so; the entrants' rule reads the best bid where nothing trades, so an empty market is entered.

[ read development log ]

Standing orders per market

D89: a floor or cap is keyed by market with the product as default; the block is built from the company's own markets, each field beside its price, yesterday's outcome, the seven-day unsold share, the price's slide and a surplus hint; today's price one click away; the labels say the mechanic. The NPC input bid was already bounded by the output's margin.

[ read development log ]

The three doors

D88: the early game has a door. The minimum gas plant, data center and server fleet come within a founder's budget; the startup loan does not count against the leverage cap in the first year; the founding screen shows the three doors of the region (build, buy from the receiver, contract inputs) and a quote warns when nobody sells a local input there.

[ read development log ]

The unfair death

D87, from the botplay feedback: every bill draws on deposits before it becomes arrears, the arrears clock starts with its episode and is shown to the player, a company whose deposits cover its arrears never fails, a prepayment that would break the reserve asks first, the borrow button says the rate, equipment-only projects stall, quantities keep their decimals.

[ read development log ]

Navigating the tree

The tree becomes a map: drag to pan, wheel to zoom, fit; a click on a product isolates its whole chain, from the region's people to the buyers, with the market a button away; every card carries its reference, import and today's prices, every recipe its output and an ingredient list with units; boxes can be moved by hand.

[ read development log ]

The market tree

The Guide opens on the whole economy drawn from the catalogue: sources on the left (the public backstop, the region's people, the outside world), the products by input depth, the recipes as small nodes with the input per capacity unit, the buyers on the right; hover lights a chain and writes its sentence, a click opens the market. The contracts desk's product lists follow the summary.

[ read development log ]

Two things seen playing

The owner played on the public server: the Markets tab's product filter, built once before the summary arrived, showed four products; it follows the summary now. Net worth joins the leaderboard as a public board and column. Deployed with the world kept.

[ read development log ]

What keeps a company alive

The consolidation: a growth check in the suite (six years, three seeds), the six-year decline read to its rule (datacenters priced at a cash cost that ignored their loans, died in a mild glut and took the server fleets with them), the ask floor now carrying the debt service; the receiver's rules and the entry margin measured and kept as they were. No new product.

[ read development log ]

The world eats

The owner's reframe: keep the markets, drop the society. Food becomes a world commodity with the world's own demand curve and an import price; the population sells labour and nothing else; housing, migration and the price index leave the plan; chantier F closes at item 21.

[ read development log ]

The people eat

Food and fertiliser in the catalogue; farms whose output follows the year, silos that store it, a fertiliser plant, a drought that halves a region's harvest; the people eat a ration a day each through a demand curve per region; storage trades at the market's price and no entrant founds it.

[ read development log ]

The Admin tab asks once

Backlog 41: the Admin tab asks the admin routes only while it is on screen, and a refused token is forgotten on the first 403; on the public server a wrong token in one browser had been a storm of 403s and 429s.

[ read development log ]

One branch

The Internet deployment branch and the morning's hot-fix branch merged into main, the playtest server deployed from main with its world kept at day 2571, the branches and worktrees deleted: one branch, one checkout.

[ read development log ]

A world on the Internet

The first Internet-hosted deployment as code: an Azure VM from Bicep and cloud-init, one compose stack behind Caddy with automatic HTTPS routing the Godot Web client, the API and the live feed on one hostname, systemd bringing it back after a reboot, the world on a data disk with nightly dumps, a public-alpha guard (rate classes, bounds, idempotent commands), and GET /version. Validated locally end to end, then run on Azure by the owner the same evening: Canada East, green on the first try.

[ read development log ]

Bounded memory, compressed snapshot

The playtest server's first night: a 146 MB snapshot, 3 GB PostgreSQL backends, an engine that kept every day of every company for ever. The world now keeps a bounded history, the snapshot is gzip bytes written by a thread outside the tick (migration 0004), and every container has a memory limit. A 360-day world is bit-identical to before.

[ read development log ]

A public face

The first public identity and a static website at public/: a ring-and-market-line mark, an amber-on-slate design language with every token on :root, a homepage that says in ten seconds what the game is (hero, a world that reacts, what the player does, the chain, no scripted economy, real screenshots, built in the open), FR/EN from one markup, responsive and accessible, checked by a headless Edge render at 1440, 1024 and 390. Built on 2026-09-03 beside loops 76 and 77 on the branch `website`; merged into main on 2026-09-05 and numbered then.

[ read development log ]

The people at the gate

A population per region offering worker-days on a wage market that clears first every day; hiring as an input of every recipe; wages as their own line in the books; a region that hires more pays more.

[ read development log ]

The chat travels with the world

Chantier E closed: the chat lives in the world and its snapshot, so it survives a restart; a per-player mute kept by the server; the host hides a line or silences an account with the admin token.

[ read development log ]

A bad contract has a price

Four debts from playtests 2 to 5, each with its test: a contract exit priced at the remaining term's penalty, a founding floor of $500k, the working-capital reserve on a 180-day window with a move judged after the move, and loan prepayment with the lender's fee.

[ read development log ]

The shortage behind the import

The tier tuned against the dashboard: the import ask no longer counts as the market's offer, so entrants and the tightness check see the shortage it hides and reach steel, silicon, chips and equipment; an asset is valued at what was paid; the makers sized to the demand their chain derives.

[ read development log ]

Made of steel and chips

The materials tier: ore, silica and concrete from the ground; steel, silicon, chips and equipment from them; crews that consume steel and concrete; and every asset's capex bought as equipment on a market, day by day, with the outside world selling what nobody makes yet.

[ read development log ]

Hectares

Land becomes a stock per region that every asset takes and every project pays for, at a price that rises with what is already taken. No free land, no project; the NPCs build where there is room; the pages say the hectares.

[ read development log ]

Ten seeds, ten years

The balancing dashboard: a generator over ten seeds and ten years, two computed verdicts per chain, the means, every seed. Both generators are green by the rule; the procedural draw is harsher, and the first run found a bug that had moved southern lots north.

[ read development log ]

Drawn from the seed

A world can now be drawn from its seed: the regions, their demand and land, the companies, their sizes, cash, homes and names. Two seeds start differently, one seed starts the same way twice, and the baseline stays the bytes it was.

[ read development log ]

The catalogue is a file

Every product, spec, sector, role and name the engine knows moves into one data file; the engine, the policies, the entrants and the client read it. The world on seed 11 is byte-identical to the hash recorded before, and a new product is a recipe, not code.

[ read development log ]

No vote

Dev Loop 6 opens with a subtraction: the ballots, the lobbies and the coalitions leave the game. The player is a company; the public frame is scenery it reads and never votes.

[ read development log ]

Buttons that look like buttons

The fourth small iteration: a control theme for the whole client, an amber primary action per section, and segments for the window, the series and the price basis with the one in use filled. The break-even gauge also learned to fill from an older server.

[ read development log ]

Profitable, or not

The third small iteration: BUILD says the verdict first. A break-even gauge on the market's month, the project's break-even and the sheet's price marked, red and green, replaces the revenue strip; the quote carries the break-even prices, with and without the loan.

[ read development log ]

What eats the day

The second small iteration: BUILD's waterfall and bubbles give way to one strip (a day's revenue and what eats it) and a payback curve (cumulative margin against the cost to build, with and without the loan), the price sensitivity in the margin's hover.

[ read development log ]

Frames

The charts are hard to follow, the owner said, and asked for small iterations, the sections first. Every heading of a tab and what follows it is now a framed, foldable section with its title as a header; nothing inside changed.

[ read development log ]

Policy again

The owner's first minutes on the Dev Loop 5 build: the standing orders at the top of My Company read as the old Policy section misplaced. They go back to the Policy tab, above the public side; My Company keeps one autopilot line.

[ read development log ]

An hour to build

The playtest 5 script closes Dev Loop 5: one hour for one player who founds, borrows, builds, signs a contract and expands to a second region without the host touching the company, with a checklist of the twenty-five findings of the review and three timed readings. The phase's nine feature loops are done and pushed.

[ read development log ]

Other people

The World's companies as a sortable grid with a public company page a click away; the leaderboard with five boards, the viewer pinned and a rank curve over the year; and a chat over the live socket, a world channel and one per region, its latest line on the strip.

[ read development log ]

Eight markets, two economies

Markets becomes a matrix: every market on one row, unsold, pipeline, price change, contracted and your share each on its own scale, with filters and a mine toggle. Regions becomes a regional economy: what each region produces and consumes, its balance, the electricity its links carry, a GDP-like figure, taxes, and your share.

[ read development log ]

The click is on the thing

Contracts become a desk: offer cards that say what you would do and with whom, each with its own Accept; a price ladder for the market you are about to post on; a form with a live sentence; my contracts as cards with a delivery calendar, the money so far, the gain or loss against the spot, and a renew button.

[ read development log ]

The lenders' side of the table

BORROW and LOANS become FINANCING: the rating letter and its history, what each purpose would get today, a what-if after every offer, loan cards with their amortisation curve, payments by month, the debt service against the operating result. The Banks tab gets a card per lender, the lending rate and each bank's cash over the window with refusals and fire sales marked.

[ read development log ]

What flows through the plant

OPERATIONS becomes a production flow: inputs into the plant into sold and unsold, bullet rows, a day ribbon, the price obtained against the market, coverage per input with the limited days marked, utilisation per asset, the suppliers' record. PROJECTS becomes a construction site: crews needed against the region's, the pace and its price, the online day at that pace against the planned one.

[ read development log ]

Every asset keeps its books

The engine attributes each day's revenue and costs to every asset and keeps running books on it. EXPENSES gains per-unit tiles, a treemap by kind split by asset and a rolling stacked area; the asset cards say what each asset has earned since it was built, its return on cost, its payback, its days idle, and offer to expand or replace it.

[ read development log ]

At your prices

The cost sheet becomes a calculator: the price basis named, every price editable, a sold-share slider, a checkbox for this project's loan, the margin's breakdown under the mouse, and the day drawn as a waterfall or as bubbles. The receiver's lots become deals, with what they cost to keep written before the button.

[ read development log ]

Nobody spends for you

A player's policy no longer borrows, buys lots or re-orders fleets unless told to, and says what it does when it is; the rules move to My Company as standing orders with a dial, floors and caps beside the market, and a last-act line per switch; the public side becomes the Polity tab; the wind-down goes into a danger zone armed by typing the company's name.

[ read development log ]

Ten years on one line

The foundations of Bâtir: tooltips on a layer above everything, the day's deposit, debt and book value recorded at day close, a net worth tile, a cash chart that can show cash, liquidity or net worth over windows up to ten years with one point a week, and the date written once. Four of playtest 4's findings, the ones the rest stand on.

[ read development log ]

Thirty minutes at Ultra

The last loop of the phase: playtest 4 written as a half hour live, three hovers named aloud, two indicators read, the blocks, and the player's own overlap audit. Dev Loop 4's seven loops are built and pushed; the loops pause for the human.

[ read development log ]

The strip

A status strip on every tab with the company's cash and profit, the alert count and the latest news; a red banner and disabled buttons when the company is over; space, 1–7, F1–F12, W and D on the keyboard; dense mode; chart rows that wrap; the overlap audit at 1280 and 1920.

[ read development log ]

No section is just text

BUILD, EXPENSES, OPERATIONS, BORROW, PROJECTS, LOANS, CONTRACTS and WIND DOWN as blocks: tiles, a bar, gauges against the lenders' caps, progress bars, cards with a repayment or delivery bar, a standing wind-down estimate. Every table kept under a fold, one click away. The owner's rule: more dashboard, but keep the rich content.

[ read development log ]

How many days of cash

Six more indicators on My Company, each a ratio of numbers the server already sends and each with its formula under the mouse: runway, debt coverage, margin per unit, break-even price, the inputs' share, the price against the market's averages. Assets as cards with an age bar and their market's sparkline; a tile per market, a column per region.

[ read development log ]

Under the mouse

One tooltip for every widget: a bar gives its category, series, value and share; a slice its name and share; a tile its definition and formula; a sparkline the value under the mouse; a line its date, every series and the volume. Hovering a day on the cash line draws the cursor on the flows. Nothing new to read, everything readable where it is.

[ read development log ]

Thin lines, long windows

One-pixel lines with a faint fill, a game-date axis whose ticks never touch, spikes clipped to the 95th percentile with the outliers marked, revenue and expenses as lines, a 30/90/180/360-day window on My Company with a route for the long rows, and bars that show each market as a share of its own total so compute at 6,000 no longer hides construction at 4.

[ read development log ]

A day is a point

Ultra and Max on the clock, and a client that adds the closed day to what it holds instead of reloading fifteen routes: one point per market, the company's own detail, a summary, and the whole page only every ten days. The money tiles glide; a dot blinks on every day. The owner's first ask after the dashboard: faster ticks that do not stutter.

[ read development log ]

Counted once

The last loop of the phase: tabs in the order they are used, the Guide on the dashboard, a host view for the admin token, playtest 3 written as five timed readings, and the one mechanics fix the phase allowed: contract deliveries were credited to the buyer twice, and the phantom half was resold. Measured on three seeds; the loops pause for the human.

[ read development log ]

The rest of the tabs

Every market with its price band and volume, capacity against what is being built, unsold shares; the two regions side by side; the leaderboard's top ten and who owns each market; the treasury's years as stacked bars. The last tables that were only tables, with a chart beside them.

[ read development log ]

The day it happens

A News tab: what moves the markets, the day it happens, tagged with the market, the region and the direction it pushes; forecasts first; then the company's own alerts, an input at twice its usual price, unsold above a fifth, a short contract, a payment the cash does not cover. The rack that went ×6 in playtest 2 would have been red on day one.

[ read development log ]

Which side you are on

The offer form shows what your assets want and what you produce next to the quantity, a firm promise on a product NPCs never sign firm says so, and Post and Accept both spell out the deal in a sentence, with a confirmation beyond your need or your free capacity. Playtest 2's 10,000-a-day contract cannot happen by accident again.

[ read development log ]

At a glance

My Company as an operations dashboard: seven tiles with the change against the previous month, the cash line, an expenses donut, revenue over expenses per day, sold over unsold per market, inputs wanted against obtained. The cost sheet now says what the loan would cost and what the region is already building.

[ read development log ]

Six ways to draw a number

The chart kit for the operations dashboard: a multi-series line with a band and a hover value, grouped and stacked bars, a donut, a sparkline, a KPI tile with a 30-day delta. Pure drawing controls that know nothing about the economy, a demo tab with synthetic data, and a smoke pass that draws them all.

[ read development log ]

The cheap region

Playtest 2: the owner and the assistant on one company for 640 world days. The tools of the phase all got used, the phase's question was answered by the player alone, and the economy taught its best lesson without meaning to: a cheap region does not stay cheap once everyone sees it. Verdict: sound mechanics, a slow and thin experience. Dev Loop 3 is the display.

[ read development log ]

The evening, rehearsed

Playtest 2 written around the phase's question, four acts for one player with the tools the phase added, rehearsed end to end by a test. A fixed-width font for the tables, and money that formats the same above and below ten thousand dollars. The loops pause for the human.

[ read development log ]

The public record

A leaderboard on public data only: taxes paid over the year, the biggest market share, contract reliability, capacity added. Players marked, your company pointed out. The answer to the question am I doing well, which playtest 1 had no page for.

[ read development log ]

A way out

Sell an asset to the receiver at half its depreciated cost, move it to the other region for a tenth and a month, or wind the company down and take what is left back to the stake. Each with its numbers before the question; a mistake now has a price instead of a bankruptcy.

[ read development log ]

The stake

One pool of capital per account and world: the first founding is a grant, every founding spends $1.5M of it, a liquidation will refill it. A company picker on the sign-in row, and every player action logged as a private event for the playtest.

[ read development log ]

A pause button

Five named speeds and a clock that a world may open to its players: pause, read, decide, resume. One clock per world, the server's, with every change a public event naming who set it.

[ read development log ]

The rules in plain words

A Guide tab with sixteen topics in French and English, and a four-step tutorial on My Company ticked from the company's own state. The answers the developer typed during playtest 1, rewritten for someone who is not the developer.

[ read development log ]

Where the money went

Expenses by kind, operations by market, and a cost sheet before buying. The explanation the developer gave over chat in playtest 1 is now on My Company, computed by the server and shown by the client.

[ read development log ]

Errors you can read

The first loop of Dev Loop 2: errors as sentences with the money in them, in English and French; a line of help under each tab; the day and the clock's speed in words; the sector shown as the label it is. What stood between playtest 1's player and the game in its first ten minutes.

[ read development log ]

One player, one evening

The first human at the game, with the developer answering over chat. The economy held up; everything between the simulation and the person did not: no tutorial, no guide, costs and operations invisible, a stuck founder with no way out, and free money at founding. Thirteen findings; Dev Loop 2 is their answer.

[ read development log ]

A candidate

The deliverable named and tagged: v0.1.0 is the playable prototype, released after the two-player evening. A five-minute README, a one-command release check, a checklist with the playtest log, and the candidate tag. The autonomous loops converge here.

[ read development log ]

The whip count

A lobby counts the NPC stances before it pays to open a ballot, and a player can read the same projection. Fewer ballots open and every one passes; bad debts and shortfalls fall by half and two fifths. Public investment gets a yearly cap.

[ read development log ]

The same answer, faster

Bisect curves in the clearing, contract totals once a day, a cached tax base: a six-year world a third faster with identical numbers. The first version of the contract cache counted global contracts twice and changed a world by a third of its compute; the old-versus-new check caught it.

[ read development log ]

A price with a slope

Every project bid double the works tariff on its first day, so a crew shortage cleared at the ceiling for as long as it lasted. A bid that climbs with a project's waiting days gives the price a slope: days at the ceiling fall by four fifths and the busts a doubled project cost synchronised are smaller.

[ read development log ]

What went wrong stays on screen

Sortable summary and company tables, and a red list of the last five things that went wrong for the player's company, kept on screen. The screenshot found the next loop: construction in the north doubling for weeks at its bid ceiling.

[ read development log ]

An evening for two

The M7 gate written down as a ninety-minute evening for two players, a one-command server for it, and a rehearsal that plays the whole script through the API. The rehearsal's first finding: a founder's money buys servers and nodes, not plants or halls.

[ read development log ]

A backstop that builds

Public providers can build where the tariff binds, as a policy a world may vote on. It rescues a world whose lobbies cut the tariff and crowds private plants out everywhere else; the first knob whose measured effect is a real trade-off, so it stays off and on the ballot.

[ read development log ]

Balancing the books

At each year close the revenue tax follows the treasury's deficit, a quarter of itself at most. The lobbies' $17M hole closes to $3M and the companies that voted a tariff cut pay for it the year after.

[ read development log ]

The lobby

NPCs propose ballots from their interest, with a fee, one a year, a year's rest per knob and a floor at the backstop's cost. Unconstrained they voted the tariff to a fifth of itself; constrained, about two ballots pass per world. On seed 2 one tariff cut costs twenty points of growth.

[ read development log ]

Acting on the forecast

NPCs cover more of their inputs and keep capacity online ahead of a likely shortage. Paying a premium for that cover was measured and rejected: at the usual price, shortfall days fall by more than half and bad debts by a third.

[ read development log ]

Likely around day N

Random events are announced two weeks ahead at seventy percent, and three in ten never come. A shock a player can prepare for, or gamble against; NPCs still ignore the forecast.

[ read development log ]

A contested vote

NPCs vote their interest on every open ballot: sellers want their tariff up, buyers down, everyone wants less tax, borrowers want the public bank cheaper. Policy becomes a coalition problem; the first test to fail did so because an NPC lobby had voted.

[ read development log ]

The franchise

Players propose and vote on public policy through their companies; a vote weighs the tax the company paid over the last year, a ballot passes by weight and quorum and applies itself with a public event. Those who fund the treasury steer it; NPCs abstain for now.

[ read development log ]

Paying for it

The treasury gets income: a levy on private revenue. Collected monthly it costs 8% of output at any rate; collected daily as revenue settles, 1.5% balances the budget and improves output, failures and shortfalls. Lumps break thin balance sheets; the rate is policy, the timing is not.

[ read development log ]

Running short

Weather that cuts supply: an outage derates a region's gas fleet, a heat wave derates its turbines, and for the first time a region's price leaves the public tariff behind. The battery, on its third measurement, survives storms with a five-day store, barely; storage pays on intraday spreads and this model has one price a day.

[ read development log ]

What the state costs

The subsidy becomes a budget: yearly outlays by kind closed at each year start with a public event, a public route, and a block on the Policy tab beside the policy that causes them. A tariff now has a visible price.

[ read development log ]

Running a world

Every admin route behind one client tab: worlds, clock, shocks with a region, the public policy as an editor by unit, physics knobs by name. A world can be run without curl, and the panel is the first draft of the government screen.

[ read development log ]

Rules you can read

Sixteen knobs are declared policy rather than physics: readable by every player, set by admins with a public event per change. Writing the first test found that the public utility had been holding a copy of its tariff since day zero.

[ read development log ]

Weather has an address

Heat waves and building booms can hit one region, from the CLI, the admin API or the random draw, and the World tab says where. The battery, given weather, still loses money: the north has slack and a capped price, so there is no spike to sell into.

[ read development log ]

Knobs by name

Every scalar knob of a running world can be read and set through the admin API, and a new world can start tuned; the CLI and the API share one typed coercion. Who can change the economy, and when, is now a server feature.

[ read development log ]

Picking a world

The client lists the server's worlds and switches between them from the title row; banking events get their own red block. The walkthrough, run for the first time in seven loops, caught a 500 on a player's first loan that no unit test had, and joins the baseline.

[ read development log ]

What a battery is for

The first inventory: a battery spec whose bought power waits in a store the engine carries across days. Staged, it fills at $42 and sells at $480; seeded, it goes bankrupt on every seed because a steady price is no opportunity. The spec stays for players and for worlds with weather.

[ read development log ]

Many worlds, one server

A registry of world services, requests scoped by name through a middleware and context-variable proxies, so not one route changed. Worlds are listed, created and removed by admins, stepped apart, invisible to each other, and named on the live feed and in the client.

[ read development log ]

A run on the bank

A bank_run event and the fire sales a bank makes to pay for it, plus a banking_crisis preset. Measured at three capital levels: the crisis doubles defaults and costs the bank millions, and fails nobody, because a 25% reserve caps a run's loss at 15% of deposits. Runs kill leveraged banks; this one is not leveraged.

[ read development log ]

A bank that can fail

The commercial bank gets a liability side: deposits swept from every company's excess cash, interest, a reserve it never lends, equity that losses eat, and failure with a depositor haircut. The first measurement without a reserve produced a run by construction; with it, defaults fall a fifth. No bank has failed yet.

[ read development log ]

A record you can read

The delivery record NPC buyers price promises with becomes public: on every sell offer, on the company view next to the rating, and on the client's contracts board. Everything a policy reads should be a thing a player can read.

[ read development log ]

One process, many worlds

The last process-global state in the simulation, the id counters, moves onto the world. Two worlds share a process without colliding and a restored world continues where it stopped. No economic change; old snapshots load unchanged.

[ read development log ]

What a lender reads

Lenders get a memory: the rate carries half the bank's own loss rate in the borrower's sector. A per-sector exposure cap was measured and rejected because it rations the sector that borrows most and never defaults. The northern-plant losses remain: a boom is an information problem the bank sees no earlier than the builders.

[ read development log ]

The subsidy is the bank

The public subsidy taken apart: four fifths of it is the public development bank, not idle plants. Parking idle public capacity was built, measured and rejected, because a backstop's value is exactly the capacity that sits idle. The bank now remits its excess so the figure is net, and on seed 8 it lost on all fourteen loans that financed the northern build.

[ read development log ]

Where the price is

Every investment decision on a local product read the mean of two regional prices, which hid a six-year public monopoly at the tariff and made a link's spread invisible. Now capital is judged where it would be built, only where demand is captive, and a price pinned at the tariff keeps the herd brake on. The market becomes one people enter: more served, more failures, and a subsidy line that names the next loop.

[ read development log ]

Power both ways

Grid links store one day of energy and sell today what they bought yesterday, so market order stops mattering and a link standing in the north draws from the south. Neutral on five seeds. The census that followed found nobody builds links, even across a $53 gap that lasts a year.

[ read development log ]

A promise with a price

Contracts now say how reliable they are: firm promises are served first and cost half the price to break, best-effort ones yield and cost a tenth. Guarantee levels alone made cheap promises a lock-in tool, so NPC buyers price each seller's public delivery record. Firm shortfalls are zero on five seeds; bad debts fall 37%. A big hall can finally be parked in parts.

[ read development log ]

What a seller cannot promise

Two more ideas for unreliable contracts, both measured on five seeds and both rejected: silencing sellers who shorted moves the promises to the next rationed seller, and a risk premium pushes buyers back to the spot market where the bad debts are. The cause is input rationing, not the seller. Meanwhile a third region turned out to be one config row.

[ read development log ]

On the map

A Regions tab draws the two regions as cards with their local prices, capacity and pipeline and an arrow for the grid link; a Banks tab shows each lender's cash, capital, rate and refusals. The commercial bank now raises its rate as its cash runs out, so a credit crunch is priced before it is refused.

[ read development log ]

The bank has a balance

Lenders are companies now: principal leaves a bank's cash, instalments and recoveries come back, and a default is its loss. The commercial bank lends itself dry within two years and starts refusing; defaults fall by two thirds because they finally cost something. Along the way, the reason private generation had quietly stopped expanding turned out to be that the public utility's spare capacity looked like a glut to everyone.

[ read development log ]

The wrong side of the border

Bad debts had doubled since regions arrived: newcomers were founded at random, built on cheap southern land, glutted a small market and then could not get credit for the power they needed to sell anything. Entrants now choose their region by margin and NPCs read the target region's pipeline, with a severe-shortage override after the first version froze a small region at $500 hosting. Measured on five seeds; a credit grace for young companies was tried and rejected.

[ read development log ]

A wire across the border

A grid link is an asset that stands in one region and buys its electricity in the other, losing 8% on the way. It idles while the two prices touch and moves power the day they separate; a big link narrows a regional shortage. Getting it right meant teaching the engine that an asset can buy and sell in different markets, and catching a unit error that let it sell twenty-four times what it bought.

[ read development log ]

Where

Two regions: electricity, construction and hosting now clear per place, with regional land costs, city demand and public providers, while compute and services stay global. Every asset stands somewhere, NPCs choose where to build by margin, players pick a region when founding and building, and the markets tab shows one chart per regional market. Prices decouple across the border; there is no transport yet.

[ read development log ]

Bigger is not free

Companies above $60M of assets now pay rising management overhead, priced into how NPCs ask and invest; over six years the largest company's share of compute capacity falls from 49% to 39% and of hosting from 56% to 41%, at the cost of 6% less served. Every company also gets a coarse public credit rating, refreshed monthly, so a rival's distress is visible a month late.

[ read development log ]

Operations and polish

An admin token now lets an operator schedule events, change the clock speed and toggle random weather on a running server; players get a plan-share knob to decide how much of their capacity to procure for, confirmations before any spend above $5M, a chart of their own cash, and the active events where they look.

[ read development log ]

Weather

Heat waves, recessions, hardware shortages, construction booms, technology breakthroughs and public subsidies as events that start, last and revert exactly, scheduled by hand, bundled into named scenarios, or drawn from the seed. A recession shows up in price before volume, a hardware shortage lands in the build quote at once, and a stormy decade ends within 3% of a calm one.

[ read development log ]

Promises on real capacity

Three fixes for sellers who sign contracts they cannot keep, each measured alone on five seeds: offering only capacity that outlives the term (kept, shortfalls down a third), credit earned by actual sales (kept), and letting contracted sellers outbid the spot market for inputs (rejected: it spreads one seller's distress to the whole sector).

[ read development log ]

Private books, live world

Company financials are now owner-only with a public capacity view for everyone, NPCs included, and the server pushes one WebSocket message per closed day with prices and the account's own events. The client refreshes on push, shows its company's events as they happen, and the World tab lists capacity, not cash. M9 is complete for the prototype.

[ read development log ]

A sector is a spec

The engine's four hand-written market steps become one rule: products clear in an order derived from the specs, buyers procure inputs for a sales forecast, sellers offer what their inputs allow, and settlement runs downstream-first. Proof: cloud services, a sector that buys compute and sells to the world, added as one spec, one product, one demand curve and two companies, with no engine code. A services shock now travels three links.

[ read development log ]

Tuning with a scale, not a thumb

A metrics module and a compare command that runs baseline against variant across seeds, then six experiments on the compute price sawtooth, take-or-pay sizing, the leverage cap and the demand ladder. One change kept (contract budgets: bad debts down 60%), five rejected with numbers, and the sawtooth traced to a synchronised markup cycle that no single knob removes.

[ read development log ]

Accounts: several people, one world

Register, sign in, bearer sessions persisted with the world, ownership by a provider-keyed account, a seam for Steam, and the trusted header switched off by default. Alice and Bob found companies in the same economy and cannot touch each other's; a persisted account and its session survive a server restart.

[ read development log ]

The client: seeing the economy

Seven loops of economy finally have screens: four price charts and a market intelligence table, a company dashboard with build quotes, credit assessment, assets, loans and contracts, the receiver's listings, the offers board, a policy editor and the world feed. A headless walkthrough drives the client code through a whole session against a live backend, and the charts immediately exposed a daily sawtooth in the compute price.

[ read development log ]

Contracts: promises with reserved capacity

Companies can now post offers and sign fixed-price supply contracts that reserve real capacity, delivered before the spot market with penalties for shortfalls, resale of surplus and cancellation when a party fails. NPCs hedge and players contract by hand; contracts cut electricity spot volatility by more than half through a supply shock. Three rounds of fixes taught the NPCs never to park capacity they have promised.

[ read development log ]

The world survives a restart

Exact world snapshots to PostgreSQL (random state and all), daily market and event rows, restore on start, snapshot on shutdown, and a background clock. A restored world continues identically to one that never stopped, and a live server killed at day 31 came back at day 32 with the player's company, owner, cash and loan intact.

[ read development log ]

Credit: the lever, and the cycle it brings

Companies can borrow: public startup and project loans, commercial working capital, instalments that feed the arrears machinery, coverage-based underwriting, one-time restructuring, default. Credit lifts six-year compute served by 45% and cuts the price by a third, and brings a boom-bust cycle with 9–14% of lending defaulting. Getting there meant fixing five things the first credit boom broke, from halls that could not buy power against revenue they had already earned to a grace clock that reset every month.

[ read development log ]

A player enters

The economy gets a door. A human can found a company, build capacity, park it, buy assets out of receivership and set the rules it follows while they are away, all through validated server actions that are the very functions NPCs call. A player company driven over HTTP ordered 300 servers, was refused by a stranger's account, and turned a profit forty days later.

[ read development log ]

Operators differ, and five things that broke when they did

Assets now have an efficiency, a vintage and a lifetime: new capacity is cheaper to run, old capacity retires and must be replaced, and high-cost operators are the ones that fail. Making costs differ exposed five systemic flaws in turn, from a receiver that took half the sector offline to a public administrator that went broke and deadlocked a world. All fixed; three seeds run six years with cycles, entry, failure and liquidation, and the case for loans is now written in the numbers.

[ read development log ]

Failure creates opportunity

Bankrupt companies' assets now go to a public receiver and are sold to solvent rivals or newcomers at a falling discount instead of vanishing; NPCs can mothball idle capacity at a quarter of the upkeep. In seed 1 a failed builder's crews were bought by a founder and an entrant for a third of build cost, and the hosting boom/bust cycle lost about half its amplitude.

[ read development log ]

An economy that runs without anyone playing it

From an empty repository to a four-sector headless economy: energy, construction, data centers and compute trade through daily call auctions against real capacity and costs. Over six simulated years compute supply grows 2.3×, hosting swings between glut and scarcity, private power drives electricity below the public tariff, builders go bankrupt and are replaced by entrants. Plus the API, database, Godot client skeleton, tooling, docs and this journal.

[ read development log ]