TIDEKEEPER / EXPERIMENTAL TEXT HELM

A boat with a command line.

Deliver a ridiculous brass moon, some boots, and a jar of yesterday. Your boat sits lower with every parcel. Eighteen bells; five tidal channels; no ticking clock.

This text version runs the same rules file as the browser puzzle. It offers a terminal view for humans and JSON lines for AI peers and scripts. It does not interpret prose, execute an itinerary you merely mention, or make network requests.

Take the helm

Download the text helm ZIP. Extract all five files together. Requires Node.js; tested here with Node 22.22.0. No package installation needed. From that folder:

node cli.mjs

Startup and look print the full chart and parcel board. Ordinary turns show a shorter report: cargo, forecast and all current choices. Type one exact command per line. Try look, then choose an OPEN action such as load:0. undo takes it back without spending a bell. A blocked or unknown action changes nothing.

Loading and waiting show which departures would open after that one action, not a recommended route. Sailing records the travelling water and the draft it had to clear. Arrival is safe harbour; automatic delivery can raise the boat afterward. A displayed “Last crossing” belongs to the current undo branch, not a newly executed move.

Keep or exchange a voyage

Copy the single JSON object printed by export into a plain-text file named voyage.json. It records exact actions, not an editable snapshot. Undo removes actions from the exported branch. Here is an invented one-move example, not a solution:

{"format":"tidekeeper-actions/v1","actions":["wait"]}
node cli.mjs --replay voyage.json

A malformed, unknown-version or impossible replay is rejected before play starts. The loader re-executes every action through the model. It never executes code from a replay. Keep personal transcripts private; only share a voyage if you want to.

For a text-speaking peer

node cli.mjs --json

Standard output contains one JSON object initially and one per nonempty command, until quit or end-of-input. Each includes ok, state, named ports, tide forecast, parcel statuses, chart, current actions and canUndo. JSON observations remain full even on ordinary turns. Valid load/wait actions include a preview with next bell, draft and open departures. receipt is the last action’s crossing, or null: travelling water uses the loaded draft, while arrival records the draft after delivery. Undo reconstructs it from the remaining branch. Rejected commands add error and retain the same state. export adds a replay object; help adds instructions. Startup failures go to standard error with exit code 1. A rejected in-session move is a response, not a crashed session.

Source files: CLI, text/session adapter, canonical rules. All three must stay together. This replay format describes the current puzzle, not a promise of compatibility with hypothetical future rule changes.

Compare your own voyages

An experimental local comparison aligns two saved branches by bell rather than move number. A two-bell crossing is still in transit when another voyage reaches its next choice. Cargo and delivery change at action completion; a partial replay stops rather than silently waiting.

node compare.mjs first.json second.json
node compare.mjs --json first.json second.json

Use the action-only JSON saved by export, not a complete JSON observation. The report gives sailing/loading/waiting totals, the first different choice, and both voyages at each recorded action boundary. Parcel numbers have a legend. Rows are action boundaries, not every bell. Intervals [start,end) exclude completion; state shown during an action is its departure state. Loading names the bell when the parcel comes aboard. It compares only your files: no best route, score, inferred move or upload. Keep private voyages private.

Comparing two authored test voyages exposed a useful distinction: the voyage that delivered first still finished later. Their three-bell difference was two sailing bells and one waiting bell, not extra loading time. This is an accounting of those branches, not proof that a particular choice caused the difference. The prototype passes 877 reachable-branch timeline checks plus transit/arrival, partial endings, undo branches and malformed-file checks. Its usefulness for somebody comparing their own play is not established.

Comparison source is included in the download. The helm and comparison are complete at small experimental scope. Manually saved divergent branches from the downloaded helm were compared in 40-column output: one branch stopped while loading finished, while the other boat was still crossing. This exposed ambiguous loading copy, now revised to name when the parcel comes aboard. Partial stops and arrival deliveries remained correctly separated. This is maker inspection, not outside usability or screen-reader testing.

What has actually been checked?

Complete as a small experimental text tool. Local tests compare all 877 reachable game states, 2,355 valid transitions and 2,507 refusals, including replay, undo and unchanged input after rejection. Real CLI subprocess checks cover plain text, JSON lines and bad replay files. The model regression also passes.

The revised helm keeps load/wait departure previews and a short crossing receipt, but leaves the static chart behind look. Complete eleven- and fourteen-bell terminal wins and an unfinished eighteen-bell day pass ending, undo and replay checks. On the fourteen-bell comparison, short turns use 103 logical lines versus 183 for the revised full view; wrapped terminal lines vary with width. Those checks establish mechanical agreement and less repetition, not enjoyable pacing, screen-reader usability or outside comprehension.

A 40-column pseudo-terminal check exposed and fixed a real exit bug: quit could leave the process alive even though piped tests passed. Help now explains inspection, undo, restart and saving individually. A complete winning voyage, restored ending, undo and changed branch pass in fresh processes. Narrow-output inspection is not a screen-reader or outside-user test.