feat(editor): F4.6b the command line on a computer's desktop

A new oracle, TerminalWindowRun, types into Java's own command line
window: the window writes each line after its prompt, takes a blank
line, cls, reset and exit itself, keeps the lines for the arrow keys,
and keeps its text, history and working directory over a stop and a
start.

The room now holds a command line window per computer for everyone
(TerminalWindow), kept over stops; the protocol carries its lines and
the one way to read them (terminalScreen); the core goes on in the
working directory of the run before (continueIn). The desktop opens
programs in Java's frame, and the command line works with keyboard and
finger: grey on black, the prompt hidden while a command runs, history,
chips for the commands, Ctrl+C. The room's failure is now tested in the
browser.

Fixed: the room handed the engine the wall clock with fractions of a
millisecond, and a ping hung after its first timeout. The engine and
the room count whole milliseconds, as Java's clock does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 14:22:49 +00:00
co-authored by Claude Opus 5.5
parent dfd5ec03ce
commit ac48e969f4
23 changed files with 1255 additions and 47 deletions
+11
View File
@@ -141,6 +141,17 @@ describe('event queue and virtual clock', () => {
expect(engine.state.pendingEvents).toEqual([]);
});
it("counts whole milliseconds, as Java's clock does: a time's fraction waits for the next step", () => {
const engine = new NetworkRuntimeEngine(9);
engine.handle({ type: 'start', snapshot: EMPTY_TOPOLOGY_SNAPSHOT, seed: 9, initialTimeMilliseconds: 10.6 });
expect(engine.state.currentTimeMilliseconds).toBe(10);
engine.handle({ type: 'schedule', deadlineMilliseconds: 100, kind: marker('at-100') });
expect(firedKinds(engine.handle({ type: 'advance', toMilliseconds: 99.9 }))).toEqual([]);
expect(engine.state.currentTimeMilliseconds).toBe(99);
expect(firedKinds(engine.handle({ type: 'advance', toMilliseconds: 100.2 }))).toEqual([marker('at-100')]);
expect(engine.state.currentTimeMilliseconds).toBe(100);
});
it('rejects a past time without changing the clock', () => {
const engine = new NetworkRuntimeEngine(7);
engine.handle({ type: 'start', snapshot: EMPTY_TOPOLOGY_SNAPSHOT, seed: 7, initialTimeMilliseconds: 10 });