# Pending — uncommitted Theseus changes Working-tree state that hasn't been committed or shipped. Read this before touching the same files. Update when you land or add work. Format: each group has a `session:` label so parallel sessions can see what belongs to whom and coordinate. Naming convention: `YYYY-MM-DD:short-slug` for date-bounded work, or `parallel:` for work owned by a session that isn't the current one. Last updated: 2026-10-29 (post-0.3.130 batch). --- Releases are no longer recorded here: the live version and hashes are in `../site/releases-manifest.json` and `https://dl.silentmode.st/releases-manifest.json`, and each release commit is `Theseus 0.3.x: ...` in git history. ## Staged for the next release (post-0.3.131) - **LANDED: Startpage layout reverted to the pre-0.3.131 default, plus the user's two preferred tweaks baked into the defaults — the slot column is chromeless (floats on the page background, no panel box around it) and default `iconSize` is "large" (60 px tiles).** Changes in [home.html](home.html): - HTML: `
` and `
` back as body siblings (not nested in a `.page` grid with a sidebar aside). `.homepage` is the 2-col grid `minmax(260, 300) 1fr`, hero padded `5vh 1rem 0` as the top of the page again. - CSS: `.sidebar` renamed back to `.left-column`, `.cards-wrap` back to `.right-column`, the `.page` + `.main-col` grid dropped. `.section.chromeless` kept (brought back) — the left column uses it so slots float on the page background like the user had it; the SM cards keep the soft panel surface. - `defaultState().iconSize` is `"large"` (60 px slot tiles) — matches the sizing in the user's screenshot; existing profiles with their own `iconSize` keep that choice. - `.slots-list { grid-template-columns: repeat(3, 72px); width: max-content; margin: 0 auto }` — fixed-cell 232 px grid, centered in its panel. `layoutSlots` back to `minSlots = 9` (3 × 3 rows, matches the SM cards grid height). `minSlotsForFill()` and its `ResizeObserver` are gone. - `.hero .ver-line` CSS + its `body.light` override removed; the `

` markup gone; the init-script block that wired `getVersion()` → `navigate("silentmode.st/releases")` gone. The user asked for "What's new" to be dropped again after I restored it for 0.3.131; `window.home.getVersion` exposure in [home-preload.js](home-preload.js) also removed since nothing calls it any more. - `moveItem()` now strips the `slot` property when a q item moves to sm (link → card). Pin-to-slot is q-only, so leaving the anchor on an sm card re-pinned it back to a slot cell on the next revert. This fixes the user-reported "moving a link to card doesn't work" (actually it moved, but the stale slot anchor flipped it back on the next render). - **Live user state reset.** Backed up `%APPDATA%\Theseus\home-cards.json` to `.bak-before-reset`, rewrote it to the restored defaults — SM cards list contains Game.X (replacing SilentMode.X in its slot), quicklinks strip holds hello.bch / sia.coin / Pithos.sia / Bergamot.X / SilentMode.X, plus any user-added extras preserved. Preserved: `background` (indigo preset) and `iconSize` (large). User must reload the open home tab (Ctrl+R or close/reopen) to pick up the new file. - **LANDED: Claude connector no longer rotates its bearer on every stop (0.2.2).** The old `stop()` generated a fresh token on every server stop, so a Theseus quit, a panel toggle-off, or even a 0.3.X → 0.3.X+1 install silently invalidated every registered Claude. The Connect button wrote the new token to `~/.claude.json`, but any already-running Claude Code or Claude Desktop process holds the previous token in memory and only re-reads config on launch, so `/mcp` reconnect kept sending the stale bearer and the server rejected it. Observed symptom from the connector log: after installing 0.3.131 and clicking Connect, `.claude.json` was updated (correct new token written at 01:02:53) but the running Claude Code session's MCP calls stayed 401 forever. Fix in [bundled-addons/claude-connector/index.js](bundled-addons/claude-connector/index.js): `stop()` keeps the stored token; only the panel's "Revoke token" button rotates. Addon version bumped 0.2.1 → 0.2.2 so `seedBundledAddons` picks up the fix on the first boot of 0.3.132. - **LANDED: Nostr per-site identities (0.1.1).** The 0.3.131 Nostr add-on always signed with Hermes's one `npub`, which gives sites a single identity they can correlate across the Nostr network. 0.3.132 adds a per-origin profile picked on first approval: - `lib/hermes.js` gains `nostrKeyFromRootForOrigin(messengerRoot, origin)` — HKDF with info `silentmode/nostr-origin/v1/` over the existing 32-byte messengerRoot, so every site that chooses "site- specific identity" sees a different `npub` and clients can't cross- correlate. Deterministic from the mnemonic, no new vault field needed. - [main.js](main.js): `_nostrAPI` methods take `{ profileId, origin }`. `profileId` is `"hermes"` or `"origin"`; the signer cache keys on both. Per-origin secret keys are hot-cached under `nostrOriginSkCache` so the async HKDF only runs once per (vault, origin). Backward-compatible: callers that omit `profileId` get the Hermes identity (what 0.3.131 did). - [bundled-addons/nostr/index.js](bundled-addons/nostr/index.js): grant schema gains `profileId`. First-time approval modal shows BOTH npubs side-by-side and two Allow buttons ("Use site-specific identity" is primary, "Use my Hermes identity" is the opt-in to the shared key). Subsequent calls reuse the stored profile silently. Pre-upgrade grants (no `profileId` field) default to `"hermes"` so existing approvals keep behaving the same. - [bundled-addons/nostr/panel.html](bundled-addons/nostr/panel.html): each grant row shows which identity the site sees — "Shared Hermes identity" or "Site-specific identity" with the derived npub under it. - Addon version bumped 0.1.0 → 0.1.1 so `seedBundledAddons` reseeds the fresh-from-0.3.131 copy on the next Theseus start. ## Staged for the next release (post-0.3.130) Queue of asks for the next cut. Items marked LANDED are edited in the working tree waiting for a bump + build. Items marked TODO still need the code change. - **LANDED: Nostr NIP-07 signer** — new bundled add-on `bundled-addons/nostr/` (0.1.0) plus host support. Puts `window.nostr` on https + localhost pages so any Nostr client (Primal, Coracle, Snort, nostrudel) can sign with the identity Theseus already holds. **Needs a Theseus release**: it changes `main.js` and bundles a new add-on, so the extension OTA alone cannot deliver it. **MISSED 0.3.130** — the folder is untracked (`??` in git status), so the detached-HEAD build worktree never saw it. For 0.3.131 the ship script must either `git add` the folder first or `cp -r` it into the build worktree the same way `build/`, `tor/`, `snapshots/` are copied. - [lib/nostr-signer.js](lib/nostr-signer.js) — new. Crypto half: `getPublicKey`, `signEvent` (BIP340 via nostr-tools `finalizeEvent`), nip04 + nip44 encrypt/decrypt. Recomputes `pubkey`/`id` rather than trusting the page. - [main.js](main.js) — `global._nostrAPI` next to `_hermesAPI`. - Identity is Hermes's key (`nostrKeyFromRoot(messengerRoot)`); vault with no mnemonic reports no identity instead of failing obscurely. - Policy per-origin (read vs sign), kinds 0/3/5/10002 re-prompt every time with no remember option. - Tests: `scratchpad/signer-test.mjs`, `nostr-policy-test.mjs`, `nostr-e2e.mjs`. - **LANDED: Home — SilentMode.X moved to the quick-links strip, Game.X takes its place in the Silent Mode cards.** [home.html](home.html) `defaultState().sections.sm` and `.q`. Game.X entry uses a built-in `game` brand mark (new SVG in `BRAND`); the real description and favicon will come from the live site once game.x is up (currently a stub). SilentMode.X moves into the slots strip as the 5th quick-link. **Still TODO:** update the remote cache at `https://dl.silentmode.st/home-cards.json` so existing profiles pick the swap up without resetting (local `sections.sm` isn't reseeded by `migrateCards` — only the remote fetch rewrites it for installed users). - **LANDED: Mail is now a Sidebar quicklink, not an extension.** The user flagged two things in one: the Mail add-on's 0.1.0 panel was a black screen (iframe + XFO: DENY), AND Mail conceptually belongs under Settings → Sidebar (webapp quicklinks) rather than Settings → Extensions. Both resolved by dropping the extension form entirely: - `settings.quickLinks` default list in [main.js](main.js) gains `{ id: "silentmail", url: "https://mail.silentmode.st/", title: "Silent Mode Mail" }` as the first entry. - `migrateAegisRename()` grew a mail retirement block: on first boot of this Theseus, any installed `extensions/mail/` folder moves to `addons-backups/mail-migrated-/`. The one-off `mail/` directory I added under `bundled-addons/` earlier in this session is removed again (the quicklink + retire is the right path). - `"mail"` added to the first-party reserved-ids list so a community add-on can't claim the id after retirement. - The quicklink does exactly what the old extension's "Open Mail" button did (new tab at `mail.silentmode.st`), without taking a panel slot or an Extensions row. - **LANDED: Left-side sidebar panels free their render tree after idle.** [main.js](main.js) `closeLeftPanel`: closed panels used to keep their loaded page (`leftPanelLoadedId` kept, webContents warm) forever — great for fast reopen, bad for RAM when the user docks a heavy app-like panel (Hermes, Pithos, mail) once and never comes back. Now a 2-minute idle timer blanks the panel to `about:blank` after close, dropping iframes/media/listeners; reopen inside the window still reuses the loaded page (`cancelLeftPanelIdleUnload` on open). `LEFT_PANEL_IDLE_MS = 2 * 60 * 1000`. Does NOT touch the right-side `sidebar` view (webapp tabs — Telegram, X, WhatsApp, AI chat) — those are longer-lived by design; follow-up decision whether to apply the same idle unload there. - **LANDED: Startpage light theme palette flip under `body.light`.** [home.html](home.html): the existing `@media (prefers-color-scheme: light)` block only flipped tokens when the OS preferred light. Picking the "light" background preset (`body.light`, set by `applyBg()`) left `--ink` white against a white page, so hero title, SM card titles, slot labels and the ".bch" extension read as pale ghosts. Added a full `body.light { --ink; --mut; --card; --line; ... }` block plus overrides for the hero/card translucent panels (dark-glass → light- glass on light theme so the dark text inside reads), the ctx-menu and modal (white surfaces, dark text). Dark theme untouched. ## session: `parallel:collision-policy` Owner's focus: BCNR ↔ ICANN name collision handling. Not mine — leave for that session to land or bundle by explicit ask. - Android / mobile: [../AriadneResolver/mobile/app/AndroidManifest.xml](../AriadneResolver/mobile/app/AndroidManifest.xml), [BchFetcher.java](../AriadneResolver/mobile/app/src/com/silentmode/ariadne/BchFetcher.java), [Bns.java](../AriadneResolver/mobile/app/src/com/silentmode/ariadne/Bns.java), [build.ps1](../AriadneResolver/mobile/build.ps1) — mobile-side collision changes. - Repo-wide: `.gitignore` gained a `/.keys/` line (harmless). ## Live state Shipped hashes live at `../site/releases-manifest.json` and `https://dl.silentmode.st/releases-manifest.json`. On-chain pointer at `releases.silentmode.bch`. See [GOTCHAS.md](GOTCHAS.md) for the release gotchas.