mirror of
https://github.com/NeuralNomadsAI/CodeNomad.git
synced 2026-10-22 22:31:45 +00:00
21 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
01b20b5b78
|
chore(opencode): qualify and recommend runtime 2.1.3 (#1098)
## Summary
- Qualify OpenCode **2.1.3** (latest stable, 22 October) with the
existing locked **2.1.0 client/plugin** dependencies, and **recommend**
it.
- Keep the technical **minimum at 2.1.2**: nothing CodeNomad consumes
changed, so the minimum has no new reason to move.
- A 2.1.2 daemon stays ready and gets an optional upgrade offer. 2.1.3
is the `tested` version. Newer and custom labels keep authenticated
contract recognition.
- The reviewed-contract fast path lists 2.1.3 beside the 2.1.2 minimum.
- The recommended version is updated in the help (all ten locales), both
READMEs, `dev-docs/OPENCODE_COMPATIBILITY.md` and the architecture
skill.
## Contract review (v2.1.2 → v2.1.3, 66 commits)
- **Authenticated OpenAPI:** 119 → **121 paths**, 144 → **146
operations**. Every consumed operation is unchanged. The only changes:
- added `GET /api/experimental/voice/models`;
- added `POST /api/experimental/voice/session/{sessionID}/instructions`;
- an optional hosted `session.id` in the `POST
/api/experimental/voice/session` response.
None of these is on the instance proxy allowlist, so they stay closed.
- **Published declarations:** the client adds only `voice.models` /
`voice.instructions`. The schema changes only typing (agent `color`
decoding, `Durable` as a tagged union). The plugin is unchanged.
- **Windows managed services** move their default port from **45278 to
28894** ([#57428](https://github.com/anomalyco/opencode/pull/57428)).
CodeNomad discovers the daemon through the selected CLI's `service
status` and the service registration, and assumes no port.
- Live check: this machine's shared daemon was upgraded to 2.1.3 and
restarted on 28894, and the running CodeNomad desktop kept working
through it.
- **Core:** mostly refactors, plus behaviour fixes that the native
suites below exercise:
- compaction summary output limit;
- `keepID` validated as a message ID;
- MCP media kept out of attachments;
- only changed instruction entries resent;
- relative-directory V1 migration;
- legacy `apply_patch` permission mapped to `edit`.
## Isolated Windows qualification
Base: dev `
|
||
|
|
0e5dc954bc
|
docs(help): describe the macOS Not Opened block and the Open Anyway route (#1094)
## Problem The **macOS quarantine** troubleshooting section said that macOS "can report that the application is damaged". On a macOS 15.8 Intel VM, the `1.0.0-dev-20261022` Tauri and Electron apps behave differently once downloaded with a quarantine attribute: - both are rejected at first launch with **"CodeNomad" Not Opened**: Apple could not verify "CodeNomad" is free of malware… The only choices are Done or Move to Trash; - `spctl` rejects both bundles: Electron is only ad-hoc signed, Tauri is unsigned, and neither is notarized. The section also limited the **System Settings → Privacy & Security** step to Intel Macs and did not name the actual action. ## Change Ten locales, `docs/help/<locale>/troubleshooting.md`, with headings unchanged: - The introduction states that the macOS releases are not notarized. A downloaded copy is therefore blocked at first launch with **"CodeNomad" Not Opened**, or reported as damaged. - Step 3: for the **Not Opened** message, **Open Anyway** for CodeNomad in **System Settings → Privacy & Security**, confirmed with an administrator password, is an alternative to `xattr`. The Intel-only wording is gone. - macOS labels stay in English in every locale, as in the existing translations. ## Verification - On the VM, after a blocked launch, Privacy & Security showed **"CodeNomad" was blocked to protect your Mac.** with **Open Anyway**. I did not click it, since it needs the user's password. - The documented `xattr -dr com.apple.quarantine /Applications/CodeNomad.app` let both apps start. - `npm run test:help`: 9/9. |
||
|
|
9f93729882
|
fix(opencode): explain why OpenCode 2 cannot be installed beside an older command (#1093)
## Problem On an Ubuntu 24.04 VM, OpenCode 1.17.18 was installed by curl in `~/.opencode/bin` and also linked as `~/.local/bin/opencode`. With that setup, the OpenCode panel offered **no installation**, only the generic "Select a supported executable or install @opencode/cli on the execution host" advice. On macOS/Linux the user npm prefix is `~/.local`, so that link occupies OpenCode's command name exactly where OpenCode 2 would be installed beside the older version. npm refuses to link over it, and CodeNomad never modifies a foreign installation. The plan therefore correctly had no prefix, but nothing told the user why. ## Fix `sharedInstallationPlan` reports the obstacle on the foreign installation, forwarded as `foreignInstallation.blocked`: | `reason` | `path` | When | |---|---|---| | `occupied` | the occupying command | a non-npm command holds OpenCode's name in the user npm bin directory | | `unwritable` | the user npm prefix | the prefix, or a recognized npm installation in it (an `@opencode/cli` launcher, a Windows npm shim or an `opencode-ai` 1.x installation), cannot be written | The installation notice then says how to clear it: move or rename that command, or fix the folder's permissions, then choose **Check status and updates**. The usual curl layout, on PATH only through `~/.opencode/bin`, still offers **Install OpenCode 2 for CodeNomad**. This was verified on the same VM, where the installation then succeeded. The English messages and their nine translations, the `opencode.md` help page in all ten locales and `dev-docs/OPENCODE_RUNTIME_SETUP.md` describe the obstacle. ## Tests - `legacy-installation.test.ts`: builds the exact VM layout (link in the user npm bin directory) and checks that the plan never offers a prefix over the foreign command and reports `occupied`. The ordinary layout must still offer the prefix, and a read-only prefix must report `unwritable` (POSIX, non-root). - `opencode-setup.test.ts`: renders the occupied notice with no install action. - A second POSIX regression puts a verified npm OpenCode 1.x installation in a read-only user prefix and expects `unwritable`, never `occupied`. - Results: - the `opencode-update` unit tests: 51/51 on Windows (1 POSIX-only skipped); on the Ubuntu VM as uid 1000, 48 passed, 0 failed, 4 Windows-only skipped, including both POSIX cases; - the `opencode-setup` browser tests: 34/34; - the server and UI typechecks; - `npm run test:help`. |
||
|
|
1840c71054
|
fix(timeline): mirror every transcript block in order and keep clicks on the clicked marker (#1086)
## What changes for the user The timeline now matches the transcript block for block, and a click lands exactly where it should. - **One marker per visible block, in transcript order:** each reply, each thinking run, each tool (or collapsed tool group), each compaction and each system context. Markers follow Message content: a block that is hidden in the transcript is hidden in the timeline too. - **The clicked marker stays active** until you scroll, and its own block, not just the start of its message, is placed at the reading position. This also works for history that is not loaded yet. - **While scrolling,** the active marker is the first block below the reading line. ## Reproduced in numbers before fixing We replayed 45 of the user's real sessions (65,241 messages, exported read-only) into the real `SessionView`, with the outline, windows and previews served by the real server readers. Each session was measured at 1280×800 with two presets, using 16 real pointer clicks and 8 wheel scrolls per run. Baseline and fix used the same seeds. | Metric | Before, Complet | Before, Balanced | After, both presets | |---|---|---|---| | Sessions out of sync | 43/45 | 42/45 | 0/90 runs | | Markers / expected | 68,949 / 130,818 | 68,949 / 98,759 | 130,818 / 130,818 and 98,759 / 98,759 | | Click: clicked marker active | 53.6% (46.0% the one above) | 57.2% | 1,440 / 1,440 | | Click: block at reading position | 41.5% (median off by 35 px) | 82.2% | 1,440 / 1,440 (median 0.27 px) | | Scroll: reading-line block active | 93.1% | 92.2% | 505 / 505 moving wheels | What was wrong with the markers in the Complet runs: - 29,782 tool markers were collapsed into one marker per step. - 31,777 thinking blocks and 282 system blocks had no marker. - There were 10,232 order inversions. ## Causes 1. Once an outline existed, the outline projection replaced the markers of loaded messages too (`message-section.tsx`). It collapsed a step's tools into one marker placed before its reply, and dropped system blocks. 2. Resident segments merged thinking into replies, dropped thinking-only steps and skipped system parts. 3. After a click or a scroll, the active marker was the message's first marker. The message itself came from a scroll offset that rounds a row starting just below the top to the previous message. 4. Clicks navigated to the message, not to the block. 5. Jumps into unloaded history had no row to hold while the target was not yet rendered. ## How - **Server (outline):** each assistant step can now carry an optional `layout` field. It lists the step's visible parts in order: thinking runs, reply runs and each tool, at most 64 entries. It is computed in the same bounded SQL. Older plugin copies don't send it, and the client then falls back to the counts: thinking, then text, then tools. - **Markers:** `buildTimelineSegments` emits one marker per block, keyed `messageId:type:ordinal`. Loaded messages keep their exact markers. Unloaded steps are placed at their native position from `layout`. - **Click and scroll:** the list's `scrollToKey(key, selector)` holds the selected block on every frame, survives row remounts, and follows Virtua's estimate until the row renders. `timeline-transcript-blocks.ts` maps markers to blocks and finds the block at the reading line. - **Saved indexes:** outline indexes saved without `layout` are revalidated once. - **Docs and help:** updated in `dev-docs/SESSION_HISTORY_NAVIGATION.md` and in the help pages for all 10 locales. ## Behaviour to be aware of - **The timeline has more markers:** about +90% with Complet and +43% with Balanced on this sample, because every tool, thinking and system block now has its own marker. - **Tool icons for unloaded steps:** a step not loaded yet shows its first tool's icon on all of its tool markers, until its window loads. - **Plugin requirement:** the pruning plugin must ship with the new `layout` field. ## Validation - **New regression test:** `tests/browser/timeline-sync.test.ts` passes 4/4 and fails 4/4 on unmodified dev. Fixtures are synthetic. - **Measurement harness:** the opt-in qualification `npm run qualify:browser:timeline-sync`. - **Browser suites:** | Suite | Result | |---|---| | history-navigation | 65 | | message-scroll | 128 | | session-rendering | 47 | | render-cost | 17 | | full-source-copy | 12 | | search-highlight | 11 | | system-messages | 10 | | timeline-tool-filters | pass | | streaming-outline (no full reprojection over 64 token deltas) | pass | | session-search | pass | | transcript-presets | pass | - **Other checks:** UI unit tests 75/75, server session-pruning 70/70, help 9/9 and the UI typecheck pass. - **After rebasing on dev:** the typecheck passes, along with timeline-sync 4/4, timeline-tool-filters, full-source-copy 12/12, usage-metrics 5/5 and streaming-outline. Oversized files touched: `message-section.tsx` (~1,637 lines), `virtual-follow-list.tsx` (~1,368), `message-timeline.tsx` (~508), `message-timeline.css` (204). |
||
|
|
1b97c7df8a
|
fix(transcript): jump between user messages with Alt+Up/Down, also from the composer (#1087)
Shift+Up/Down already selects text in every text field, so the user-message jump could not work from the composer, where people usually are. The defaults become Alt+Up/Down, and Cmd+Option+Up/Down on macOS, where Option+Up/Down moves to a paragraph's start or end in text fields. Neither edits text, so the jump now also works from the composer and other text fields, keeping the draft, its caret and focus; Shift+Up/Down selects text again everywhere. Saved custom bindings are unchanged. The key guard allows text fields and leaves modified arrows where they already mean something: code editors (Monaco moves lines) and terminals, arrow-key widgets, selects and popup triggers (Alt+Down opens them, such as the new-instance launcher), fields that move a list's active option (aria-activedescendant, input[aria-controls], such as the mission picker search), non-text inputs and IME composition. The composer's / and @ picker moves its selection with every arrow key, so its root carries data-prompt-picker and the jump yields while it is open. Platform defaults live in defaultHotkeyBindings, like prompt-alternate-send. The help shortcuts table (10 locales) and HOTKEYS.md describe the new defaults. Validation: unit tests for the platform defaults (no conflict on either platform) and the key guard; browser regressions jump with Alt from the conversation and the composer (draft, caret and focus kept; Shift+ArrowUp still selects), keep the key for an open composer picker, and, with a real MissionPicker for Alt and emulated-macOS Cmd+Option, move the picker search's option without moving the conversation (the guard checks fail without their selectors). hotkeys-settings and composer-picker-enter pass; UI own-tsconfig typecheck, root typecheck and test:help pass. Gatekeeper review (GPT-6.1 Sol): one P2 (mission picker search) fixed, then zero actionable findings at 7eb2cb081da4ebb1a04e5a7391322deaeb154dd4. Refs #1075 |
||
|
|
7a1fc90310
|
docs(agents): keep AGENTS.md to universal rules and agent docs to the current state (#1082)
AGENTS.md loaded about 33,000 tokens into every agent session, subagent and reviewer, mostly per-feature contracts, and the agent documentation around it had accumulated duplicates, dated logs and history of removed designs. This PR makes AGENTS.md a short set of rules that apply everywhere plus an index of area documents, and leaves AGENTS.md, dev-docs and the repository skills describing only the current state. Three commits, reviewable separately: 1. **Move (lossless).** Every per-area rule moved verbatim from AGENTS.md into its area document (existing ones, or six new ones: UI_CONVENTIONS, UI_SHELL, COMPOSER, TRANSCRIPT, SETTINGS, PROJECTS). A script split the old file into 208 units, required one destination for each and checked all 199 content units verbatim at their destination. AGENTS.md went from 134,000 to 16,000 characters. 2. **Trim.** A per-area ponytail review removed rules stated two or three times (keeping the more precise copy), dated validation logs, per-version qualification sections below the current minimum, abandoned designs and self-references; seven documents whose surviving rules live elsewhere were deleted. It also fixed statements the code contradicts (locale registration, the Mission play/recovery condition, plugin package updates, cleanup progress UI, timeline index persistence, automation restart/targets, stale pins and minimums). 3. **Current state only.** The new AGENTS.md rule: no history (removed features and their names, former behavior, provenance, dated logs) and no denials; correct a contradicted statement at its source. DEVELOPER_MODE.md is merged into BROWSER_AUTOMATION.md and every Developer Mode mention is gone (including the README and the browser help page in ten locales). Names that only made sense against older designs are renamed with every reference updated, MISSIONS_ENVIRONMENT_ADMISSION is folded into SESSION_ENVIRONMENT, and INDEX lists every document. The server npm README now states the real OpenCode minimum (2.1.2). AGENTS.md is now about 14,000 characters (roughly 3,500 tokens); AGENTS.md, dev-docs and the vendor README went from about 11,200 lines to under 4,700. Validation: every relative Markdown link and every cited dev-docs path resolves; no reference to a renamed or deleted document remains; `npm run test:help` passes for all ten locales. Review: three independent GPT-6.1 Sol (high) reviews by area found binding rules lost in the trim and current-state passes; 25 were restored as present-tense facts or prohibitions and four contradicting statements corrected, each checked against code. A Fable 5.1 gatekeeper review of the whole PR passed; its follow-up routes session recovery from the index, points to dev-docs/INDEX.md and documents the family identity read. |
||
|
|
ad844d0645
|
feat(transcript): jump to the previous or next user message with Shift+Up/Down (#1077)
Finding "what did the agent answer when I asked…" meant scrolling or hovering the timeline marker by marker. Two new commands, Previous User Message and Next User Message, appear in the command palette and in Settings → Keyboard shortcuts, bound by default to Shift+ArrowUp and Shift+ArrowDown. From the conversation (where focus lands after a send), they place the nearest user message before or after the reading position at the top, paging its history window in when it is not resident, like a timeline click. Text fields, arrow-key widgets, IME composition and modal dialogs keep the keys, so Shift+Arrow still selects text in the composer; key repeat does not repeat the jump. components/user-message-navigation.ts searches the timeline's markers, including the structural index beyond the resident window, and uses list order for a current message without a marker. MessageSection handles the shortcut in the capture phase, before the transcript reads arrows as a scroll gesture; the palette commands reach it through JUMP_USER_MESSAGE_EVENT. The jump requests the index even while the timeline is hidden, and a jump finding nothing resident before it arrives runs once it does. The last target stays the reference while loading or shown, since the list cannot raise a message near the end to its top. Both are forgotten in cancelWindowNavigation, which every other navigation (First/Latest, sends, paging, session changes, deactivation) passes through, and on scroll gestures, so a late index never overrides a newer navigation. The public help lists the shortcut in all ten locales and states the 74-action catalog (it said 49); HOTKEYS.md and AGENTS.md describe the dispatch; labels are translated in every locale. Validation: unit tests for the target search and key guard plus the catalog count (now run in CI); browser regressions for resident and windowed jumps, the composer keeping Shift+ArrowUp, the deferred jump with a hidden timeline, an explicit Latest dropping it, and repeated jumps near the end (the last three fail without their mechanism). hotkeys-settings, header-windows and history-navigation suites pass; UI own-tsconfig typecheck, root typecheck and test:help pass. Gatekeeper review (GPT-6.1 Sol): one P2 (deferred jump surviving Latest) fixed, then zero actionable findings at 7ab3f17d3cac6be694f989fde8d217c313599f9d (rebased on dev as bf6e09990ba7b65789d5789fe00d87b5e1362625; only the help pages' catalog count conflicted). Refs #1075 |
||
|
|
1dabb5110f
|
docs(help): bring the user guide back in line with the current app (#1079)
docs(help): bring the user guide back in line with the current app The help was written on 2026-10-14 and about forty user-visible changes merged since without touching it, so several pages described controls that no longer exist: Missions still listed four playbooks and a Save step for preferences that now save on each change, the depth editor kept its old names, notifications still had their former switches, and voice input pointed to a microphone button that is not in the composer. Every English page was re-checked claim by claim against the current labels (English UI messages) and behaviour, then the nine translations were updated to match, using each locale's own UI labels. Notable corrections: Missions (Compare two models, autosaving defaults with Apply to / Global / Reset, Subsession nesting depth, prepared hand-offs, retired-task interrupts, the named causes of "Mission Control is unavailable", standalone server support); conversations and history (reasoning/tool durations, token lines adding up the cleanup selection, presets including Nothing, timeline markers following Message content, in-place reveal of long text, Open in session, focus after send, Queue message / Steer now, Retrying); settings (notification routing table and defaults, Stats, Mode, info tips, Server setting badge, localized native menus); shortcuts (72 actions, Clear shortcut, Ctrl/Cmd+K); voice (More actions entries, Save status); files (live Workspace refresh, Show 200 more); OpenCode, install, server and updates (2.1.1 recommended, OpenCode 2 beside an older installation, version card first, private loopback listener for Missions, preview releases offered once all builds are published); providers, integrations, browser, SideCars, desktop and remote pages. Translations also repaired older drift, mainly the project-tab closing passages. The Chat settings table header (Default state, its title, item column, the thinking row and its accessible label) was still English in eight locales; it is now translated so the help can cite what users see. AGENTS.md now asks every PR changing user-visible behavior to update the affected help pages in the same PR, since CI validates structure and links but not whether the text still matches the UI; it also corrects the needs-input notification default. USER_HELP.md no longer claims native menus stay English. Validation: npm run test:help (all ten locales, 25 pages, heading ids unchanged), a full help build, and the i18n and transcript-visibility unit tests. |
||
|
|
f314123dd1
|
fix(opencode): qualify and require 2.1.2 for correct Code Mode execution (#1078)
Raise the approved external runtime minimum and recommendation to 2.1.2 after reproducing incorrect native Code Mode job ordering on 2.1.0/2.1.1. Keep the independently qualified 2.1.0 client/plugin build pins and preserve bounded contract recognition for custom/future runtimes. Add the real isolated execute regression to the minimum/latest compatibility matrix, align supported installer fixtures without weakening assertions, and update setup/help in all ten locales. Two author-side review passes found no blockers; the final focused set passes 93/93 and native Code Mode passes. Qualification includes builds/typechecks, UI/browser, native pruning/Missions/recurrence, migrations and isolated installation/upgrade. Record the broad server shutdown timeout and its two unchanged isolated passes precisely. Admin merge explicitly authorized by the maintainer without waiting for CI. |
||
|
|
f5c5eefefc
|
chore(opencode): qualify and recommend runtime 2.1.1 (#1055)
Recommend the qualified external OpenCode 2.1.1 runtime while retaining minimum 2.1.0 and the unchanged locked client/plugin build. Align setup/update regression expectations and the recommended-version help tables in all ten locales; preserve authenticated contract recognition and mutation/ownership fences. Record isolated Windows native runtime, session/account/usage, pruning UI/history, four historical migrations and all eleven recurring Mission journeys. Server units pass 2442 with seven skips, UI units 1635 and focused browser tests 125; final dev Settings/preview-offer deltas and retained-minimum controls are revalidated. Two review passes found no actionable issue in the PR. Admission/update tests and explicit isolated 1.x-to-2.1.1 replacement pass. The user explicitly authorized administrator merge despite the unrelated Tauri Windows negative-control race test failure, the general test job still running at inspection and the required GitHub review. No stable release is published by this merge. |
||
|
|
88532c23bd
|
feat(composer): queue or send now from the More actions menu, Alt+Enter by default (#1054)
The composer's More actions menu now offers the follow-up delivery Enter does not use: Queue message when Enter steers, Steer now when Enter queues. It is enabled only in normal mode while the session runs and a draft can be sent, and it goes through the same delivery resolution as the shortcut, so an idle session always sends normally. Alt+Enter becomes the default alternate-send shortcut on Windows and Linux, with Ctrl+Shift+Enter kept as a second binding. On macOS Option+Return is the native line break in text fields, so only Cmd+Shift+Return sends there; the platform check lives once in hotkey-definitions. The file/command picker now ignores any modified Enter, so Alt+Enter never selects the highlighted item. The menu tooltip shows the effective shortcuts, the help tables note Alt+Enter is for Windows and Linux, and the menu rebuilds only when its enabled states flip. Validation: composer-alternate-send and composer-picker-enter browser tests (including Alt+Enter with the picker open), hotkey-bindings unit tests for macOS and other defaults, usePromptKeyDown, submitPrompt, hotkeys-settings, help test and UI typecheck pass. |
||
|
|
46208ad902
|
fix(settings): adopt a live window for Preferences startup state and spin the Stats refresh (#1050)
Native Preferences showed "The CodeNomad window that opened Preferences is no longer available" with disabled startup controls whenever its opener was unknown (Preferences restored at launch) or closed, even with CodeNomad windows open. Startup state (restore previous state, saved snapshot, Clear) is each window's own, so the host now adopts the most recently used local window as the opener in that case: Electron through PreferencesWindowRegistry.adoptOpener (startupStateTargetId), Tauri through set_opener (startup_state_target). The epoch rotates on adoption, so a change prepared for another window degrades to a read of the adopted one before any write. The warning and its string in all ten locales are removed; the card re-reads up to three times while the adopted window starts and stays disabled only when no local window can answer. Code contracts, AGENTS.md and the public help in all ten locales describe the opener, otherwise the most recently used window. Stats' text Refresh button becomes the shared icon button sized like the period select, keeping its localized accessible name and tooltip; the icon spins while a read runs. Validation: Electron unit tests for live/closed/unknown openers, adoption, epoch rotation and fenced changes; Tauri unit test for adoption and fencing; preferences-startup-state (Electron and Tauri hosts), other-profiles and service-usage browser tests; UI and Electron typechecks; help test; rustfmt check. Independent review: the first pass found that startup state is per window and that the fence no longer followed the target; the adoption fix was re-reviewed and approved, with two trivial notes applied. |
||
|
|
7d9093de68
|
feat(timeline): follow Message content tool visibility (#1049)
Timeline tool markers now follow the Message content filters: a marker disappears when the tool type it shows (its icon; the outline's representative tool for indexed history) is hidden there, and the Nothing preset removes every tool marker. As with hidden tools before, the transcript's active marker and markers with an active permission stay visible, so highlighting and reveal keep following the transcript. Collapsed tools keep their marker. Because the rail now follows those filters, the separate "Show tool calls in the timeline" preference is removed everywhere it surfaced: Settings > General, the View menu item in the renderer, Electron and Tauri hosts, the palette command, its shortcut catalog entry (72 actions, 23 initially unbound) and its strings in all ten locales and the help. Saved values are ignored; the server schema passes unknown keys through, and hosts ignore an extra field from older renderers. The never-updated expandedMessageIds timeline input is dropped. Intended default change: tool markers are visible with the Balanced preset unless their type is hidden in Message content. Validation: new timeline-tool-filters browser test (hidden, Other-routed and collapsed tools, Nothing/Everything presets, a hidden active marker shown and highlighted); view-menu, a real Electron View menu, hotkeys-settings, transcript-presets, render-cost, history-navigation and other timeline suites (one local-environment failure that also fails on unmodified dev); related unit tests; UI typecheck; rustfmt check of view_menu.rs. Independent review approved after the active-marker fix. |
||
|
|
04e7aae1db
|
feat(transcript): add a Nothing preset and a preset menu in Message content (#1043)
Transcript presets are now Nothing, Minimal, Balanced and Everything. Nothing hides every message-content row, including all registered, historical and unknown tools, thinking, diagnostics, tool inputs, tokens and system messages. Detailed is retired: saved Detailed choices load as Custom with Detailed's effective tool column (only read, skill and invalid collapsed, other tools expanded) and the same legacy thinking fallback, so existing transcripts keep their appearance. The Message content popup gains a native select under its title with the four presets. A disabled Custom entry appears only after a manual row change, and the saved preference always drives the shown value, so refused or failed saves never leave a stale choice. Escape closes an open list before the popup. Preset recognition and patches move from Chat settings into the shared transcript-visibility module used by both surfaces; the tool-output command reuses the shared Other-tools resolution. Preset names and descriptions were English in most locales; they are now translated in all ten, along with the accent-less French, German and Spanish card strings. The public help lists the new localized presets. Validation: new transcript-presets browser test (popup order, choices, Custom after a manual change, pointer choice keeps the popup, Escape order, French labels) plus existing status-tokens tests; unit tests for preset round-trips, Nothing visibility and the Detailed migration; behavior-registry tests; help test; key parity across locales; UI typecheck with the pinned 2.1.0 client. Independent review approved with no P0-P2 findings; its two trivial P3 notes were applied. |
||
|
|
7a2ee897ec
|
fix(projects): keep the new-tab launcher project-only (#1039)
## Summary Remove the three bottom actions (Servers, SideCar, Full home) from the project-tab plus launcher. Also remove its server disclosure, profile hook/loading, local expansion state, server actions/dialog binding, unused props/icons/CSS and four keys in all locales. This is not just hidden chrome. Recent search/list, Browse, Temporary and Clone remain. A normal plus click still opens home. All long-press/context/keyboard gestures and Escape focus remain. Home keeps remote server and SideCar functionality; shared server setup is mounted only for its caller. ## Validation UI typecheck passed. Real new-instance-launcher browser suite 8/8: retained actions/gestures/focus, no server requests from launcher even with saved profiles, home remote/SideCar controls retained. Desktop/narrow captures inspected. git diff --check passed. No app/daemon/state touched. ## Scope 48 files (+110/-190), largely 10-locale help and removed translations. App.tsx remains oversized (~915 lines); only obsolete launcher props changed. |
||
|
|
d6a890fba7
|
chore(opencode): qualify 2.1.0 and adopt its native contracts (#1029)
Adopt the OpenCode 2.1 native replay and compaction contracts, align client/plugin pins and set minimum and recommended runtime to 2.1.0. Preserve authenticated contract recognition for future/custom runtimes and explicit installation/restart boundaries. Preserve historical conversations through official projection-based pruning revisions and independently checked migrations from 2.0.3, beta-19271 and 2.0.32. Retain ownership, execution claims, stale-selection checks and transaction fences. Update setup, help and qualification evidence. Isolated Windows native qualification and integration checks cover pruning UI, historical reimport, Compare/Wayfinder, recurring Missions, builds and typechecks. Document broad-suite limitations and outstanding platform/package/mobile acceptance; this merge does not publish CodeNomad 1.0.0. |
||
|
|
db6685cb55
|
fix(workspaces): closing a project tab closes the project in CodeNomad (#970)
## Problem
Closing a project tab only hid it in that window. The backend workspace
record kept routing the folder's events, notifications, auto-accept and
pending-request recovery, invisibly, until the palette-only **Stop
Workspace** command was run on the active tab. That command still showed
the V1 message "Stop OpenCode instance? This will stop the server."
although V2 has one shared OpenCode service, and it called
`debug.location.evict`, which (per OpenCode source) rejects pending
permissions, cancels pending Forms, fails plugin RPC and kills terminals
of that directory, even for sessions started elsewhere. OpenCode loads
locations on demand and unloads idle ones itself.
## Change
- **Closing a project tab** (×, Ctrl/Cmd+W) removes that tab's backend
workspace record. CodeNomad stops following it; sessions keep running in
OpenCode and reappear when the project is reopened.
- **Another tab of the same folder** has its own record and is
unaffected.
- **The same record shown in another window**: that window's tab closes
through the existing `workspace.stopped` broadcast, with an info
notification ("closed from another window"); the initiating window shows
nothing.
- **CodeNomad never evicts OpenCode locations**: eviction, its
serialization helpers and `locationOwned` bookkeeping are removed. A
failed launch now always removes its logical record (the retention only
existed to retry a failed eviction).
- **Stop Workspace removed** (command, confirm dialog, i18n keys in all
locales).
- Unchanged: opening an open project still offers a new tab (recent row)
or switching (switch button); temporary projects keep Keep / Discard /
Cancel; window close, app quit, reload, restore and backend shutdown
delete nothing; disconnected-instance dismissal stays local.
- Delete failure: error toast, record kept and reachable from the home
page, no automatic retry.
## Docs
Help in all 10 locales (`projects`, `index`, `desktop`, `server`,
`opencode`, `missions`), `AGENTS.md`, `CONTRIBUTING.md`,
`dev-docs/architecture.md`, `packages/server/README.md` and the
architecture-guide skill now describe the new contract.
## Validation
- UI store tests (`--conditions=browser`): app-tabs,
temporary-instances, workspace-list-reconciliation-fence,
instances-restore-ownership — 30/30.
- Server: manager + shared service 54/54; event ownership and workspace
identity suites pass.
- New real-component browser regression (click ×, Ctrl+W, Cmd+W): 3/3;
project restoration (Electron/Tauri) and new-instance launcher browser
suites pass.
- `npm run test:help` 9/9 (250 pages); UI, server and Electron
typechecks.
|
||
|
|
de44f7b29c
|
fix(pending): name the cause, folders and sessions in the recovery warning (#965)
The "Question and permission recovery is incomplete" warning now says which project it concerns, why recovery failed, which folders failed and which sessions made them required, instead of a fixed sentence. ## Why - The previous warning grouped every possible cause into one fixed text and named none of them, including unrelated failures such as the initial workspace load. - Six earlier fixes each removed one measured cause, but every new cause produced the same text, so it could only be diagnosed by live captures. - With several projects open, it did not even say which project was affected. ## Example Before: > Question and permission recovery is incomplete. Known requests are retained; inactive worktrees are not loaded. Now, for the live case fixed by #964: > **CodeNomad: questions and permissions not fully recovered** > Outside this project: prompt-replay-yield. Affected sessions: ISSUES Codenomad. ## Change - **Server:** every `error` directory in the pending snapshot carries a `reason`: - `not-owned`, `deleting`, `missing` (an owned folder that no longer exists), `unverified` (Git/filesystem/WSL translation could not verify it) and `changed` (ownership or repository changed during the read); - a native placement outside the workspace is reported as `not-owned`, and a deletion fence raised during the read as `deleting`. - **UI, `stores/pending-recovery-cause.ts`:** a small module turns failures into a structured cause: - folder issues, plus client-side `timeout`, `unavailable` (with the HTTP status when known) and `excluded` (a required folder reported as history); - the plugin being unavailable, repeated supersession, an initial load failure and a generic request failure. - **Messages:** - folder issues are grouped by cause, named by folder basename, and capped at three with a remainder; - only the sessions that made a folder required (active, or holding a request) are named; - the title uses the same label as the project tab (`lib/instance-label.ts`, shared with `instance-tab.tsx`). - **Diagnostics:** the structured cause is also logged at warn level. - **Unchanged:** the two-attempt threshold, once-per-episode notification, re-arming on success, retained queues and deferral handling. - **i18n:** the generic key is replaced by the cause keys in all 10 locales. ## Tests - Server: `pending-requests.test.ts` 40/40; every error assertion now names its reason. - UI: - `instances-pending-requests` passes, including the live scenario: an active session in a folder reported `not-owned` produces "Outside this project: prompt-replay-yield. Affected sessions: ISSUES Codenomad.", while an idle session in the same folder is not named. A timed-out batch names each folder. - The unavailable plugin is named. - New `pending-recovery-cause.test.ts` covers grouping, caps, the detail variants, request classification and failure combination. - 39/39 together with the compaction and permission lifecycle suites. - i18n tests and both typechecks are clean. |
||
|
|
1a9f202420
|
feat(desktop): localize native menus and open About in Settings → Info (#963)
## What - **Native menus follow the UI locale** (Electron and Tauri): top-level menus and every item of the app, File, Edit, View, Window and Help menus. Previously only the custom titlebar's top level and the View panel items were translated. - **About CodeNomad opens Settings → Info** (the About card with version, updates and diagnostics) instead of the bare native panel. It runs a new `open-about` command, also listed in the command palette. ## How - Renderer translates `NATIVE_MENU_LABEL_KEYS` (`lib/native/menu-labels.ts`) and sends them as `menuLabels` with the existing View menu state for the focused window; older hosts ignore the field. - Hosts: English until a renderer reports labels; the last locale is kept for windows without one (loading/sign-in); labels validated (known keys, non-empty, ≤ 200 chars); `&` escaped outside macOS. - **Electron**: rebuilds its menu when labels change; role items get explicit labels; English defaults come from the English messages (`menu-labels-en.ts`). - **Tauri**: every translatable item (including predefined Edit/Window items) is built explicitly, retained and retitled in place on the main thread, outside our mutexes. `menu_labels.rs` defaults are checked against the English messages by `menu-labels.test.ts`. - About fallback when no application window can receive the action: Electron's native panel, Tauri a short version dialog. - Help pages now name menu items in each page's language (Help → CodeNomad Help, Get Updates, New Window, Zoom). - i18n: 30 `window.menu.native.*` keys + 3 `commands.openAbout.*` keys in all ten locales; existing New Instance / Command Palette translations reused. ## Validation - Electron `view-menu.test.ts` + `menu-target.test.ts`: 3/3 (locale change, per-window labels, kept locale, invalid labels, `&` escaping). - Tauri `cargo test -- menu`: 25/25 (label resolution/validation + existing menu tests). - `menu-labels.test.ts`: every locale complete; Tauri defaults identical to English messages. - `help-command.test.ts`: 5/5 — About opens native Preferences on Info locally, embedded Info remotely. - `npm run test:help`: 9/9. - Typecheck: UI only the pre-existing `help-url.test.ts` error; Electron only pre-existing `Array.at` lib errors. - **Not run locally**: the real-Electron menu suite (`view-menu-electron.test.ts`, Electron not installed here) and a running Tauri build. `packages/tauri-app/src-tauri/src/main.rs` is already oversized (~2,700 lines); only `build_menu` and the About handler changed. |
||
|
|
d09d1222fa
|
feat(ui): merge Updates into About and move connectivity last in Info (#962)
Settings → Info showed the CodeNomad version three times: as the UI version in About, as the server version at the top of the connectivity card, and again as the server version in the separate Updates card. The network card, mostly useful for remote-access troubleshooting, also sat between About and the version/update information most users look for. About now opens with a single Version row (the server version, else the UI version). A separate UI version row appears only when the served UI differs from the server, the one case where both matter. The former Updates card becomes an Updates section of About, with the same feed selector, latest version, help text, install/download and Refresh actions, without its own copy of the version. Diagnostics follows, and the connectivity card moves last without its version row; its server OS, architecture, listener and address details are unchanged. A "Version" label is added in all ten locales and the unused Updates subtitle removed. The Updates help page now describes a section rather than a card in every locale. The diagnostic report, bug report environment and update behaviour are unchanged; only the presentation moves. Validation: a new browser case checks the card order (About, Diagnostics, connectivity), the Updates section and feed inside About, that the version appears once, and that a differing UI version adds its own row. Info and desktop-update browser suites pass 26/26, diagnostics/client-OS/bug-report unit suites 19/19, and npm run test:help 9/9. ES2022/DOM typecheck reports only the pre-existing help-url.test.ts error from #859. Two independent COMMENT gatekeeper rounds; the round-1 P3 (help still describing an Updates card) is fixed and the final head reports zero actionable P0-P3 findings. |
||
|
|
c0d53f13d4
|
docs(help): multilingual help site with in-app Help menu and palette entry (#859)
## Summary A complete public CodeNomad help site in the app's ten languages, published on GitHub Pages (https://neuralnomadsai.github.io/CodeNomad/) and opened from the app. - **Content:** 25 pages in 8 sections (Start, Workflows, OpenCode setup, Remote access, Customize, Extensions, Desktop, Help), written for OpenCode power users and covering the current version only. It includes everything user-relevant from `README.md`, `packages/server/README.md` (server, network, auth, TLS, Remote Control) and the user-facing dev-docs, with flags, defaults, labels and safety boundaries checked against source. - **Languages:** en, fr, de, es, he (RTL), ja, ne, ru, tr, zh-Hans. Interface labels reuse each locale's own app strings; native desktop menu names, code, commands, flags, paths and anchors stay unchanged. - **Site:** `scripts/build-help.mjs` renders `docs/help/<locale>/<slug>.md` with translated chrome (`docs/help/i18n/`), stable `{#id}` anchors identical across locales, same-article language links with hreflang, a root language chooser, and a first-party offline per-locale search (Ctrl/⌘+K, substring matching for CJK, Devanagari and Hebrew, hidden without JS). No analytics or remote resources. - **Validation:** `npm run test:help` fails on any missing page or string, heading drift, broken link/anchor/asset or invalid search target. `.github/workflows/help-pages.yml` validates PRs and deploys only from `dev`. - **App entry points:** one `open-help` command for the palette and a new **CodeNomad Help** item at the top of the Electron and Tauri Help menus. It opens the help in the invoking window's UI language through the existing external opener, falls back to the root URL for windows without the handler, and reports failures without replay. - Documents the strict boolean environment-variable rule from #959 and the updater entry points from #960. ## Review Delivered as a CodeNomad mission with independent review loops, each to zero findings: - English content audit (5 passes, 14 fixes) and technical gatekeeper (2 passes) before translation. - After translation: QA, UX review, and a final multilingual gatekeeper (35 translation/label findings fixed, then verified), plus a visual fix for the search focus ring and a verified sync with #960. ## Validation - `npm run test:help`: 9/9 (25 pages × 10 locales, strict, including negative tests); `npm run build:help`: 250 pages. - `node scripts/test-help-browser.mjs`: 44/44; Playwright: 500 page visits at 390 and 1280 px, all locales, no overflow, no external requests. - UI help-command and desktop-updates browser tests 19/19; help URL unit tests; Electron menu tests; UI and Electron typechecks; Tauri `cargo test` 272/272. |