Repository navigation
Land rcode: 6 lanes - #210
Merged
Merged
Conversation
merge_block(type, base, mine, theirs) merges two changed versions of one block through the merger its type registered. With no merger the result is a conflict, which keeps today's conflict copy. merge_page uses it only when a changed block opted in, every block changed on both sides merges, and the other page fields changed on one side at most. The merged revision comes from the two revisions alone, so every device reaches the same bytes in any order (ADR 0089). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Before the page rule, sync tries the block merge for two concurrent live versions of page.json, from the newest .history snapshot both list as an ancestor. The process-wide mergers take part; merge_with takes explicit ones for tests. With no merger registered the merged manifest and its conflict copies are byte-identical to before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
conflict.text now also returns the blocks that differ between the two versions, with their types. A block type registers a compare and resolve view with registerConflictView, and the conflict dialog shows it for that type's blocks and the side-by-side text for the rest. Tables and code projects register theirs in later lanes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The follow-up that ADR 0049 named: one merger and one conflict view registry per block type, and when sync merges a page by block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The block merge on sync used an older shared snapshot as the base when the newest one had none. A merged revision never had a snapshot, so the next concurrent round merged against a stale base and brought undone changes back. Now only the newest shared revision is the base, and the merge publishes a snapshot of the merged revision. merge_page also keeps the conflict copy when a side is read-only or the two sides were read at different version keys (R-VER-5). The conflict dialog keeps the whole-page text under a disclosure when every changed block has its own view, so page-field differences stay visible. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The merge base is the first revision each side's ancestor list shares with the other, and both sides must agree. A device whose clock runs behind can no longer make an older shared save the base. - Sync uploads a .history snapshot of each page.json revision it sends that has none yet, so pages synced while open keep their base. - The conflict list hides a copy the current page already includes. - Split long merge functions into helpers and move the block merge into crates/sync/src/merge/blocks.rs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments and suggestions are marks in a text block's Markdown with their records in data.comments and data.suggestions (ADR 0086, spec 6.10). A review model rides on the text sync, so a mark and its record change in one undo step, and records of marks that left are dropped. Suggesting mode turns typing into insertion marks, deletions into deletion marks, and formatting commands into format changes that keep the old Markdown. Accept and reject settle one change, all changes, or one author's changes. The marks get styles for the All, Simple, and None markup views, and a screen reader hears "Insertion by Sam". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The comments pane lists a page's comments in reading order. It posts a comment's text, replies, resolves, reopens, deletes, and goes to the text. The Review tab gets New comment, Show comments, Previous and Next comment, Resolve, Delete, Track changes (Ctrl+Shift+E), the markup views, Accept and Reject (one, all, or by author), and Previous and Next change, all behind text.review. The person's display name for comments and changes is typed in the pane and kept on this device. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A paragraph whose text is the same but whose Markdown differs now says what changed, such as "Formatting changed: bold added to 'grow'". Paragraph formatting compares key by key, so an alignment change alone makes a changed paragraph. This prepares a later per-key paras merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Records, the rider that keeps a mark and its record in one undo step, suggesting mode, accept and reject, markup views, the comments pane, the local author name, and what is not tracked yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review's chunks load only after the page view, so they join the page group and count without the editor (about 10 KB at most). Its start-up registrations and strings add about 2.8 KB: origin/beta builds 542.1 KB and this branch 544.9 KB, so the start-up limit goes from 542 to 545. The aero tool chunk grows from 222.8 to 223.1 KB as shared chunks split differently, so its limit goes from 223 to 224. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/tools/registry.json gains the Review tab commands, and featureCommands.ts gives each one a sentence, so the feature list generator can place them. FEATURE-LIST.md is left to the docs owner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The feature list test fails when FEATURE-LIST.md is not what docs:features makes, so the generated page gains the 19 Review tab commands. Nothing else changed in it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Accept or reject removes a suggestion's paragraph breaks with it, so a deletion across paragraphs joins them and a rejected paste joins the split. - The comments pane refuses a comment over 64 KiB and a reply past 256 replies, as the core's reader does (spec 16). - Under forced colors comment marks drop their tint behind CanvasText. - The pane parses a block without an editor once per Markdown, and a caret move only updates the marked comment. - A refused record-only change puts back what the core holds and says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each change of a file starts one timer per layer (syntax 50 ms, checkers and engine checks 300 ms, code tools 500 ms, clang 800 ms, DESIGN 6.1). Every provider result carries the version it read, and a result for an older version is dropped, so a slow checker never paints marks on text that has moved (F18). A mapped change keeps shown marks on their text until the layers answer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The checker walks the Lezer tree and reports F401, F811, F821, F841, E711, E712, F632, W191, and E101, the codes Ruff documents, so people see familiar names. Scopes follow Python's name resolution: module code runs in order, function bodies later, and class bodies are hidden from their methods. The tests use Ruff's documented rule examples. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The checker reports no-undef, no-unused-vars, no-const-assign, no-unreachable, eqeqeq, no-cond-assign, and no-fallthrough with ESLint's default options, and reads /*global*/ comments as ESLint does. TypeScript type names count as uses but are never undefined. The tests use the examples in ESLint's rule documentation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
C and C++ get clang's undeclared-identifier and unused-variable over the Lezer tree. The checker stays quiet where a header could declare a name: calls, qualified names, class members, project headers, and using namespace other than std. Lua has no Lezer grammar in the app, so its checker reads tokens and gives luacheck's W113 and W211. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lezer error nodes become messages that name the unclosed bracket and its line, a Python header without its colon, the unexpected token, or an early end of file. The syntax and checker layers share one worker, and the page runs the same code when no worker is there. Runtime lanes register engine checks (SQLite, wasmoon, Python compile, clang), whose line answers become offsets. The worker sends message ids; the page words them from the diagnostics strings. loadDiagnostics loads it all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The repository checks limit sentences to 30 words and test blocks in length, so the long comment lists become short sentences and each long describe becomes several. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The benchmark harness builds a 1,000-line file of ordinary code per checker language and times one run, parse included, as the worker does it. The test holds each language under 50 ms (DESIGN 6.1, gate G-D2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The layers before the code tools pack are built: the scheduler, the syntax layer, the checkers, and engine check registration. The tools pack is the lane's Beta 13 work. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the page the grammars now come from the lang-* packs, which the editor has already loaded, so diagnostics add no new chunks and stay inside the bundle budget. The worker keeps the bare Lezer grammars, since it has no use for CodeMirror. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Completion must work on every build, with no model (DESIGN 10.2). This adds the ranked list (scope names from the Lezer tree, members of known types and modules, keywords and built-ins by bundled frequency, snippets with fields, words from open files, and a recency boost) with a deterministic score. It also adds the pattern predictor for one line of ghost text (idioms, a def colon, numeric steps, and earlier lines with the same start) and the explicit request rule: the predictor at a lower threshold, then the list's top item when it leads the next by a fixed margin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
attachCompletion gives an editor the ranked list and the pattern ghost source, and records accepted items for the recency boost. loadCompletion keeps it in a lazy chunk for the studio window and code cells. Tests run a real editor: the Python for snippet's fields move with Enter and Shift+Enter while Tab indents, and explicit requests insert the leader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Beta's run contract now resolves with how the run ended and takes a context, so the test stubs reject instead of resolving with nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Vitest's module runner turns each import into a property read, which made the parser about ten times slower than in the app. The gate now bundles the harness as the app does and times it in its own Node process, as the diagnostics worker runs it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Code studio can now run JavaScript and TypeScript projects in the run worker. Each run gets a fresh QuickJS runtime with the page's limits. - Sucrase strips TypeScript and turns import and export into require. It keeps every line in place, so errors map to the line in the file. - A loader inside QuickJS serves require from the mounted project: relative paths only, .ts for .js names, JSON, and a cache so each module runs once. A missing file or a package gives a clear error. - console methods, print, readline, prompt, process.argv and exit, and a Math.random seeded from the run. The main file's last value shows after an arrow, as in code cells. - QuickJS stacks and Sucrase syntax errors become RuntimeDiagnostic items on the first project frame. - A Jest-compatible test API (describe, it, test, beforeEach, afterEach, expect with .not) runs every *.test and *.spec file when a run asks for framework tests, and sends one test message per test. Its semantics follow Jest's documentation. Both runtimes are registered in run/adapters.ts, as the run core's hand-over asks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The members type rules read lines nearest the caret first, with string operations and linear patterns. Lines over 500 characters are skipped, so a line of spaces can no longer hang the main thread. Parameter and bare annotations now name a receiver's type. A dot with no named receiver offers nothing. The list keeps 200 items, and the words, scope, and pattern sources read a window around the caret. The scope walk skips scopes away from the caret, so a cold list costs about 2 ms in a 1,000-line file. The perf test now samples cold. Ghost text keeps nested brackets and strings before a closer. The step rule keeps padded widths and stops at zero and at 15 digits. Digits outside ASCII tokenize as single characters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Cap the QuickJS heap at the page memory limit, and end the run when the heap grows past the run's own limit. - Check the time and memory limits after promise jobs, in main runs and test runs. A test run stops at a limit and marks the rest as not run. - Cap a test run at 500 tests and number equal names with a map. - Find error places in paths with spaces and parentheses. - Stop with a clear message at a namespace with code and at an export with several names, which Sucrase 3.35.1 compiles wrong. - Print any thrown value without failing the run. - Keep plain scripts in sloppy mode unless Sucrase changes them. - Keep line-1 columns right after Sucrase's prefix. - Add beforeAll and afterAll, and clear errors for .only, .each, and a test inside a test. Compare symbol keys and Map keys in toEqual. - Add a help page for JavaScript and TypeScript in code projects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # app/src/features/codestudio/index.ts
- Lua: a local whose value holds a function is declared in the scope of its own statement, not inside the function. - C/C++: declare default arguments, parameter packs, using declarations, namespace names, lambda init captures, names a file macro declares, and brace-initialized template variables. - Python syntax: "expected ':'" only for a header that has no colon of its own, at the error's line; match/case only in a match statement. - Python F811/F401: submodule imports compare full names; `x as x` re-exports and `__all__ +=` count. - JS/TS: `print` from the sandbox is a known global; bodiless signatures keep their parameters quiet; `declare function` declares its name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The signature rule scans the line once for brackets, strings, and comments. It shows the colon only when the parameters close at depth zero. An annotation that may still be typed shows only on request. The word counts keep their tail anchored to the caret line, so typing in a large file reuses them. The predictor window is cut by characters too, and the step rule never tokenizes a long line. SQL offers the columns of the nearest CREATE TABLE after "table.", also through a FROM alias. Idioms start at the line start. The step rule skips hex digits and "-0". Tables are read by own key only. Snippets say "snippet" in their note. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Give the capped heap headroom above the run limit, scaled to Emscripten's growth steps, and set QuickJS's own limit above the cap, so many small allocations end as "memory" rather than "Uncaught null"; any error with the heap past the limit is the memory limit. - Make the TypeScript namespace scan linear on blank lines, and catch every Sucrase several-declarator export form (multi-line, no space, no initializer). - The test API reports unfinished tests without program-replaceable built-ins and has a hard closing deadline; toEqual compares array lengths as Jest does. - Known answers for the toBeCloseTo bound, small-object memory runs, and the new guards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both Python runtimes run a project the same way: the files go into the runtime's in-memory file system, a Python prelude sets argv, sys.path, the working folder, prefilled stdin, and the seed, and the run's end comes back as JSON. Tracebacks drop the prelude's frames and the mount folder, and the mapper turns the innermost project frame into a RuntimeDiagnostic. checkPython runs compile() for the L-c checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MicroPython 1.27.0 loads in the warm worker before lockdown with its heap fixed at the memory limit. Its JavaScript table is cut off at load, so the js module gives the program nothing to call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pyodide 314.0.7 (CPython 3.14.2) loads from the opennote-pack scheme while the worker is warm. After lockdown the js, pyodide_js, pyodide, and _pyodide modules are dropped and refused, so the program cannot reach JavaScript or pyfetch. A missing pack gives a plain message. Pyodide is a dev dependency only, for tests; the app never bundles it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
run/adapters.ts loads python-quick and python-full lazily. Tests: the 20-program suite byte-exact in both runtimes, CPython 3.12+ known answers, traceback mapping across files, compile() checks, exit codes, stdin and seeds, and the sandbox escapes after lockdown in a real browser worker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The worker now sends the first 1,000 output messages as soon as the program writes them. A synchronous runtime keeps the worker busy until the run ends, so held output was lost when the time limit or Stop ended the worker. Past that, output goes in 4,096-character pieces as before. A runtime can now say it reads only the prefilled input (RuntimeAdapter.prefilledOnly). The worker then reports the run as not interactive, so the console says interactive input is not available (DESIGN 4.4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Exit codes: a bool counts as an int, and a code past 32 bits is clamped, so sys.exit(False), sys.exit(True) and sys.exit(2**40) end the run at once. The session refuses any other exit the page would refuse. - Memory limit in both runtimes: heap.ts caps WebAssembly memory growth at the request's memoryBytes. MicroPython starts with a 1 MiB heap and its growth is capped from the top of what it used at load. - The prelude imports its own modules with the project folders off sys.path, so a project random.py, io.py or json.py no longer replaces them. The program's own import still finds its file. - Full Python: a plain asyncio event loop before the cut-off, and the cut-off also drops Pyodide's js import hook and refuses _imp.create_builtin for the cut modules. - Prefilled-only input in both runtimes; a byte order mark is treated the same in a run, a check, and the written files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Count bytes written to MEMFS against the run's memory limit; a write past it fails with ENOSPC (OSError) in both runtimes. - The cut-off now destroys and drops every JavaScript proxy Python holds (the Pyodide API object among them), removes _pyodide_core's functions from every module and from the copy create_builtin uses, and makes Pyodide's classes refuse to make JavaScript values. - The reach test (shared by both test files) tries the closure route, walks referents and attributes, and walks JavaScript values deeply. - Links in the project are removed, never followed; the walk skips them and a walk error keeps the run's status. - The check reports errors without a frame and parser give-ups; a parser stack overflow ends a run as "error", not "memory". - os._exit gives its exit code; raw runtime text and the start failure text come from the strings file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
# Conflicts: # app/bundle-budget.json
# Conflicts: # app/src/features/codestudio/run/adapters.ts
# Conflicts: # app/src/features/codestudio/index.ts
# Conflicts: # app/src/features/codestudio/index.ts
# Conflicts: # app/bundle-budget.json # docs/FEATURE-LIST.md # docs/tools/featureCommands.ts # docs/tools/registry.json
ADR 0074 is Accepted in its file, so the index says so too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
L05's adapters carry check(); L10 waited for runtime lanes to register one. registerRuntimeChecks registers compile() in full Python as the pyodide engine check, loaded on first use, with no marks when the pack is missing. L06 sets readline, prompt, process, module, exports and require; no-undef now knows them, and a test reads the runtime's sources to keep the list true. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tests program now reaches the Python runtime through the diagnostics barrel, so it needs the same declaration file the app program has. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
featureCommands.ts went over its 800-line limit with both trains' sentences in it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ctrl+Shift+E is Word's Track Changes and Google Docs' center. The review lane bound it in every set, which clashed with the Docs set's para.alignCenter from the text shortcuts lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rows for comments and suggestions, Python and JavaScript runs, error detection, completion, and block merge. A help page for Python in code projects, and a comments and suggestions section in Typed notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments and suggestions register with the page at start-up: 620.7 KB gzipped against 620. Sucrase loads only in the run worker for TypeScript runs, at 44 KB gzipped. 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.
Merge train for six Beta 12 lanes: one integration branch off beta, one CI run.
Lanes (merge order)
Conflicts (7 files over 4 merges)
app/bundle-budget.json(L05, text-review): kept beta's higher budgets (start-up 620/30, KitAeroTool 230).run/adapters.ts(L06): union of the Python and JavaScript/TypeScript adapters.codestudio/index.ts(L10, L12): union of loadCodeProjects, loadDiagnostics, and loadCompletion.docs/tools/featureCommands.ts(text-review): union of beta's format and layout sentences and review's 19.docs/tools/registry.json,docs/FEATURE-LIST.md(text-review): regenerated.Fixes on the train
diagnostics/runtimeChecks.tsregisters L05's compile() check (full Python, lazy, no marks without the pack) for L10. L10's no-undef knows L06's runtime globals (readline, prompt, process, module, exports, require). Both with tests.featureCommands.tswent over its 800-line limit: review sentences moved tofeatureCommandsReview.ts.tests/tsconfig.jsonincludes MicroPython's module declaration, since the tests program now reaches the Python runtime.Waiting on later lanes
Gates (local)
🤖 Generated with Claude Code