bootstrap
Adom Hydrogen (platform base)
Public Made by Adomby adom
Layer Hydrogen's workspace onto a standard Adom workstation.
← Commit history
skills/hd-editor-state/SKILL.mddeleted−52@@ -1,52 +0,0 @@-name: hd-editor-state-description: The Editor State Machine (ESM) — HOW to know the true state of the VS Code editor and the Claude Code conversations inside Hydrogen Desktop, and the HARD typing invariants. Use BEFORE typing into a Claude conversation, driving setup-step threads, diagnosing "state unknown", empty split panels, tab spam, prompts landing in the wrong conversation, or any Claude tab/webview confusion. Trigger words — editor state, /editor/state, claude tab state, conversation state, which tab is active, empty editor group, split panel, double-type, typed into two boxes, prompt in wrong conversation, census, safe to type, stray text, disk verified, msg_count wrong, workbench unknown.--# hd-editor-state — the Editor State Machine--ONE authoritative read: `GET /editor/state` on HD's control API. Everything below is what it-returns and the rules for acting on it. Full design: docs/EDITOR-STATE-MACHINE.md (hd repo).--## The layered truth (never blend layers)--| Layer | Question | Source | Trust |-|---|---|---|---|-| L0 `lifecycle` | starting / editor-up / ready | port probes (7380, :8821, CDP) | absolute |-| L1 `layout`+`conversations` | groups, widths, empty panels, tab census, focused tab | workbench DOM + tab bar | high (VS Code chrome is stable) |-| L2 `extension` | what commands can I invoke | the extension's contributed-command registry + fingerprint | absolute (it IS the API) |-| L3 `conversations_disk` | turns, first prompt, generating, delivered | the jsonl transcripts | absolute — works for DISPOSED background tabs |-| L4 `census` | compose boxes + submit buttons visible NOW | DOM probes across ALL contexts | only under the invariants below |--## The HARD invariants (John 2026-07-17 — non-negotiable)--1. **Never type unless `census.safe_to_type == true`** (exactly 1 visible input across ALL- webview contexts — not just the focused one).-2. **Freshness oracle is the TITLE**: `title == 'Untitled'` = never submitted. NEVER use- `msg_count` for freshness — it counts welcome-screen DOM nodes (reads 5 on a pristine tab).-3. **After a submit, run the stray-text audit**: `POST /editor/audit-prompt {prefix}` must- return `contexts_containing: 0`. 1+ = the prompt is ALSO sitting in another conversation's- box (double-type) — clear it, fail loudly, never ignore.-4. **Delivery is proven on DISK, not in the DOM**: the prompt must be the first user turn of- exactly ONE `~/.claude/projects/*/*.jsonl`. 0 = not delivered; 2+ = double-send.-5. **Background tabs are unreadable** (VS Code disposes their webviews): `loaded:false`,- null ctx/compose. To read one, activate it first (`/claude/tabs/activate {index:<ordinal>}`- — by ORDINAL, never by label: every Claude tab is labeled 'Claude Code').-6. **`normalize_needed: true` → `POST /editor/normalize`** before showing the user anything- (an empty split group steals 50% of their editor; populated 2-group layouts are preserved).-7. **Prefer registered commands over DOM clicks**: `extension.commands` lists them- (claude-vscode.newConversation, .focus, .editor.open, ...). Run via the in-distro- `:8821/command` API. Commands survive extension updates; selectors don't.-8. **Extension drift**: `extension.fingerprint` changes when Claude Code updates — re-verify- your assumptions (anchors, commands) before trusting flows after a fingerprint change.--## Quick recipes--- Am I safe to type? `GET /editor/state` → `census.safe_to_type`.-- Did my prompt double-type? `POST /editor/audit-prompt {"prefix":"<first words>"}` → want 0 after submit.-- Which conversation is generating? `conversations_disk[*].generating` (disk truth, any tab).-- Fix a half-width Claude tab / dead empty panel? `POST /editor/normalize`.-- Bars: `layout.bars` reports activity / primary sidebar / secondary (auxiliary) bar / bottom- panel visibility. A Claude conversation living in the SECONDARY bar is a second compose box- (census=2). Close bars deterministically: `POST /editor/bars {"primary":"close","secondary":"close"}`- (read -> toggle-on-mismatch -> verify; never a blind toggle).