From 46545d8ba4e2684740cf48f75bb2d418d92b8cce Mon Sep 17 00:00:00 2001
From: draw me an elephant <68925779+drawmeanelephant@users.noreply.github.com>
Date: Sun, 13 Sep 2026 10:30:19 -0400
Subject: [PATCH 1/5] feat(editor): make Source the hero with Author/Review
density and a Problems hierarchy
A cold open now lands in a calm Author view (Source + Project; review panes
unmounted, authoring hints folded, and section-nav links to Review panes
switching modes before they land) while Review keeps the full chrome. Source
gains a measured line gutter, current-line band, and presentation-only
frontmatter seam over the native textarea, and Problems leads with primary
Build & validate actions, carries per-command aria-busy progress, and
collapses large reports.
Refs #988
---
content/guides/editor.md | 27 ++
.../changelog.d/990-editor-writing-surface.md | 3 +
editor/README.md | 40 ++
editor/ui/src/App.svelte | 54 ++-
editor/ui/src/components/ActionGroup.svelte | 21 +
.../ui/src/components/AuthoringTools.svelte | 22 +-
editor/ui/src/components/Header.svelte | 34 +-
editor/ui/src/components/ProblemsPane.svelte | 63 ++-
.../ui/src/components/PublicationPane.svelte | 19 +-
editor/ui/src/components/ReportBlock.svelte | 27 ++
editor/ui/src/components/SectionNav.svelte | 50 ++-
editor/ui/src/components/SourcePane.svelte | 377 ++++++++++++++++--
editor/ui/src/lib/state/density.svelte.ts | 39 ++
editor/ui/src/lib/state/problems.svelte.ts | 5 +-
editor/ui/src/styles.css | 197 ++++++++-
editor/ui/tests/density-modes.spec.ts | 357 +++++++++++++++++
editor/ui/tests/graph-map.spec.ts | 3 +
editor/ui/tests/reading-hierarchy.spec.ts | 4 +
editor/ui/tests/safe-editing.spec.ts | 4 +
editor/ui/tests/section-nav.spec.ts | 4 +
editor/ui/tests/watch-admin.spec.ts | 3 +
21 files changed, 1288 insertions(+), 65 deletions(-)
create mode 100644 docs/changelog.d/990-editor-writing-surface.md
create mode 100644 editor/ui/src/components/ActionGroup.svelte
create mode 100644 editor/ui/src/components/ReportBlock.svelte
create mode 100644 editor/ui/src/lib/state/density.svelte.ts
create mode 100644 editor/ui/tests/density-modes.spec.ts
diff --git a/content/guides/editor.md b/content/guides/editor.md
index 54ed9046..bf09822a 100644
--- a/content/guides/editor.md
+++ b/content/guides/editor.md
@@ -226,6 +226,25 @@ does not store secrets or run a deployer.
---
+## Density modes and the writing surface
+
+The shell opens in **Author** mode: Source and Project only, with the
+authoring hints folded into one disclosure under the editor. **Review** mode
+restores the full chrome — Problems, Preview, Watch, Graph, and Publication.
+The choice is a per-browser preference, not project state; switching modes
+never touches your buffer or unsaved changes.
+
+Source is the hero in both modes. Around the native textarea the editor draws
+presentation chrome: a line gutter measured against the real text geometry
+(numbers for the visible window sit where their lines actually are, so
+wrapped lines cannot drift them, and the current line is highlighted), a
+current-line band, and a seam under a recognized leading frontmatter fence. The seam reads fence *shape* only — it
+does not parse YAML or keys, and **Build diagnostics** and Boris remain the
+authority on frontmatter.
+
+A section-nav link for a pane that lives in Review switches modes and then
+jumps to that pane, so no link pretends a hidden pane is on screen.
+
## Compiler-backed commands and problems
The Problems pane runs a fixed allowlist of Boris invocations against saved
@@ -256,6 +275,14 @@ Boris exit codes stay distinct: **1** content/graph failure, **2**
usage/configuration failure, **3** I/O/system failure. The editor surfaces the
class plus the raw exit code.
+Commands are laid out by how often an author runs them: **Validate project**
+and **Build diagnostics** lead in a primary group, **Build HTML** sits with
+them, and **Check graph**, **Verify proof**, and **Run impact** recede into
+the analysis row — all still named, visible, and reachable from the command
+palette. The command in flight shows an in-button progress affordance and
+`aria-busy`, not only the status sentence, and a proof report longer than a
+screenful starts collapsed behind **Show proof verify report**.
+
Diagnostics are grouped by content-relative source, severity, and Boris code.
Each problem card offers:
diff --git a/docs/changelog.d/990-editor-writing-surface.md b/docs/changelog.d/990-editor-writing-surface.md
new file mode 100644
index 00000000..b18c4a0c
--- /dev/null
+++ b/docs/changelog.d/990-editor-writing-surface.md
@@ -0,0 +1,3 @@
+### Changed
+
+- The editor's everyday surface now reads as a writing tool first: a default **Author** density mode (Source + Project; review panes unmounted, authoring hints folded, and section-nav links to Review panes switching modes before they land) beside the full **Review** chrome, Source as a measured hero surface with a measured line gutter, current-line band, and presentation-only frontmatter seam, and a primary/secondary action hierarchy in Problems with per-command `aria-busy` progress and large reports collapsed behind an explicit disclosure. Links: [the editor guide](/content/guides/editor.md#density-modes-and-the-writing-surface), [#988](https://github.com/drawmeanelephant/boris/issues/988), [#989](https://github.com/drawmeanelephant/boris/issues/989), [#990](https://github.com/drawmeanelephant/boris/issues/990), [#991](https://github.com/drawmeanelephant/boris/issues/991).
diff --git a/editor/README.md b/editor/README.md
index 217d13c6..e499c0b7 100644
--- a/editor/README.md
+++ b/editor/README.md
@@ -744,6 +744,46 @@ labels.
Presentation only: no endpoint, no Boris surface, and no pipeline change.
+## Density modes and the writing surface
+
+The shell has two density modes (#990), persisted per browser under
+`boris-editor-density` and validated on load like the other editor
+preferences. The mode is disposable UI state, never project truth:
+
+- **Author** (the cold-open default): Source + Project. The review panes
+ (Problems, Preview, Watch, Graph, Publication) are not mounted, and the
+ authoring hints fold into a single disclosure under the writing surface
+ instead of a second card. A section-nav link whose pane lives in Review
+ switches modes and then lands on the real pane — it stays enabled, muted,
+ and titled, so the nav never claims a hidden pane is present.
+- **Review**: the full diagnostics chrome, unchanged.
+
+Source is the hero in both modes (#989): the writing column outweighs the
+file and rail columns, and the editing surface is a bordered, elevated shell
+whose chrome is presentation only:
+
+- a measured **line gutter** — numbers for the visible window are placed at
+ each line's measured position and the current line is highlighted, so
+ wrapped lines cannot drift them (a fixed-rhythm number column would lie on
+ wrapped prose);
+- a **current-line band** behind the text;
+- a **frontmatter/body seam** drawn when the buffer opens with a recognized
+ `---` … `---` fence pair. It reads fence shape only and validates nothing;
+ Boris remains the frontmatter authority.
+
+The geometry comes from a hidden mirror that holds the buffer verbatim with
+the textarea's exact font, padding, and wrapping metrics, the same technique
+Focus writing mode uses for its paragraph bands. The native textarea remains
+the editing authority; typing, undo/redo, save, and recovery are the shell's
+existing machinery.
+
+Problems now carries an action hierarchy (#991): a primary **Build and
+validate** group (Validate project, Build diagnostics, Build HTML) and a
+secondary **Analysis** group (Check graph, Verify proof), with Run impact in
+its named row. The in-flight command carries `aria-busy` plus an in-button
+progress affordance, and a proof report over 24 lines starts collapsed behind
+a `Show …` disclosure. The allowlist and exit-class reporting are unchanged.
+
## Project file tree
The Project pane renders an indented directory tree over the host's file list.
diff --git a/editor/ui/src/App.svelte b/editor/ui/src/App.svelte
index c1788129..bb8d32d8 100644
--- a/editor/ui/src/App.svelte
+++ b/editor/ui/src/App.svelte
@@ -1,5 +1,7 @@
@@ -890,11 +917,16 @@
-
+
-
+
-
-
- rebuildPreview('manual')} />
-
-
+ {#if density.mode === 'review'}
+
+
+ rebuildPreview('manual')} />
+
+
+ {/if}
+ import type { Snippet } from 'svelte';
+
+ // One action row of the editor's shared hierarchy language (#991): a
+ // labelled group whose tone carries primary vs secondary weight. Buttons
+ // keep their own accessible names; the group label is only a landmark for
+ // assistive tech and pointer grouping.
+ let {
+ label,
+ tone = 'plain',
+ children
+ }: {
+ label: string;
+ tone?: 'plain' | 'primary' | 'secondary';
+ children: Snippet;
+ } = $props();
+
+
+
+ {@render children()}
+
diff --git a/editor/ui/src/components/AuthoringTools.svelte b/editor/ui/src/components/AuthoringTools.svelte
index fa1c1c1a..8549b8d1 100644
--- a/editor/ui/src/components/AuthoringTools.svelte
+++ b/editor/ui/src/components/AuthoringTools.svelte
@@ -4,6 +4,11 @@
import { authoring, suggestions, changeCompletionKind, refreshAuthoring } from '../lib/state/authoring.svelte';
import { buffer, insertSuggestion } from '../lib/state/buffer.svelte';
+ // Author mode (#990) keeps the hints present but folded away: the combobox
+ // and schema bounds are one disclosure, not a permanent slab under the
+ // writing surface. Review mode renders the same content expanded.
+ let { collapsed = false }: { collapsed?: boolean } = $props();
+
// The completion combobox owns its keyboard behavior: Esc closes the list,
// the arrows move the active suggestion, Enter inserts it. Focus and input
// always reopen the list after an Esc close.
@@ -28,7 +33,7 @@
}
-