Repository navigation
play: typed code shows at once in the spec editor, and a phone keeps it in view - #1359
Merged
Merged
Conversation
…it in view The editor is a transparent textarea over a coloured <pre>, and the <pre> was redrawn only after the debounced compile, so while a reader kept typing nothing new appeared: 300-1792 ms per key measured on the live player, up to 2047 ms with the CPU throttled 6x. The <pre> is now repainted on every input event -- lines the last compile saw keep its colours, changed lines are drawn plain -- and only the compile waits. Measured after: 0-2 ms per key. On a touch screen the editor's text is 16 px (EDITOR_TOUCH_FONT_PX in specs/x/player.t27, tested against IOS_FOCUS_ZOOM_BELOW_PX) so iOS Safari does not zoom into the focused field. In portrait the page scrolls instead of body, so the tabs and the compile verdict stick; line numbers stick when a long line scrolls the pane; the textarea gets wrap="off" and autocorrect="off". Closes #1357 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
X Brain Health CheckScore: 100.0/100 X Brain is above merge threshold |
Contributor
🧪 Brain Stress Test ResultsTests: 261/261 passed, 0 leaked |
gHashTag
added a commit
that referenced
this pull request
Oct 4, 2026
…issue it closes Closes #1365 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot
added a commit
that referenced
this pull request
Oct 4, 2026
play: typed code shows at once in the spec editor, and a phone keeps it in view (#1359) The editor is a transparent textarea over a coloured <pre>, and the <pre> was redrawn only after the debounced compile, so while a reader kept typing nothing new appeared: 300-1792 ms per key measured on the live player, up to 2047 ms with the CPU throttled 6x. The <pre> is now repainted on every input event -- lines the last compile saw keep its colours, changed lines are drawn plain -- and only the compile waits. Measured after: 0-2 ms per key. On a touch screen the editor's text is 16 px (EDITOR_TOUCH_FONT_PX in specs/x/player.t27, tested against IOS_FOCUS_ZOOM_BELOW_PX) so iOS Safari does not zoom into the focused field. In portrait the page scrolls instead of body, so the tabs and the compile verdict stick; line numbers stick when a long line scrolls the pane; the textarea gets wrap="off" and autocorrect="off". Closes #1357 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag
added a commit
that referenced
this pull request
Oct 4, 2026
… a post (#1366) * play: a terminal for the seven t27 backends, one share page each, and a post The X player's spec editor gains a terminal. Every word it prints, every command it knows and every backend fact lives in specs/x/player.t27; public/play/shell.js only interprets those constants. - 12 commands; `t27c gen <backend>` for zig, c, rust, verilog, verilog-hir, js, ts, with the `gen-<backend>` spelling as an alias. - `run` executes only the JS module in the browser (RUNS_IN_BROWSER); the other six print the native command to run instead of pretending. - One share page per backend under play/hello-world/<backend>/ with its own card, generated by scripts/play-from-spec.mjs from the spec. - .gitignore: `zig/` was ignored repo-wide, which silently dropped the zig page; negated for public/play/*/zig/. - Recording t27.ai/term/play-terminal-gates/ (check:play and test:play-spec, 21 pass, 0 fail) and the bilingual post a-terminal-for-seven-backends-in-an-x-post. Gates: check:play (spec tests 14, asserts 43, all hold), test:play-spec (21 pass, 0 fail), typecheck ratchet at baseline. Closes #1365 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * blog: the terminal post names its own PR, trinity#1366 Closes #1365 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * blog: the terminal post's receipts say #1359 merged and #1365 is the issue it closes Closes #1365 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot
added a commit
that referenced
this pull request
Oct 4, 2026
play: a terminal for the seven t27 backends, one share page each, and a post (#1366) * play: a terminal for the seven t27 backends, one share page each, and a post The X player's spec editor gains a terminal. Every word it prints, every command it knows and every backend fact lives in specs/x/player.t27; public/play/shell.js only interprets those constants. - 12 commands; `t27c gen <backend>` for zig, c, rust, verilog, verilog-hir, js, ts, with the `gen-<backend>` spelling as an alias. - `run` executes only the JS module in the browser (RUNS_IN_BROWSER); the other six print the native command to run instead of pretending. - One share page per backend under play/hello-world/<backend>/ with its own card, generated by scripts/play-from-spec.mjs from the spec. - .gitignore: `zig/` was ignored repo-wide, which silently dropped the zig page; negated for public/play/*/zig/. - Recording t27.ai/term/play-terminal-gates/ (check:play and test:play-spec, 21 pass, 0 fail) and the bilingual post a-terminal-for-seven-backends-in-an-x-post. Gates: check:play (spec tests 14, asserts 43, all hold), test:play-spec (21 pass, 0 fail), typecheck ratchet at baseline. Closes #1365 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * blog: the terminal post names its own PR, trinity#1366 Closes #1365 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * blog: the terminal post's receipts say #1359 merged and #1365 is the issue it closes Closes #1365 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1357
What was wrong
The spec editor in the X player (
/play/<id>/,public/play/embed.html+embed.js) is a transparent<textarea>over a coloured<pre id="hl">. The<pre>is the only thing a reader sees, and it was redrawn only insidedraw(), afterRECOMPILE_DEBOUNCE_MSof silence plus a full compile. Each keystroke restarted the timer, so on a phone nothing typed appeared until the typist stopped.Measured with headless BrowserOS (Chromium) over CDP, phone emulation 390x844, 14 keys typed 120 ms apart at the end of line 15 of hello_world.t27. Each number is the ms until a key first shows in
#hl:cb612ea994070,1670,1548,1427,1306,1183,1059,933,804,678,1792,554,427,300cb612ea994070,1790,486,1535,621,757,1022,1665,1402,1150,1922,2047,891,12747c9449f8a6610,0,0,0,0,0,0,0,0,0,0,0,0,17c9449f8a6610,0,2,0,0,0,2,0,0,2,0,0,2,2What changed
embed.js:#hlis repainted on everyinputevent. Lines the last compile saw keep its colours (a head/tail line diff against what was painted), changed lines are drawn as plain escaped text, and only the compile is debounced. The textarea's ownscrollLeft/scrollTopare pinned to 0, because the pane scrolls, not the field.specs/x/player.t27:IOS_FOCUS_ZOOM_BELOW_PX = 16andEDITOR_TOUCH_FONT_PX = 16, with the testfocusing_the_editor_on_a_phone_does_not_zoom.play-from-spec.mjsrequires both in its schema. The player readsEDITOR_TOUCH_FONT_PXfrom the compiled spec into--ed-touch-font, used under@media (pointer:coarse). The comment onRECOMPILE_DEBOUNCE_MSnow says what it delays.embed.html:htmlscrolls andbodyno longer does (a scrolling body is its own scroll container, and nothing inside it can stick). The header (tabs) and footer (compile verdict) areposition:sticky, andscroll-paddingkeeps the caret's line out from under them.position:sticky; left:0, withbox-sizing:border-boxon the::before(*does not match pseudo-elements; without it every code glyph moved 1em right of the caret).wrap="off"andautocorrect="off".-webkit-text-size-adjust:100%.public/play/player.t27andpublic/play/hello-world/index.html(player build7c9449f8a661).The desktop and X-card layout at 1200x675 is unchanged: compared side by side with the live screenshot, and the glyph-to-caret offset is 0-0.08 px, the same as live.
{ "version": 1, "head_sha": "34e36eca4aad32c0833d63e4b16066c77ce17e83", "summary": "Typed code in the X player's spec editor now shows on the next frame instead of after the debounced compile, and on a phone the editor no longer zooms, keeps its tabs and compile verdict in view, and keeps its line numbers.", "changes": [ "embed.js repaints the coloured layer on every input event; lines unchanged since the last compile keep their colours and changed lines are drawn plain until the debounced compile recolours them.", "specs/x/player.t27 gains IOS_FOCUS_ZOOM_BELOW_PX and EDITOR_TOUCH_FONT_PX with a test that the touch font is never below the zoom threshold; the player reads the font size from the compiled spec.", "embed.html makes the header and footer sticky in portrait by letting html scroll instead of body, adds scroll-padding for the caret, sticky line numbers, wrap=off and autocorrect=off on the textarea.", "The generated public/play/player.t27 and hello-world/index.html are rewritten by play-from-spec.mjs; player build 7c9449f8a661." ], "tests": [ { "command": "node gap.mjs \"$U\" with U = https://t27.ai/play/embed.html?spec=specs%2Fdemos%2Fhello_world.t27&v=cb612ea99407 (live) and the same query on a local server of this branch (390x844 mobile emulation, 14 keys 120 ms apart)", "result": "Live build: 0 to 1792 ms per key before a typed key is visible; this branch: 0 to 1 ms per key.", "status": "passed", "evidence": "invisibleMsPerKey live [0,1670,1548,1427,1306,1183,1059,933,804,678,1792,554,427,300], branch [0,0,0,0,0,0,0,0,0,0,0,0,0,1]" }, { "command": "CPU=6 node gap.mjs \"$U\" for the same two URLs", "result": "With the CPU throttled six times, live reaches 2047 ms per key and this branch stays at 0 to 2 ms.", "status": "passed", "evidence": "invisibleMsPerKey live [0,1790,486,1535,621,757,1022,1665,1402,1150,1922,2047,891,1274], branch [0,0,2,0,0,0,2,0,0,2,0,0,2,2]" }, { "command": "node align.mjs <url> 1200 675 0 and node align.mjs <url> 390 844 1", "result": "Coloured glyphs sit on the textarea's text origin within 0.18 px on mobile and 0.08 px on desktop, the same as live.", "status": "passed", "evidence": "dx 0 to 0.08 px at 1200x675 and at most 0.18 px at 390x844, identical to the live player's offsets." }, { "command": "npm run check:play", "result": "The generated player files are up to date and every test block in specs/x/player.t27 holds.", "status": "passed", "evidence": "player build 7c9449f8a661; 1 play(s): hello-world; spec tests 9, asserts 23, all hold" }, { "command": "npm run test:play-spec", "result": "All twelve generator and schema tests for the player spec pass on this branch.", "status": "passed", "evidence": "# pass 12, # fail 0" }, { "command": "iOS Simulator, Safari, http://127.0.0.1:8766/play/hello-world/", "result": "Not run: the simulator hung on openurl, screenshot and Safari launch, so the iOS-specific changes are not device-verified.", "status": "not_run", "evidence": "simctl openurl and io screenshot did not return; the simulator was shut down without a result." } ], "limitations": [ "The 16 px touch font, wrap=off, autocorrect=off and text-size-adjust are iOS fixes taken from WebKit's documented behaviour and were not checked on an iPhone or in the X app's in-app browser.", "All timings are from Chromium with mobile emulation; real phone keyboards and IME composition were not exercised.", "Between keystrokes and the compile, changed lines are plain text; they take their colours about 250 ms after the typist pauses.", "X's player-card rules ask that the player not collect data entry; an editable editor inside the card is a policy question for the owner, not changed here." ], "tags": ["t27", "XPlayerCard", "MobileWeb", "Editor"], "blog": { "title": "Why typing in the X player's spec editor showed nothing on a phone", "summary": "The editor is a transparent textarea over a coloured layer, and the layer waited for a debounced compile. Repainting it on every keystroke took the gap from up to two seconds to under three milliseconds.", "outline": [ "The pattern: a transparent textarea for the caret and selection over a pre coloured from the compiler's own tokens, so the reader only ever sees the pre.", "The anomaly measured: 300 to 1792 ms per key before a typed character appeared, up to 2047 ms with the CPU throttled six times, because each keystroke restarted the compile timer.", "The fix: repaint the layer synchronously on input, keep the colours of lines the last compile saw, draw changed lines plain, and debounce only the compile.", "The phone details: a 16 px floor so iOS does not zoom the focused field, html as the scroller so the tabs and verdict can stick, and sticky line numbers with border-box sizing." ] } }🤖 Generated with Claude Code