# History One dated entry per session, appended. Never rewritten. ## 2026-09-09 — Turbo MoonBit built, from an empty repository to a passing gate - **Goal**: a Turbo editor for MoonBit — `/turbo-new-editor` for the language, in this directory, with the MoonBit toolchain's installation documented. - **Changes**: `go.mod` (turbo-core v0.4.2, no active `replace`), `main.go`, `internal/moonbitlang/` (profile, three-file scanner, three starter templates), `Makefile`, `scripts/`, the four release scripts, `docs/{en,fr}/` at 34 pages each, `docs/diagrams/packages.drawio`, `README.md`, and eight test files. - **Decisions**: - **The scanner carries no state.** Established from MoonBit's published lexical grammar rather than assumed: no block comment, no literal that may cross a line, multi-line strings as runs of self-contained `#|`/`$|` lines, attributes explicitly one line. Every other editor in this family threads a carry; this one does not, and a stray quote therefore cannot paint the rest of the file. Rejected: copying Turbo Python's carry structure and leaving the fields unused. - **No table of built-in types.** MoonBit's `uident` rule is lexical, so one line colours `Int`, `StringBuilder` and a type written this morning. Accepted cost: an enum constructor of your own reads as a type. Rejected: a table of the standard library's types, which goes stale the day the library grows. - **The prelude was read out of `moonbitlang/core/prelude`'s generated `.mbti`.** That is how `print` stayed out — MoonBit has never had it, and the compiler said so when the tutorial's first draft used it. - **The toolchain menu is `~M~oonBit`**, put to the user. M is free; both the O and the N of "MoonBit" are taken by Options and Snippets. - **`moon-lsp --stdio`**, with the whole-toolchain installer as the install hint, because moon-lsp does not exist as a separate package. - **Root markers stop at `moon.mod` / `moon.mod.json`**, put to the user. `moon.work` was rejected although `moon` itself looks for it: it only sits above a module, so naming it would make a rare case look like part of the rule. - **Snippet bodies are TOML literal strings**, because MoonBit's `\{…}` is not a valid TOML escape and a basic-string body would make the file the editor had just written unreadable. - **Tests**: 374 tests and subtests. Scanner invariants (one entry per line, spans ordered and non-overlapping, broken input, nothing carried), one case per construct and one per documented refusal, the template contract, the editor assembled on a `SimulationScreen`, the drawio held to `go list`, the languages reference held to the scanner with its keyword row read out of the page, and seven tests driving a real `moon-lsp`. `make check`. - **Falsification**: 50 mutations run across four suites; all caught. Two weak tests were found and strengthened — one that passed with the language list missing from the snippets comment (the file's own slug satisfied the `Contains` check), and one that missed a literal running past its closing quote. - **Quality**: PASS on the first run and again at the end — 0 errors, 0 warnings, 0 smells, total complexity 87, worst file 40 against a limit of 60. - **Docs**: 34 pages × EN + FR. `reference/languages.md`, `explanation/colouring-and-completion.md`, both tools pages, `how-to/enable-completion.md` and the tutorial were written rather than adapted. A new `how-to/install-the-moonbit-toolchain.md` in both languages covers the installer, `MOON_HOME`, upgrading, what each binary is for, and how to check the editor found it. - **Verified in a pty**: the menu bar, `Alt-M`, the create/open pair swapping, every colour claim in the tutorial read back as SGR codes, the About box, `moon fmt` run from the menu, and a file that does not compile showing `×` in the gutter and its message on the status bar. The tutorial's arrow counts were read off the wire rather than counted. - **Two boundaries found and written down rather than worked around**: moon-lsp never diagnoses a `.mbt` file created after it started (turbo-core sends no `didChangeWatchedFiles`; confirmed at the raw protocol level and pinned by a test), and `turbo-classic` draws `syntax.attribute` and `syntax.identifier` identically, so a MoonBit label is invisible as such in that one theme. - **Family**: turbo-core's README, both doc READMEs, `profile/profile.go`, both workspace how-tos and its `.memory/summary.md` now count four editors; its `.go` strings were swept for hardcoded language names and every hit was innocent, so **no library change was needed**. A pre-existing defect was fixed in turbo-python at the same time: its docs claimed `Alt-T` for a menu whose key is `Alt-P`, inherited from Turbo Rust's `Rus~t~` through a mechanical substitution, in eight places across both languages. ## 2026-09-09 (later) — three demo projects, and what building them found - **Goal**: `demos/` with two or three MoonBit projects to open in the editor. - **Changes**: `demos/README.md` and three projects — `hello` (struct, enum, match, labelled argument, interpolation), `shapes` (library plus `cmd/main`, traits, generics, `suberror`, five tests), `syntax-tour` (every construct the scanner recognises, in one compiling file). `.gitignore` gained `demos/**/_build/`. The root README, both doc indexes and both `how-to/install.md` link to them. - **What building them found**, none of which the Go tests could have: - **`derive(Show)` is deprecated**; `derive(Debug)`, or a hand-written `impl Show … with fn output`, is what the toolchain points at. The starter snippets file used it. Fixed there, in the README banner, and in the demo. - **The functional `loop (a, b) { (x, y) => … }` form is deprecated**, replaced by `for i = a, j = b { … break … continue … }`. The starter snippets file's `loop` snippet used it. Fixed. - **`typealias` is not accepted at top level** by this compiler, although the published grammar lists it as a keyword. Left in the scanner's keyword table — it is a keyword to the lexer, which is what the scanner models — and simply not used in the demos. - **`print` does not exist** — only `println`. The compiler caught this three separate times while the demos were written, which is the best evidence yet that leaving it out of the builtins table was right. - **`pub struct` is read-only outside its package**; `pub(all)` is what lets another package construct one. - **A scanner boundary was found and made precise.** Opening `tour.mbt` in a pty showed a string nested inside an interpolation being split: `"answer: \{if true { "yes" } else { "no" }}"` colours `yes` and `no` as identifiers. The reference and the explanation had said "one flat run is the honest answer", which is true of the ordinary case and not of this one. Both pages now state the boundary exactly in both languages, `TestAStringInsideAnInterpolationEndsTheOuterLiteral` pins it, and the demo keeps the line with a comment rather than avoiding it. - **Tests**: one added. `make check` passes, and all three demos pass `moon check` with no warnings, are unchanged by `moon fmt`, and run; `shapes` passes its own 5 tests. - **Quality**: PASS, run #4 — 0 errors, 0 warnings, 0 smells, complexity unchanged at 87. qlty does not analyse `.mbt`, so the demos neither help nor hurt the numbers. ## 2026-09-09 (later) — the theme list gained three entries - **Goal**: none of its own. turbo-core gained `monochrome-light`, `darcula` and `intellij-light`, and renamed `monochrome` to `monochrome-dark`; this repository's documentation had to follow. Eleven themes ship now. - **Changes**: `docs/{en,fr}/reference/themes.md` — the embedded list, three new table rows, and a new "a name a theme used to answer to" section saying `monochrome` still loads; `docs/{en,fr}/how-to/write-a-theme.md` — the inherit-from advice and the shipped-theme count; `README.md`'s themes bullet. No code change. - **History was left alone**: "comments were the dimmest colour in six of the eight shipped themes" in `write-a-theme.md` is a true sentence about when that rule was written. - **Not yet true of the binary.** This repository pins turbo-core v0.4.2, which ships eight themes. The documentation is ahead until turbo-core is tagged and the `go.mod` here is bumped — see turbo-core's handoff of the same date. ## 2026-09-14 — the family count moved from four to five - **Asked**: nothing of this repository. Turbo Golo was built beside it — adapted from this editor's pages — and `docs/{en,fr}/explanation/architecture.md` said the library's packages are used unchanged by "all four editors". - **Changes**: that one sentence, in both languages — four → five. No code touched; no tests run. - **Also in the working tree, not mine**: `demos/hello/.turbo-moonbit/settings.toml` has the user's own uncommitted change (theme `catppuccin-frappe` → `monochrome-light`). Left alone. ## 2026-09-15 — ACP agent windows, ported from turbo-go - **Goal**: carry the Agent Client Protocol support to this editor. The feature itself is turbo-core's — the protocol client, the conversation model, the window widget, the `Agent` menu and the permission dialog all live there. See turbo-core's history for the same date. - **Changes**: `internal/*/acp.toml.tmpl`, embedded in `templates.go` and wired into `profile.Templates.Agents`. That is the entire code change — one file and one line. Plus six documentation pages (EN + FR: how-to, reference, explanation) and their index entries. - **Decisions**: the example agent is `docker agent`, as in every other editor, because the protocol is the point and the agent is the user's choice; the one sentence in the starter file that is about **this** editor names its own fence, and a test holds it to that — a starter file copied from another editor and left naming that editor's language is the obvious way to get this port wrong. - **Tests**: 5 new in `internal/*`: both blanks filled with no `%!` marker, the file loads back as exactly one agent, it explains its keys, it names this editor's own language, and creating it twice leaves the first alone. - **Quality**: PASS 0/0/0. - **Docs**: adapted rather than copied — the slug, the language, the fence, the build command and the language server all differ from turbo-go's, and each was replaced. - Not committed. ## 2026-09-15 (night) — slash commands and `@` mentions, documented - **Documentation and the starter file only in this repository**; the code is turbo-core's (see its `.memory/` of the same date). The user asked for the ACP changes that let an agent's commands be discovered the way Zed discovers them, then for `@` as a file selector. - **Changes**: `docs/{en,fr}/reference/acp.md` — seven key rows for the list, a **Commands and mentions** section, the `session/prompt` and `available_commands_update` rows, the Limits bullet; `docs/{en,fr}/how-to/talk-to-an-agent.md` — "Use the agent's own commands" and "Point the agent at a file"; `docs/{en,fr}/explanation/agent-windows.md` — the "left out" bullet narrowed to images, two sections appended; the embedded `acp.toml.tmpl` — two key lines. Applied by one script across the five editors with an exactly-once anchor check. - **Tests**: `go test ./...` green (the template change is a comment; the tests that read the created file still pass). - **Ahead of the binary**: this repository pins turbo-core v0.7.0, which has none of this. The pages are true once turbo-core is tagged and the pin moved. - Not committed. ## 2026-09-16 — the trace variable and a troubleshooting bullet, documented - turbo-core gained `TURBO_ACP_TRACE=` and an "update this editor could not read" line in Agent status, because the user saw no `/` commands from their own agent and nothing on screen could say why. Documented here EN + FR: a bullet in the how-to's Variants, a section in `reference/acp.md`. Docs only; not committed. - **Later on 2026-09-16**: `demos/hello/.turbo-moonbit/acp.toml` (and `agent.yaml`, docker agent's config copied from turbo-go) now hold two agents — **Bob (llama.cpp)** via `docker agent serve acp`, and the user's **mini-me (llama.cpp)** (`mm -acp`, `AGENT_CONFIG` env) — placed where this repository's demo project already keeps its settings. Verified to load as two agents with this editor's own `Profile()`; not opened, `mm` and `docker` are on the user's Mac. Working files for trying the `/` picker, not part of the feature. ## 2026-09-16 — family count: a sixth editor, Turbo JS - **Asked**: nothing of this repository directly. Turbo JS was built beside it, and the sentences here that count the family went false the moment it existed. - **Changes**: `docs/en/explanation/architecture.md`, `docs/fr/explanation/architecture.md` — "five editors" → six. Nothing else touched; history left as it was. - **Tests**: none affected — documentation only. ## 2026-09-17 — documentation: terminal windows and tools on Windows - **Asked**: nothing of this repository directly. turbo-core gained pseudo-console (ConPTY) terminal windows and a per-platform tools shell (cmd.exe on Windows); the pages here that said "Linux and macOS" or `/bin/sh -c` went false the moment that landed. - **Changes** (EN + FR): `README.md` (terminal windows: Linux, macOS and Windows), `docs/*/reference/terminal.md` (shell row, controlling-terminal row, platform table, error row), `docs/*/explanation/terminal-windows.md` (the Windows section rewritten: a pseudo-console and why it is a file of its own, built and vetted but not yet run), `docs/*/how-to/use-a-terminal.md` (`%COMSPEC%`, the five things to try first on Windows), `docs/*/reference/moonbit-tools.md` (shell row, cmd.exe's globs and `;`, error row), `docs/*/explanation/moonbit-tools.md` (`cmd.exe /S /C`). Applied by one script across the six editors, one anchor per file. - **Not changed**: code, `go.mod`. **The documentation is ahead of the binary** until turbo-core is tagged (v0.9.0) and re-pinned here; the feature has never been run on Windows by anyone. - **Tests**: none affected — documentation only. ## 2026-09-18 — the "Untitled window has no LSP" fix: docs variant added, fix is turbo-core's - **Asked**: propagate to every editor the fix made in turbo-core the same day — saving now announces a document the server does not know (a window that started Untitled gets LSP from its first save), and Save As under a new name closes the old document. See turbo-core's `.memory/history.md` of 2026-09-18 for the defect and the fix. - **Changes here**: `docs/{en,fr}/how-to/enable-completion.md` gain one variant — completion in a window that started without a name works from its first save, no relaunch needed. No code in this repository is involved. - **Quality**: gate not re-run — a Markdown-only change; the gate measures the Go code. - **Docs ahead of the binary**: the behaviour arrives only when turbo-core is tagged and this editor re-pinned. Not committed. ## 2026-09-19 — moved to Rickub: turbo-core v1.0.0 re-pinned, releases published by a workflow - **Asked**: the same migration turbo-go received the same day, for all five remaining editors — turbo-core moved to `rickub.com` and was published as v1.0.0 with a Release workflow. - **Changes, module**: `codeberg.org/turbo-editors` → `rickub.com/turbo-editors` in `go.mod`, every `.go` file, `Makefile`, `scripts/install.sh`, `README.md`, `docs/{en,fr}`, `.memory/summary.md` (turbo-core deep links also from Codeberg's `src/branch/main/` to `blob/main/`). `require rickub.com/turbo-editors/turbo-core v1.0.0`; `go mod tidy` with `GOWORK=off` rewrote `go.sum` from the proxy. - **Changes, release tooling**: `.github/workflows/release.yml` (new), `01-release.tag.sh` (rewritten), `03-build-releases.sh` → `02-build-releases.sh` (tag from `$1`, validation, `replace` check, fresh `release/${TAG}/`, `go install` line in the README, no hand-off to 04), `02-release.publish.sh` and `04-release.upload-binaries.sh` deleted, `release.env` rewritten (`TAG="v1.0.0"`, `ABOUT="Turbo MoonBit"`). All generated from turbo-go's final files with the names substituted; the README paragraph naming this editor's language server and the example file (`main.mbt`) kept from the old 03. Docs: the release section and the wrong-commit variant of `docs/{en,fr}/how-to/make-a-release.md` rewritten. - **Tests**: `release_test.go` regenerated from turbo-go's — see `summary.md`. The file-writing helper is `writeTestFile` because turbo-python's `main_test.go` owns `writeFile`, and the command helper `runOrFail` because `main.go` owns `run`. - **Not done**: nothing committed or pushed — no commit exists yet and `origin` is unreachable from the sandbox. The workflow has not run on Rickub for this editor; turbo-go's identical one has, and published. ## 2026-09-19 (later) — first run on macOS: two real-server tests failed, the defect was turbo-core's - **Origin**: the user's `./01-release.tag.sh` stopped in `make check`: `TestCompletionEndToEndWithRealMoonLSP` ("No completions here") and `TestDiagnosticsForAFileThatDoesNotCompileWithRealMoonLSP` (nothing in 30 s); the four other `…WithRealMoonLSP` tests passed. First time this suite ran on macOS. - **Cause**: macOS temp dirs are `/var/folders/…`, a link to `/private/var/…`; moon-lsp canonicalises paths, so the file the editor announced belonged to no package (no type-level completion) and its diagnostics came back under `/private/var/…`, which turbo-core keyed by `filepath.Abs` could not match. Reproduced on Linux with `TMPDIR` under a symlink and with an LSP probe; the toolchain and the fixture (`moon.mod` / `moon.pkg`) are fine — `moon 0.1.20260915` accepts them, and warns that the JSON manifests are deprecated. - **Fix**: in turbo-core (`lsp.CanonicalPath`, used by `PathToURI` and `pathKey`), to be released as **v1.0.1**. Nothing changed in this repository's code or tests: through `go.work` against the fixed local core, all six real-server tests pass under a symlinked `TMPDIR`, and the whole suite passes. - **Next**: once turbo-core v1.0.1 is tagged — `go get rickub.com/turbo-editors/turbo-core@v1.0.1 && go mod tidy && GOWORK=off make check`, then `./01-release.tag.sh`. ## 2026-09-19 (later still) — the "never diagnosed after start" pin went red on macOS; the fix is turbo-core v1.0.2 - **Origin**: re-pinned to turbo-core v1.0.1, `./01-release.tag.sh` failed in `make check` on `TestAFileCreatedAfterTheServerStartedIsNotDiagnosed`: moon-lsp on the user's Mac diagnoses a file created after it started. On Linux (moon 0.1.20260915) it does not — unless `workspace/didChangeWatchedFiles` names the file, which turbo-core never sent. The documentation the test cited had already moved on (`enable-completion.md`, 2026-09-18) and `languages.md` no longer says anything about it. - **Changes here**: the pin replaced by `TestAFileCreatedInTheEditorIsDiagnosedFromItsFirstSaveWithRealMoonLSP` — `editor.Open` on a file not yet on disk, type the broken fixture, `SetAutosave(true, 10 ms)`, wait for the diagnostic; the one exported way to write a buffer without a dialog. `typeText` sends `KeyEnter` for `\n` (it dropped newlines: traced through a tee wrapper around `moon-lsp`, the saved file was one `///|` line). `os` imported. - **Fix**: turbo-core v1.0.2 (`lsp.Client.FileCreated`, sent by `announceSaved` when the save created the file). Verified through `go.work` against the local core: the new test passes under `/tmp` and under a symlinked `TMPDIR`; **against the published v1.0.1 it fails** — the falsification. - **Next**: when turbo-core v1.0.2 is tagged — `go get rickub.com/turbo-editors/turbo-core@v1.0.2 && go mod tidy && GOWORK=off make check`, then `./01-release.tag.sh`.