Merge pull request #212 from levineuwirth/post-1.1.0-accuracy

Absorb the v1.1.0 release, and correct what it made stale
This commit is contained in:
Levi Neuwirth 2026-08-01 18:27:38 -04:00 committed by GitHub
commit 21de0b2038
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 166 additions and 46 deletions

View File

@ -95,7 +95,7 @@ remain open to them.
| § | Concern | Grade | One-line state | | § | Concern | Grade | One-line state |
|---|---|---|---| |---|---|---|---|
| 2 | Golden product journey | **Runs to step 10** | `pmacs .` opens the directory (1a); the interface introduces itself (1b-3); a missing language server says so (1b-2, #204); a build is bound and prefilled (1b-1, #203). Steps 1, 11 and 12 remain the thin end | | 2 | Golden product journey | **Runs end to end, thin at 1112** | **Step 1 now works — v1.1.0 ships binaries (#211)**, so the journey no longer begins with a source build. `pmacs .` opens the directory (1a); the interface introduces itself (1b-3); a missing language server says so (1b-2, #204); a build is bound and prefilled (1b-1, #203). **Steps 11 (background-work ownership, §9) and 12 (session restore) are the remaining thin end** |
| 3 | Zero-configuration state | **Partial** | Defaults genuinely strong; missing-tool failure is silent, not graceful | | 3 | Zero-configuration state | **Partial** | Defaults genuinely strong; missing-tool failure is silent, not graceful |
| 4 | Progressive disclosure | **Inverted** | The advanced level is real; the beginner level is the missing one | | 4 | Progressive disclosure | **Inverted** | The advanced level is real; the beginner level is the missing one |
| 5 | Unified discoverability | **Partial** | Discovery Stage 1: eleven `help.*` commands (describe key/mode/hook/buffer/command/setting, where-is, list commands/keybindings/settings, apropos) over the existing registries, indexed by `M-x help`. Commands, keys, modes, hooks and settings are now reachable, and `*workers*` already was (`M-x editor.list-workers`); **packages have no comparable surface** (§13), and workers still lack owner/purpose/hierarchy and any indicator (§9). `Command` still has no title/category/flags, M-x rows are still bare names, and the Rust help layer is still orphaned | | 5 | Unified discoverability | **Partial** | Discovery Stage 1: eleven `help.*` commands (describe key/mode/hook/buffer/command/setting, where-is, list commands/keybindings/settings, apropos) over the existing registries, indexed by `M-x help`. Commands, keys, modes, hooks and settings are now reachable, and `*workers*` already was (`M-x editor.list-workers`); **packages have no comparable surface** (§13), and workers still lack owner/purpose/hierarchy and any indicator (§9). `Command` still has no title/category/flags, M-x rows are still bare names, and the Rust help layer is still orphaned |
@ -110,7 +110,7 @@ remain open to them.
| 14 | Workbench primitives | **Partial (best trajectory)** | Listview is a real primitive but only 3 call sites, all LSP panels; buffer-list and search re-implement it; bottom panel complete on BOTH frontends (#155 + Stage 2) | | 14 | Workbench primitives | **Partial (best trajectory)** | Listview is a real primitive but only 3 call sites, all LSP panels; buffer-list and search re-implement it; bottom panel complete on BOTH frontends (#155 + Stage 2) |
| 15 | Contextual affordances | **Weak** | Right-click menu only; code actions apply first-blindly; no git integration at all | | 15 | Contextual affordances | **Weak** | Right-click menu only; code actions apply first-blindly; no git integration at all |
| 16 | Semantic frontend | **Strong** | v6..=v21 schema support; production attach remains v20 during the dark panel slice; degradation practiced | | 16 | Semantic frontend | **Strong** | v6..=v21 schema support; production attach remains v20 during the dark panel slice; degradation practiced |
| 17 | Distribution | **Missing** | CI is test-only; no binaries, channels, checksums, or update path | | 17 | Distribution | **Partial** | **v1.1.0 ships prebuilt Linux/macOS binaries on tag** (#211) with checksums and a stated glibc floor. No channels, in-place update, rollback, signing, or package-manager distribution |
| 18 | Onboarding | **Partial** | Journey Stage 1b-3: an unconfigured launch greets in `*scratch*` naming `M-x` and four real bindings, and `M-x help` renders a cheat sheet. Still no tutorial and `C-h` still deletes a word — deliberately, see §18 | | 18 | Onboarding | **Partial** | Journey Stage 1b-3: an unconfigured launch greets in `*scratch*` naming `M-x` and four real bindings, and `M-x help` renders a cheat sheet. Still no tutorial and `C-h` still deletes a word — deliberately, see §18 |
| 19 | Coherence acceptance tests | **Started** | `tests/journey_acceptance.rs` carries 45 pins over steps 2, 3, 4, 5, 6 and 9 — the ratchet is real and stages add rows to it. The other five §19 scenarios (workspace lifecycle, worker ownership, config provenance, package lifecycle, extension isolation) are still unwritten | | 19 | Coherence acceptance tests | **Started** | `tests/journey_acceptance.rs` carries 45 pins over steps 2, 3, 4, 5, 6 and 9 — the ratchet is real and stages add rows to it. The other five §19 scenarios (workspace lifecycle, worker ownership, config provenance, package lifecycle, extension isolation) are still unwritten |
@ -389,7 +389,7 @@ Full verdict table:
| # | Step | Verdict | Evidence | | # | Step | Verdict | Evidence |
|---|---|---|---| |---|---|---|---|
| 1 | Install | **Partial** | Source build only: `cargo build --release --workspace --features pmacs/crdt` (`README.md`). No binaries, no packaging. Runtime deps (`/bin/sh`, git, tar, coreutils) documented, never checked at runtime | | 1 | Install | **Works** | **v1.1.0 ships prebuilt Linux x86_64 / macOS arm64 binaries with `SHA256SUMS`** (#211); source build remains. Not yet: package managers, in-place update, signing. Runtime deps (`/bin/sh`, git, tar, coreutils) are documented in the release notes but still never checked at runtime |
| 2 | Launch unconfigured | **Works** | `EditorState::new()` → empty `*scratch*`; missing config is not an error (`src/config.rs:7-9`); recentf/saveplace/autosave default-on | | 2 | Launch unconfigured | **Works** | `EditorState::new()` → empty `*scratch*`; missing config is not an error (`src/config.rs:7-9`); recentf/saveplace/autosave default-on |
| 3 | Open real project | **Works at the CLI** | Journey Stage 1a: `resolve_target_buffer` answers `ResolvedTarget::Directory` before the EISDIR-producing load, and `EditorState::open` / the daemon bootstrap dispatch the `path.open-directory` chain, whose fallback is dired (#165's buffer, reached rather than duplicated). Startup no longer fails: an unreadable directory, a crashed resolver, and a cleared handler all report on the status line and leave the session running. Because the listing is async and the bootstrap is synchronous, the commit runs against a destination captured at request time (`pmacs.window.commit_to`) rather than against the ambient frontend | | 3 | Open real project | **Works at the CLI** | Journey Stage 1a: `resolve_target_buffer` answers `ResolvedTarget::Directory` before the EISDIR-producing load, and `EditorState::open` / the daemon bootstrap dispatch the `path.open-directory` chain, whose fallback is dired (#165's buffer, reached rather than duplicated). Startup no longer fails: an unreadable directory, a crashed resolver, and a cleared handler all report on the status line and leave the session running. Because the listing is async and the bootstrap is synchronous, the commit runs against a destination captured at request time (`pmacs.window.commit_to`) rather than against the ambient frontend |
| 4 | Understand interface | **Partial** | Mode line gives name/modified/L:C/scroll + mode/LSP/terminal segments. Journey Stage 1b-3 adds a welcome in `*scratch*` and `M-x help`; **still Partial** because `C-h` deletes a word (deliberately — §18) and there is no tutorial | | 4 | Understand interface | **Partial** | Mode line gives name/modified/L:C/scroll + mode/LSP/terminal segments. Journey Stage 1b-3 adds a welcome in `*scratch*` and `M-x help`; **still Partial** because `C-h` deletes a word (deliberately — §18) and there is no tutorial |
@ -1487,13 +1487,22 @@ optional external tools, and let the user open a project immediately.
### Ground truth ### Ground truth
**Grade: missing — zero release machinery exists.** **Grade: partial — binaries on tag exist; everything after them does
not.**
`.github/workflows/` contains exactly one workflow, `ci.yml`, and it is **Distribution Stage 1 (#211, shipped as v1.1.0) closed the first of the
test-only (fmt/clippy/test matrix; the only `release` strings in it are seven things this section asks for.** A `v*` tag now builds `pmacs` and
`cargo test --release` flags). No release job, no artifact upload, no `pmacs-gpu` on pinned `ubuntu-22.04` and `macos-15`, asserts the tag
tags-to-binaries path, no checksums, no channels, no update or rollback against the crate version and the commit against `main`, verifies the
mechanism. Installation is `git clone` + `cargo build --release archive's exact contents, machine-checks a **glibc ≥ 2.35** floor, and
publishes a GitHub Release with `SHA256SUMS`.
Still missing: channels, in-place update, rollback, signing and
notarization, reproducible builds, package-manager distribution,
Windows, Intel macOS, RHEL 9 (below the glibc floor), and
protocol/package-API compatibility reporting. See
`docs/distribution-stage1-framing.md` §5, where each is a stated
non-goal rather than an omission. Installation is `git clone` + `cargo build --release
--workspace --features pmacs/crdt` (README), which additionally requires --workspace --features pmacs/crdt` (README), which additionally requires
knowing the feature-flag matrix (luajit vs lua54 × crdt). Runtime knowing the feature-flag matrix (luajit vs lua54 × crdt). Runtime
dependencies (`/bin/sh`, `stty`, git, tar) are documented in the README dependencies (`/bin/sh`, `stty`, git, tar) are documented in the README
@ -1681,10 +1690,18 @@ sequencing per §13.
### Priority 8: Ship binaries and release channels ### Priority 8: Ship binaries and release channels
**State: zero (§17). Independent of everything — can start anytime.** **State: Stage 1 SHIPPED as v1.1.0 (#211); the rest of §17 is
The editor becomes testable by users who are not repository untouched.** The editor is now installable by someone who has never
contributors; every other priority's value is invisible until this one cloned the repository — **journey step 1 is reachable for the first
exists. time**, and this priority's stated blocker ("every other priority's
value is invisible until this one exists") is lifted.
What Stage 1 deliberately did not do is as important as what it did:
channels, in-place update, rollback, signing, reproducible builds, and
package-manager distribution are all still absent, and each is a named
non-goal in `docs/distribution-stage1-framing.md` §5 rather than an
oversight. The next increment is a decision about which of those the
project actually wants, not a continuation of a plan.
### How this maps to arcs ### How this maps to arcs
@ -1718,7 +1735,9 @@ implementation — this list is direction, not commitment):
6. **Workspace entity** (P2): the object, then location values. 6. **Workspace entity** (P2): the object, then location values.
7. **Config provenance + adoption** (P6). 7. **Config provenance + adoption** (P6).
8. **Package lifecycle** (P7, after 4). 8. **Package lifecycle** (P7, after 4).
9. **Distribution** (P8, anytime). 9. **Distribution** (P8): **Stage 1 landed (#211)** — binaries on tag,
checksums, a machine-checked glibc floor. Later stages (channels,
update, signing) are unscoped and independent.
A standing process change accompanies all of them (§1.3): **every new A standing process change accompanies all of them (§1.3): **every new
framing doc must state its coherence impact** — which journey steps it framing doc must state its coherence impact** — which journey steps it

View File

@ -29,17 +29,25 @@ the same buffers concurrently with live cursor/selection presence.
## Status ## Status
**v1.0.0 --- stable core, active development.** The v1.0 gate (the **v1.1.0 --- stable core, active development, and the first release
instance/frontend partition, the Lua surface, and a REPL package audited with prebuilt binaries.** The v1.0 gate (the instance/frontend
to use zero direct Rust core access) shipped some time ago. Development partition, the Lua surface, and a REPL package audited to use zero
since has expanded the semantic frontend protocol from v6 through v20, direct Rust core access) shipped some time ago. Development since has
brought the GPU frontend near input/render parity with the TUI, and expanded the semantic frontend protocol from v6 through **v21**, brought
completed the LSP, editing, persistence, themes, and terminal arcs. Recent the GPU frontend near input/render parity with the TUI, and completed
work added major modes and modeline detection, a typed configuration the LSP, editing, persistence, themes, and terminal arcs. Recent work
registry, composable statuslines, multi-language syntax processing, and added major modes and modeline detection, a typed configuration
cross-frontend tab-width parity. Current direction lives in registry, composable statuslines, multi-language syntax processing,
`docs/roadmap-2026-07.md`. Public contributions are open: use, evaluate, cross-frontend tab-width parity, a directory browser, a describe/list
file issues, and send pull requests. command family, and a bottom panel on both frontends.
Current direction lives in `COHERENCE.md` (the product-coherence thesis
and its audited priority order) and `docs/agent-handoff.md` (durable
project state). `docs/roadmap-2026-07.md` is a historical planning
snapshot and is no longer the authority.
Public contributions are open: use, evaluate, file issues, and send
pull requests.
## Highlights ## Highlights

View File

@ -205,6 +205,47 @@ git worktree add ../pmacs-ci-crdt \
githubsucks/ci-crdt-coverage githubsucks/ci-crdt-coverage
``` ```
## Distribution (P8) — STAGE 1 SHIPPED as v1.1.0 (#211)
**Rewritten as a lane rather than removed**: the arc is not done — Stage
1 was scoped to binaries-on-tag and everything else in §17 is untouched.
Framing `docs/distribution-stage1-framing.md` revision 3. Durable facts
are in `docs/agent-handoff.md` §1.
- **Released 2026-08-01.** `v1.1.0-rc.1` (prerelease) then `v1.1.0`,
**both cut from the same commit `000b6cd`** — the #211 merge SHA — so
the final release was built from byte-identical source to the one whose
artifacts were verified.
- **Verified against the DOWNLOADED artifacts, both tags, not the build
logs:** archive member lists (exactly `pmacs`, `pmacs-gpu`, README, two
licenses), executable bits, absence of `pmacs-audit` /
`pmacs_fake_lsp` / `pmacs_fake_mcp`, `pmacs --version` = `1.1.0` and
`pmacs-gpu --version` = `1.1.0 (protocol v21)`, `SHA256SUMS`, the
glibc floor, and CRDT presence **against a non-CRDT negative control**
(1,576 `loro` strings shipped versus **0** in a control build — the
control is what makes the number mean anything).
- **`pmacs` alone needs only glibc 2.34; `pmacs-gpu` needs 2.35.** The
stated floor is the pair's, 2.35, not the more flattering single-binary
number. That is why RHEL 9 (2.34) is excluded even though the editor
binary would run there.
### Still owned by this lane, not yet done
Each is a stated non-goal of Stage 1 (framing §5), not an oversight.
**The next increment is a decision about which of these the project
wants, not a continuation of a plan.**
- **Channels** (stable/nightly), **in-place update**, **rollback**.
- **Signing and notarization.** macOS binaries are Gatekeeper-quarantined
today; the release notes say so.
- **RHEL 9 and older glibc** — needs a container or cross-build, not a
runner change.
- **Intel macOS**, **Windows**, **reproducible builds**,
**package-manager distribution**.
- **Runtime dependency checking.** §17 asks first launch to identify
optional external tools; `/bin/sh`, `stty`, git and tar are documented
and never checked. That is §18 onboarding work.
## Discovery lane (P4) — STAGE 1 MERGED (#207); STAGE 2 IS NEXT ## Discovery lane (P4) — STAGE 1 MERGED (#207); STAGE 2 IS NEXT
**Rewritten, not removed.** Rule 4 removes a lane when its ARC is done; **Rewritten, not removed.** Rule 4 removes a lane when its ARC is done;

View File

@ -1,6 +1,9 @@
# Agent handoff — cross-machine continuity # Agent handoff — cross-machine continuity
**Last updated: 2026-08-01, as the CI CRDT coverage lane #209 — the **Last updated: 2026-08-01, as Distribution Stage 1 #211 — released as
v1.1.0, the first pmacs release with prebuilt binaries, which makes
journey step 1 reachable without cloning the repository. Beneath it the
docs absorption #210 and the CI CRDT coverage lane #209 — the
first time CI has ever compiled and run the `crdt` half of the test first time CI has ever compiled and run the `crdt` half of the test
corpus, closing a gap that left 279 tests (including a REQUIRED corpus, closing a gap that left 279 tests (including a REQUIRED
`CLAUDE.md` gate) unexecuted for the project's whole life. Development `CLAUDE.md` gate) unexecuted for the project's whole life. Development
@ -65,14 +68,55 @@ commands, read `docs/active-work.md` immediately after this file.
## 1. Where the project stands (2026-08-01) ## 1. Where the project stands (2026-08-01)
- **`main` @ `c5f7501`.** The CI CRDT coverage lane #209 lands atop the - **`main` @ `000b6cd`, released as v1.1.0.** Distribution Stage 1 #211
docs absorption #208 and `cfc1710`. Beneath that, nine PRs landed in lands atop the docs absorption #210, the CI CRDT coverage lane #209,
the absorption #208 and `cfc1710`. Beneath that, nine PRs landed in
this order: the ledger absorption #199, the process-signal diagnostic this order: the ledger absorption #199, the process-signal diagnostic
#200, the test ambient-root isolation **framing** #201, the #200, the test ambient-root isolation **framing** #201, the
reap-ledger diagnostic #202, Journey Stage **1b-1** #203, **1b-2** reap-ledger diagnostic #202, Journey Stage **1b-1** #203, **1b-2**
#204 and **1b-3** #205, the ambient-root isolation **implementation** #204 and **1b-3** #205, the ambient-root isolation **implementation**
#206, and discovery Stage 1 #207. Each has its own bullet below; this #206, and discovery Stage 1 #207. Each has its own bullet below; this
line is the head-of-`main` anchor and nothing else. line is the head-of-`main` anchor and nothing else.
- **pmacs is installable without cloning — Distribution Stage 1, #211,
released as v1.1.0.** A `v*` tag builds `pmacs` and `pmacs-gpu` on
pinned `ubuntu-22.04` / `macos-15` and publishes a GitHub Release with
`SHA256SUMS`. **Journey step 1 works for the first time**, and
`COHERENCE.md` §17 moves missing → Partial. Scope was deliberately
binaries-only; channels, update, rollback and signing are stated
non-goals. Five durable facts:
- **A release build can produce FIVE binaries and three must never
ship.** Cargo auto-discovers `src/bin/*.rs`, so `pmacs-audit`,
`pmacs_fake_lsp` and `pmacs_fake_mcp` appear alongside the two real
ones. Exclusion is **two-layered** — explicit `--bin` targets *and*
an explicit staged asset list — and layer 2 is not belt-and-braces:
building the branch, `target/release` still held all three from an
earlier `cargo test --release`, and `Swatinem/rust-cache` restores
exactly that in CI. **Archiving `target/release` would have published
a fake language server.**
- **`env!("CARGO_PKG_VERSION")` expands in the crate being COMPILED.**
`InstanceIdentity::for_running_process` lived in `pmacs-protocol` and
read it there, so the daemon reported the *protocol* crate's version
to every frontend under a field named `pmacs_version`. Three tests
asserted the right thing and **could not fail** while both crates
read 1.0.0 — diverging them is what made the tests discriminating.
*A test can be correct and still prove nothing when the two things it
compares are equal for an unrelated reason.*
- **Pin release runners, never `-latest`.** `ubuntu-latest` (glibc
2.39) silently produces binaries that fail to load on Ubuntu 22.04
and Debian 12; `macos-latest` drifts the minimum supported macOS with
no commit to point at. And **a pinned runner proves nothing about the
artifact** — the glibc floor is asserted by reading versioned symbols
out of the binary (`objdump -T | grep GLIBC_`), so a bad runner
change fails in CI instead of shipping.
- **A tag pushed before its workflow is on the default branch does
nothing, silently.** `on: push: tags` resolves the workflow file at
the tagged commit, and GitHub registers workflows from the default
branch. No run, no error — indistinguishable from "not started yet",
which is the worst possible shape for a release step. Confirm a run
actually appeared.
- **Verify a release from the DOWNLOADED artifact, and use a negative
control.** Checking CRDT presence by counting `loro` strings means
nothing without building a non-CRDT binary and getting zero.
- **CI runs the CRDT half of the corpus for the first time — #209.** - **CI runs the CRDT half of the corpus for the first time — #209.**
`.github/workflows/ci.yml` had never enabled the `crdt` feature, so `.github/workflows/ci.yml` had never enabled the `crdt` feature, so
every `#[cfg(feature = "crdt")]` test was **not compiled** — not every `#[cfg(feature = "crdt")]` test was **not compiled** — not
@ -140,7 +184,7 @@ anchor, so every item is startable.
| 5 | Workbench convergence | Partial, best trajectory | Bottom panel done both frontends; **Stage 3 = flip the adopter default**. Then the tree primitive — build it *before* dired and the worker tree invent two | | 5 | Workbench convergence | Partial, best trajectory | Bottom panel done both frontends; **Stage 3 = flip the adopter default**. Then the tree primitive — build it *before* dired and the worker tree invent two |
| 6 | Config productization | Foundation only | Value provenance, then layering, then adoption migration (**table-valued settings are the hard prerequisite** — `ConfigValue` is four scalars) | | 6 | Config productization | Foundation only | Value provenance, then layering, then adoption migration (**table-valued settings are the hard prerequisite** — `ConfigValue` is four scalars) |
| 7 | Package lifecycle | Not started | Correctly sequenced after P3 | | 7 | Package lifecycle | Not started | Correctly sequenced after P3 |
| 8 | Distribution | Zero | Independent of everything, startable any time. **Every other priority's value is invisible until this one exists** | | 8 | **Distribution** | **Stage 1 SHIPPED (v1.1.0, #211)** | Binaries on tag, checksums, machine-checked glibc floor. **Journey step 1 now works and the "invisible until this exists" blocker is lifted.** Next is a *decision* about channels / update / signing, not a queued plan |
#### Open lanes (branch exists, work not finished) #### Open lanes (branch exists, work not finished)

View File

@ -39,12 +39,14 @@ usage: pmacs [-nw|--no-window] [--help] [--version] [FILE]
pmacs --attach <target> pmacs --attach <target>
pmacs --daemon-attach [--socket NAME|PATH] pmacs --daemon-attach [--socket NAME|PATH]
-nw, --no-window select the TUI frontend explicitly -nw, --no-window select the TUI frontend explicitly. This is the
(currently the only frontend; reserved for the default; `pmacs FILE` already opens the TUI, so
M4 GUI rollout, where `pmacs` will default to the flag exists to say so unambiguously in
the GUI and `-nw` will keep launching the TUI) scripts and wrappers.
--gpu start or reuse a CRDT daemon, then launch the --gpu start or reuse a CRDT daemon, then launch the
separate pmacs-gpu frontend separate pmacs-gpu frontend. Requires a build
with the `crdt` feature, and the `pmacs-gpu`
binary either beside this one or on PATH.
When FILE is present, open it before the GPU window appears. When FILE is present, open it before the GPU window appears.
--daemon run as a foreground daemon listening on a Unix --daemon run as a foreground daemon listening on a Unix
socket; supervised by the user (systemd, tmux, socket; supervised by the user (systemd, tmux,
@ -67,20 +69,24 @@ attach <target> shorthand:
pmacs --attach user@host ssh as user pmacs --attach user@host ssh as user
pmacs --attach ssh:user@host/research ssh, target instance `research` pmacs --attach ssh:user@host/research ssh, target instance `research`
pmacs --attach local:/tmp/foo.sock explicit local socket path pmacs --attach local:/tmp/foo.sock explicit local socket path
pmacs --attach tls:host:port#cert.pem TLS (parses; activation in v0.2) pmacs --attach tls:host:port#cert.pem TLS (parsed, not yet implemented)
A bare hostname is interpreted as `ssh:<host>`. Use `local:` or A bare hostname is interpreted as `ssh:<host>`. Use `local:` or
`--socket` for local-socket attaches. `--socket` for local-socket attaches.
"; ";
/// Frontend the user asked for. Only `Tui` is implemented in v0.1; /// Frontend the user asked for by IN-PROCESS dispatch. Both variants
/// `GuiAuto` records "the user did not force TUI" so future builds /// run the TUI: the GPU frontend is a separate binary reached through
/// can dispatch to a GUI frontend without touching the parsing layer. /// `--gpu`, not a value of this enum. `Auto` records "the user did not
/// force TUI" so a future display-detecting default can dispatch
/// without touching the parsing layer.
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum FrontendChoice { enum FrontendChoice {
/// Explicit `-nw` / `--no-window`. Always TUI. /// Explicit `-nw` / `--no-window`. Always TUI.
Tui, Tui,
/// Default. v0.1: TUI. M4+: TUI when no display is available, GUI otherwise. /// Default. Runs the TUI today. Reserved for a future
/// display-detecting default; `--gpu` is the explicit GPU path and
/// does not route through here.
Auto, Auto,
} }
@ -93,7 +99,7 @@ struct CliArgs {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
enum Mode { enum Mode {
/// Plain `pmacs` (or with `-nw` / a file): run a fresh in-process /// Plain `pmacs` (or with `-nw` / a file): run a fresh in-process
/// TUI. The default for v0.1 — no daemon-attach magic. /// TUI. The default — no daemon-attach magic.
Local { Local {
file: Option<PathBuf>, file: Option<PathBuf>,
frontend: FrontendChoice, frontend: FrontendChoice,
@ -177,8 +183,8 @@ fn build_attach_mode(file: Option<PathBuf>, socket: Option<String>) -> Result<At
/// continue to work. /// continue to work.
/// ///
/// IPv6 literals like `[::1]` are not supported as bare hostnames /// IPv6 literals like `[::1]` are not supported as bare hostnames
/// — the strict parser would reject them anyway. v0.1 SSH config /// — the strict parser would reject them anyway. SSH config aliases
/// aliases and IPv4 / DNS hostnames are the supported shapes. /// and IPv4 / DNS hostnames are the supported shapes.
fn parse_attach_target_with_shorthand(s: &str) -> Result<AttachTarget, AttachTargetError> { fn parse_attach_target_with_shorthand(s: &str) -> Result<AttachTarget, AttachTargetError> {
if s.contains(':') { if s.contains(':') {
AttachTarget::parse(s) AttachTarget::parse(s)
@ -399,10 +405,12 @@ fn main() -> ExitCode {
ExitCode::from(2) ExitCode::from(2)
} }
CliResult::Run(parsed) => match parsed.mode { CliResult::Run(parsed) => match parsed.mode {
// FrontendChoice::Auto and ::Tui both run the TUI in v0.1. // FrontendChoice::Auto and ::Tui both run the TUI. The
// The match is structured this way deliberately so that // match is structured this way deliberately so a future
// when a GUI frontend lands the second arm becomes // display-detecting default can make the second arm
// `editor::run_gui(file)` without touching parsing. // dispatch elsewhere without touching parsing. Note this
// is NOT how the GPU frontend is reached — `--gpu` spawns
// the separate pmacs-gpu binary via run_gpu().
Mode::Local { Mode::Local {
file, file,
frontend: FrontendChoice::Tui | FrontendChoice::Auto, frontend: FrontendChoice::Tui | FrontendChoice::Auto,