Commit graph

17 commits

Author SHA1 Message Date
Pascal André
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.
2026-10-21 14:36:51 +02:00
Pascal André
6a6367b560
chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034)
## Summary
This PR removes OpenCode compatibility code that nothing can reach any
more:
- Code that was already dead at the former 2.0.27 minimum, and is still
dead at the current 2.1.0 minimum (#1029).
- Handlers for events and data shapes that OpenCode V2 never produces.

Each item was checked against the upstream 2.0.27 and 2.1.0 sources
before removal.

Kept on purpose:
- Workarounds for upstream bugs or limits that are still present in
2.1.0.
- Code that reads conversations written by older runtimes: V1-migrated
tool names and metadata, `workspaceID` data, task summary titles,
`session-legacy` replay.
- Code that recognises and upgrades old CLIs and live older daemons: 1.x
replacement, beta recognition, 2.0.11 service discovery, 2.0.15 native
upgrade, `/api/status` and `/api/health` identification.

## Removed or changed
**Server**
- Negotiation: one "not modern → `canonical_api`" rule replaces the
pre-2.0.4 legacy schema recognition, and runs before #1029's
`native_contract` check.
- The transport no longer rewrites `/api/status`.
- Desktop skills no longer send the pre-2.0.4 `location` and `slash`
fields.
- The legacy `auth.json` usage fallback for daemons without
`credential.list` (pre-2.0.20) is removed, along with its UI reason and
the i18n key in 10 locales. A missing endpoint still fails safely.
- Workspace selectors are rejected up front, without a native resolution
request.
- CLI service probes try `/api/info` first. An admitted daemon no longer
costs two authenticated 404s on every check.

**UI**
- Remaining V1 `session.idle`/`session.status` branches: Missions store,
pending discovery (UI and server), `eventAffectsMessages`.
- `server.instance.disposed` and the now-unused `rehydrateInstance`.
- The V1 `worktree.ready` envelope (the handler now reads the V2 shape).
- V1 tool-state titles and the `success` status alias.
- Part `time.start` and `time.end`.
- Text stored as objects or segment arrays.
- `deriveMessageStatus`.
- The V1 `error.data.message` shape.
- `projectID` and `location` fallbacks on `session.created`.
- The replay-only `session.message.content.updated`.
- The unreachable `output.answers` fallback.

**Fixtures, Missions and docs**
- Legacy branches removed from the location, fork, families, pruning and
automation native fixtures. The WSL setup fixture now compares against
the reported version instead of 2.0.11.
- Unused 2.0.21 launch helpers removed.
- The Missions native and trajectory fixtures also run on the minimum
lane.
- The capability proof checks the reported version.
- Stale 2.0.2x labels now say "as of the 2.1.0 minimum".

**Follow-ups from the #1029 post-merge review**
- Test fixtures no longer send the ignored `recent: ""` compaction field
(18 sites).
- The manual compaction-isolation fixture accepts any published version
at or above the minimum.
- `CONTRIBUTING.md` wording updated.

114 files, +319 / −1117: source +90 / −487, tests/fixtures/CI +214 /
−604, i18n −10, docs +15 / −16.

## Validation (rebased on dev with #1029)
**Typechecks:** server and UI pass.

**Server tests**
- Touched areas: 480/480.
- Full server CI step: 2430 pass, 0 fail, 7 skipped, 1 cancelled. The
cancelled test is the `index.test.ts` real-process shutdown test; it hit
its 5 s timeout under load. It passes alone (4/4), and that file is
unchanged versus dev.

**UI unit tests**
- Touched files: 230/230.
- CI steps: 574/574, 200/200 and 519/519.

**Browser suites**, one at a time:
- Provider and service usage: provider-usage 13/13, service-usage 3/3.
- Missions: mission-visibility 3/3, mission-control-feedback 5/5,
mission-lifecycle-revision 10/10, mission-lifecycle-navigation 10/10,
mission-current-passage 1/1, mission-native-family 11/11.
- Transcript and rendering: compaction-responsiveness 5/5,
session-rendering 47/47, reasoning-collapse 3/3, render-cost 17/17,
tool-images 4/4, system-messages 10/10.
- Other: search-highlight 11 pass (1 skipped by its env gate),
panel-extensions 13/13.

**Native fixtures on an isolated 2.1.0 CLI:** location, session-fork,
automation, session-pruning, missions native, missions trajectory,
provider-usage, Missions capability proof and compaction-isolation all
pass. The WSL setup fixture was not run (it needs a WSL distro with a
Linux CLI).

## Left for later
- `RuntimeIdentity.discovery` is now write-only.
- `ownsLocation` has an unused `_client` parameter (about 30 callers).
- A test-only V1 translation in `auto-accept-manager.test.ts`.
- Out of scope: HTML-entity decoding (a product decision), the
`MutableHashMap` loop, the pruning-UI import-order workaround, unused
log-based Missions readers, and the unshipped managed-owner module with
its 2.0.24-pinned test.

Oversized source files touched: `stores/instances.ts` ~2,209,
`message-block.tsx` ~1,601, `workspaces/manager.ts` ~1,104,
`tool-call.css` ~1,047, `tool-call.tsx` ~865, `opencode-data.ts` ~865,
`api-types.ts` ~784, `session-events.ts` ~606,
`recurring-day-fixture.ts` ~535.
2026-10-20 19:19:47 +02:00
Pascal André
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.
2026-10-20 16:46:38 +02:00
Pascal André
1ce629b9a6
docs(sidecars): document SideCars as trusted same-origin extensions (#1001)
## Summary
Documentation only. SideCars are now documented as **trusted same-origin
extensions** of CodeNomad, replacing the "temporary exception /
isolation follow-up" wording introduced with #994.

## Why
The isolation follow-up was prototyped, measured and reviewed, then
rejected:
- **Opaque sandbox:** the frame loses cookies and storage, so the
service's own login and state break.
- **Separate origin:** keeping service cookies requires a same-site
origin (another port or subdomain). Chromium still sends the
application's `Lax` cookie across ports of the same host, and CORS alone
did not block authenticated writes, so every API would need an origin
barrier.
- **Per-view ports:** these are unreachable through a single exposed
port, reverse proxy or tunnel, and reset service storage on every
opening.
- **IP and single port:** with a literal IP and one exposed port, no
frame topology gives both isolation and working `Lax` cookies.

## Changes
- **`dev-docs/architecture.md`:** records the decision and these
constraints.
- **`AGENTS.md` and the architecture-guide `desktop-conventions.md`:**
refer to the decision instead of a pending prototype.
- **`CONTRIBUTING.md`:** no longer claims SideCar frames are sandboxed.
- **`README.md`:** tells users to add only services whose content they
trust.

The #995 cookie filtering stays as is; no behavior change.
2026-10-18 03:38:56 +02:00
Pascal André
db6685cb55
fix(workspaces): closing a project tab closes the project in CodeNomad (#970)
Some checks failed
Publish help / build (push) Has been cancelled
Publish help / deploy (push) Has been cancelled
## 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.
2026-10-15 15:14:29 +02:00
Pascal André
8e8ca15934
chore(opencode): qualify runtime 2.0.29 and align client/plugin pins (#948)
## Summary

- Recommend and pin OpenCode **2.0.29** (`@opencode/client`,
`@opencode/plugin`); the technical minimum stays **2.0.27** since
2.0.28/2.0.29 keep Effect 4.0.1.
- Add 2.0.29 as a reviewed contract profile beside 2.0.27; 2.0.28 and
future/custom labels keep authenticated negotiation.
- Test fixture only: the recurring Missions host declares the
`credential` domain that the 2.0.29 Promise adapter reads eagerly (the
managed owner spreads `ctx`, dropping the Proxy fallback). No product
code change.
- Two new isolated fixtures for upstream behavior changes: bounded
output-length continuation, and rejected Promise tools / native denial.
- Compatibility docs, CONTRIBUTING, AGENTS and architecture guide
updated.

## Upstream review

- OpenAPI: same 118 paths; additive schema changes (config `policies`,
provider/model `compatibility`, `encoding`).
- Private LocationServiceMap/Form/Permission/queue contracts used by the
pending snapshot: unchanged.
- Effect stays 4.0.1.

## Validation (Windows, isolated CLIs/databases, never the shared
daemon)

- 2.0.29: plugin runtime, automation, pruning/history/proxy, Missions
contract/family control/full journey, session environment, fork, aside,
prompt skills, Git degraded/init, provider usage/accounts, temporary
workspaces, blank-session cleanup, output-limit continuation, Promise
tool failure, system settings discovery, native upgrade 2.0.15→2.0.29.
- 2.0.27 (minimum): plugin runtime, automation, pruning, Missions
contract/family, session environment, fork, aside, prompt skills, blank
cleanup.
- Server: 2235 passed / 7 skipped / 0 failed. UI: 1524 passed. Tauri
crate 268/268, updater handoff 1/1, UI updater flow 13/13 (dev base
includes #786).

## Known, not caused by this change

`scripts/test-permission-receipts-native.mjs` times out identically on
2.0.27 with the previous pins; tracked separately.
2026-10-14 15:06:35 +02:00
Pascal André
dd5a1f387d
fix(opencode): share host plugin runtime and require 2.0.27 (#920)
## Résultat
Corrige le chargement des plugins CodeNomad avec OpenCode 2.0.27 et
établit cette version comme minimum pour les prochaines releases et les
prereleases dev. Aucun déploiement de l’application active ni
redémarrage du daemon partagé.

## Cause démontrée
- Le runtime natif passe d’Effect 4.0.0-rc.112 à 4.0.1. Le bundle
précédent reproduit `cache.stackFrame` sur une CLI 2.0.27 isolée.
- Embarquer Effect 4.0.1 ne préserve pas la 2.0.26 : échec inverse
`cache.scheduler`.
- Les schémas 2.0.27 consomment `Schema.isStartingWith`, absent du
moteur 2.0.26. Le plancher est fondé sur cette rupture mesurée, pas sur
une liste de versions testées.

## Implémentation
- Pins client/plugin synchronisés à 2.0.27 ; Effect et le SDK public des
plugins sont fournis par OpenCode, hors bundles natifs
pruning/Missions/automation.
- Réglages de build partagés et régression qui interdit une seconde
copie du runtime ; smoke natif ajouté à la matrice minimum/latest.
- Diagnostic `plugin_runtime` traduit dans les dix locales ; versions
futures et personnalisées conservent la reconnaissance authentifiée du
contrat.
- Adaptations du SDK : annulation des lectures projet, références de
credentials externes et connexion fournisseur externe avec formulaire
natif, sans fallback OAuth/API key ni rejeu.
- Le runtime OpenTunnel du backend reste isolé et inchangé. Aucun
tunnel, route ou identité distant n’est modifié.

## Validation locale
- Échec reproduit sur 2.0.26 et réussite sur 2.0.27 pour les variantes
de bundle comparées.
- Suites natives isolées automation,
pruning/historique/proxy/concurrence/redémarrage et Missions réussies
sur 2.0.27.
- Régressions ciblées de build, store/serveur et navigateur (diagnostic
du minimum, connexion externe et brouillon conservé) réussies ;
typechecks UI/serveur/Electron/OpenTunnel réussis.
- Suite serveur complète et CI multiplateforme encore en validation à
l’ouverture ; aucun résultat entièrement vert anticipé.

La revue gatekeeper indépendante sera publiée ici avant fusion. Les
anciennes preuves de qualification restent historiques, pas une promesse
de support des moteurs antérieurs au nouveau plancher.
2026-10-12 16:42:07 +02:00
Pascal André
81fb513558
feat(missions): native project coordination, briefings and tracking (#866)
# Missions: product specification

## Product goal
Missions coordinates complex work through native OpenCode conversations.
CodeNomad provides creation, controls, human attention and result
reading; OpenCode owns execution. One-time objectives and finite daily
recurring passages share the same planning and reading experience. No
OpenCode modification is required.

## Create and configure
- **Flexible mission**: free-form objectives and bounded delegation.
- **Debugging**: diagnosis, implementation, independent
standards/specification reviews and fresh validation.
- **Exploration**: bounded decisions and parallel investigation, with
explicit native human questions where required.

Creation presents an objective, a short optional title, verbatim working
notes, coordinator/task profiles and native or independent task-session
policy. Optional choices stay collapsed. A single **Create** button
saves a prepared one-time mission or paused recurring schedule without
starting anything. **Play** is a separate explicit action for both.

Settings → Missions contains defaults for **all new missions**, with
optional exceptions for each of the three types, including Flexible. A
type exception overrides the global value; an unset field shows the
inherited value. Defaults never reconfigure existing missions or busy
actors. Reusable briefs contain creation inputs only; loading copies
them into a normal draft and deletion preserves executions. **Save as
brief** is also available from a selected one-time mission, including a
completed mission: it copies objective, verbatim notes, template, stored
profile choices and task-session policy; the mission title prefills the
brief name, never copying execution identities or results.

Profiles choose an agent, model and optional reasoning variant.
Coordinators use primary/all profiles; native task actors use
subagent/all and independent actors use primary/all. Business roles
remain separate from native session identities. Actor continuation
preserves the accepted profile.

The native subagent-depth editor is separately Location-scoped and
applies to all OpenCode conversations there, not just missions. It shows
the configuration file, effective value and override. Conditional Save
preserves the original file expectation and never automatically reloads
or restarts OpenCode.

## Missions panel
The first toolbar holds only general actions: **Create**, **Settings**
and **Refresh**, aligned right. Settings opens the Missions settings
section directly, using the existing native Preferences window on
desktop. A native refusal shows an error rather than opening a second
embedded window; browser and remote windows retain their embedded
settings.

The current-mission line contains a leading chevron, the selected title
and a small status mark:
- Clicking the **chevron** expands a persistent inline list; selection
leaves it open.
- Clicking the **title** opens a transient popup; selection, outside
interaction or Escape closes it.
- Both lists show titles and status marks, with full labels in tooltips
and accessible text. Titles truncate only at the available row edge.
- Search appears only when the measured list exceeds its maximum height,
and remains available while a query is present.
- The closed chevron indicates activity/attention in other missions
using the same visual vocabulary as the session list.
- Only the picker changes the selection, remembered per project; opening
a mission's conversation never reselects a mission.

Selected-mission controls are separate: **Play/Pause**, **Stop**,
optional recurring **Run now**, then **Summary**, **Open coordinator
conversation**, **Edit** and **Delete**. Destructive actions require
confirmation. **Request an update** is a text button below the icons,
available only while meaningful; its pending/uncertain state is retained
without automatic replay.

The **Tasks** disclosure contains only the declared dependency tree, not
a duplicate task list. It is initially open, remembers its state and
uses the remaining panel height down to the window bottom rather than a
fixed task-height cap. Rows retain full-width selected/hover backgrounds
across connectors and controls. A task's exact conversation shortcut
appears on desktop hover/keyboard focus, and remains visible on touch.

Mission selection is remembered per project and changes only through
explicit mission selection/creation. Opening a coordinator or task
conversation in the session list never changes the selected mission.
Conversation shortcuts remain available from the mission panel to the
coordinator and exact task conversations. The session-list files are
unchanged relative to `dev`; restoring the full cached session hierarchy
is supplied by the separately merged #841.

## Plan and native execution
The coordinator declares tasks, dependencies, roles and expected
outcomes. Ready work can run in parallel through ordinary native
subagents. Recursive decomposition follows OpenCode permissions and
configured depth; the product imposes no delegation target or root
fallback.

Independent sessions remain available for an explicit Location, lifetime
or existing-root requirement. The task-session policy is frozen per
mission. Tasks have stable keys/generations; conversations have exact
native identities. Business dependency edges never stand in for native
ancestry.

Native task returns and business settlement are separate: a coordinator
records the actual returned result/evidence, then finalizes the mission.
A notification/admission acknowledgement is not proof of consumption or
completion.

## Results and human interaction
Long objectives, briefings, task results, evidence and plan history open
in the central reader above the transcript. Reader eyes toggle the exact
target and highlight it. Task results come before the original brief and
technical details. A missing/unavailable reader target must not leave
the transcript hidden.

The coordinator publishes dated, bounded briefings explaining delivered
results, remaining work, obstacles and the next step in plain language.
Briefings remain separate from task settlement and observed activity;
exact request identity is required to acknowledge an explicitly
requested update.

Attention contains real native Forms and permissions. Obstacles reported
in prose are not automatically human requests. Native interruptions
retain conversation provenance and drafts in the shared interruption
dock. A template's required human decision counts only when answered
through the CodeNomad UI, locally or from a live paired Remote Control
device; a simple UI-answer mark records that provenance.

Users give direction or ask questions by writing in the coordinator
conversation (**Open coordinator conversation**). From the panel itself,
the only coordinator message is **Request an update**; its
pending/uncertain state is retained by identity and never replayed
automatically.

Reports, plan history and cleanup receipts stay secondary in
reader/technical surfaces. Optional managed-session cleanup preserves
coordinators, shared/reused/moved sessions and roots with descendants.

## Lifecycle and recovery
For one-time missions:
- **Play** starts/resumes explicit mission intent; **Pause** parks
mission dispatch/notifications and interrupts the observed active native
family.
- **Stop** is terminal and interrupts observed descendants
deepest-first, then registered roots/coordinator, with bounded rechecks
for parent wakes caused by child cancellation.
- Native inbox cancellation uses exact authorized mission/subagent work.
Pause preserves deferred results for explicit Play; Stop removes the
identified queued work/results that would wake a stopped coordinator.
- Per-target receipts record observed interruption and family coverage.
Incomplete or unconfirmed interruption is shown as **Some sub-agents may
still be running**, never as proven recursive suspension.
- **Refresh** reconciles state first; an explicit refresh click may
retry a still-unconfirmed lifecycle action under its original identity.
Reconnect and ordinary display reads never resend mutations.
- **Play** offers targeted recovery only when native observation
establishes the applicable interrupted state, not merely because
activity is unknown. Active background descendants retain the
active/Pause presentation.

Native interruption does not undo completed filesystem/tool effects.
Resuming a paused mission lets the coordinator decide how to continue or
re-delegate interrupted work; there is no hidden task replay engine.

## Recurring missions
Recurring setup adds permanent instructions, a title, a daily local
time/timezone and explicitly followed project conversations. Saving
creates a paused schedule; Play arms it and Run now requests one finite
passage.

The OpenCode service/plugin owns scheduled passages while both CodeNomad
UI and its intermediary backend are closed. One native Job per running
schedule sleeps until the earlier of the next due time and one hour. On
waking it rereads the clock/document and admits only the latest due
civil day newer than the stored daily cursor; there is no backlog.
Native execution terminal events also wake observation after a debounce,
but are not settlement evidence.

Before native effects, conditional storage records deterministic
passage, coordinator and start-message identities. Lost replies
reconcile those exact identities rather than creating new attempts. A
passage archives only after the coordinator and descendants are
inactive, inboxes are empty and no relevant native Form, permission,
Shell or background subagent remains. Unknown coverage stays pending.

Passages end as completed with a final report, native terminal failed,
or ended-without-report/interrupted. Only completed passages advance
followed-conversation cursors. Schedule history is bounded to 30
passages. Civil-time DST gaps/repeated times and entirely skipped days
resolve deterministically.

Pause/Stop cancel the schedule Job; those schedule actions do not prove
an already-running passage family stopped. Stopped is terminal. After
service restart, a desired-running schedule without its Job is
**Interrupted**, awaiting explicit Resume. Resume reconciles pending
work, never sends a continuation; a turn cut by restart settles
interrupted/ended-without-report.

## Durability and UX
Mission journals and schedule documents retain tasks, roles/profiles,
results, plan revisions, controls, notifications and bounded history.
Conditional writes and original request identities protect mutation
retry. Authority, Location ownership, fresh per-send environment and
connection/deletion fences are checked at admission. Ordinary native
permissions govern tool use.

UI remains compact and square, localized in all supported languages,
keyboard-accessible and usable on touch/narrow/RTL layouts. Cache-first
display reads revalidate on visible demand and native invalidation,
without polling or clearing known data on uncertain recovery. Loading,
missing capability and uncertain effects remain explicit.

## Shared integration scope
The PR also includes supporting shared-runtime corrections; these are
not limited to the Missions tab:
- Session outcome and generation-recovery reconciliation retains
uncertain interruption state across reconnects and checks native
outcomes before clearing it. Native message pages clamp to the service's
200-message limit.
- Pending-request recovery retains known requests through incomplete
coverage and connection transitions; native ownership and deletion
fences remain authoritative.
- Keyboard offset and the compact composer help strip preserve reachable
input controls without changing composer height limits. Touch overflow
actions suppress duplicate compatibility clicks.
- Workspace text saves enter the existing worktree mutation fence;
sandboxed panel asset reads fence connection changes. Worktree scans
retain validated family identity and custody.
- The worker-based Git process runner uses an ESM-safe worker entry, and
CLI service discovery shares bounded command deadlines.
- Desktop/backend profile identity is explicit for Missions' owned
storage. Profile-scoping signals are internal to that relationship, not
permission for independently launched applications to inherit a profile.
- Shared rendering/localization includes a Turkish tool-call label
correction.
- Session-list startup restoration exposes a settled signal
(`stores/session-list-restoration.ts`, hooked in `session-api.ts` and
`instances.ts`). Missions display reads wait for it so the session list
loads first; it settles on success, failure, timeout or abandonment and
is reset when a workspace is removed. Session-list components and styles
are unchanged.

These callers are included in integration review and their regression
tests, rather than treated as an unchanged dependency surface.

## Current limitations
- Editing/deleting recurring schedules is not implemented; those icons
in the selected mission's action bar are disabled for schedules.
- An uncertain one-time creation (lost reply after the request was sent)
is held in window memory with no status endpoint; Create stays blocked
for that window until reload. Definitive refusals before any native
effect re-enable Create immediately.
- Saving a brief from an existing recurring schedule is not implemented;
the selected-mission action currently covers one-time missions only.
- Task conversation lookup for older unbound native tasks reads a
bounded coordinator-message window and recognized exact assignment
evidence. Older/unrecognized delegations may have no shortcut; no
conversation is guessed from titles or timings.
- Running native calls may not expose their child ID until completion.
The panel can instead identify a direct child by its first canonical
assignment message, within a bounded direct-child page; unrecognized or
out-of-bound children remain unlinked.
- Native task profiles are recorded, but ordinary subagent launch still
relies on the coordinator passing the declared agent/model/variant to
OpenCode. Omitted model parameters can inherit the coordinator's model;
profile storage alone does not enforce launch parameters.
- One-time recursive interruption is best-effort and bounded, not a
durable guarantee that every descendant stays stopped. Partial/unknown
coverage remains visible.
- Recurring Pause/Stop cancel scheduling, not guaranteed recursive
suspension of a running passage.
- Native qualification uses isolated services; mock-only and
source-review evidence never substitute for real native acceptance.
Final validation results are published separately in the PR reviews.
- Managed-service restart and some
lost-reply/clock-conflict/human-decision journeys still have
offline-only evidence.
- If an admitted passage start is removed by pruning before its lost
durable write is reconciled, that original start identity can become
unavailable for deduplication.

## References
- [Mission
contract](https://github.com/NeuralNomadsAI/CodeNomad/blob/experiment/missions-native-subsessions-20261003/dev-docs/MISSIONS.md)
- [Recurring
contract](https://github.com/NeuralNomadsAI/CodeNomad/blob/experiment/missions-native-subsessions-20261003/dev-docs/MISSIONS_RECURRING_SIMPLE.md)
- [Native
qualification](https://github.com/NeuralNomadsAI/CodeNomad/blob/experiment/missions-native-subsessions-20261003/dev-docs/MISSIONS_RECURRING_SIMPLE_QUALIFICATION.md)
2026-10-11 14:55:49 +02:00
Pascal André
c954841f09
revert(missions): undo PR #673 without dropping later dev changes
Revert merge c118478805 relative to its first parent after the user confirmed the merge was requested in the wrong conversation. Remove the published Missions plugin, control routes, UI, playbooks and packaging references; do not rewrite dev history or touch durable-refactor work in the separate missions-v2 checkout.

Preserve subsequent PRs #792, #829 and #830. Remove only #829's now-invalid Mission reader import, dismissal hook and dedicated reader scenario, retaining the native questions/permissions dock, file-preview navigation and its other tests. Keep the 2.0.22 package pin and parent-session creation fence.

Validation: revert applied without conflicts; all 139 original merge paths reversed; later-only paths retained except the three minimal interruption-dock integration adaptations. Server and UI TypeScript checks and 18 automation/plugin lifecycle/desktop resource tests pass using existing local dependencies. Staged diff checks are clean. Full hosted CI, browser suites and native 2.0.22 qualification were not rerun for this immediate user-authorized admin revert.
2026-10-02 16:18:06 +02:00
Pascal André
b584ffcb3a
merge(dev): reconcile Missions with the current V2 baseline
Integrate dev into the Missions PR without rewriting its reviewed history. Retain mission CRUD routes, authenticated report admission and the 512 KiB bridge limit alongside inspected-window automation and plugin controls. Keep dev's canonical transport, clean builds and 2.0.18 client/plugin dependencies; align the local plugin contract check with the same SDK.

Combine architecture guidance and preserve the technical runtime minimum of 2.0.7. Keep the isolated Missions fixture in the latest-runtime CI lane because its test-only ctx.tool.list driver is absent at that minimum; do not reintroduce legacy compatibility paths.

Validation: server, UI and plugin-contract typechecks; full server/UI/plugin build; 84 backend/compatibility/packaging tests; 59 UI/persistence/browser tests; isolated OpenCode 2.0.18 Missions fixture and workflow YAML parsing. Merge resolutions have no conflict markers or diff-check errors relative to dev.
2026-09-28 10:46:59 +02:00
Pascal André
4d7408631d
feat(missions): bundle project coordination with the desktop runtime
Provision codenomad.missions through connected-daemon discovery and independent backend presence instead of requiring a source plugin in every project. Bundle the integration for Electron and Tauri, retain project-scoped mission journals across shutdown, and use the same secondary surface as Status.

Complete the existing native actor execution work: persist explicit agent/model/variant choices, validate catalog selections and avoid switching busy actors. Admit assignment and report writes through the authenticated desktop bridge with durable-contract verification, session ownership, connection and worktree fences, and per-send profile environment synchronization.

Advance the older source branch client/plugin pin to 2.0.11 and retain its bounded runtime metadata adaptation. The isolated 2.0.16 mission fixture passes native catalog, selection, busy queues, conflict, environment, reports, reconnect and idempotence checks. Server, UI and plugin typechecks, 31 mission tests, 10 lifecycle/transport tests and six resource-layout tests pass.
2026-09-27 00:57:56 +02:00
Pascal André
d873cfd2ee
docs: refresh README and workspace screenshot for 0.20 (#782)
## Summary

- Update the main README for the shared OpenCode V2 service, current
features, managed desktop setup, minimum/recommended OpenCode versions,
and explicit service restart behavior.
- Correct release links, actual Electron/Tauri artifact formats and
architectures, Node guidance, remote authentication and SideCar
configuration fields.
- Align server and contributor documentation with the 0.20 baseline.
- Replace the old hero screenshot with a current 1600x900 workspace
rendered using real Solid components and synthetic demo data.
- Include a reproducible Chromium capture script and provenance notes;
external traffic is blocked and no user backend, daemon or provider is
used.

## Preview

![CodeNomad 0.20
workspace](https://raw.githubusercontent.com/NeuralNomadsAI/CodeNomad/docs/readme-0.20/docs/screenshots/workspace-0.20.png)

## Validation

- UI typecheck passes.
- Chromium capture passes transcript, connected-state, agent, timeline
and MCP readiness checks, with no uncaught renderer errors.
- Resulting image inspected visually.
- 20 local Markdown/image targets verified.
- Staged git diff --check passes.

Regenerate with: node packages/ui/scripts/capture-readme.mjs

Documentation and capture tooling only; CI is not being monitored.
2026-09-26 04:13:30 +02:00
Pascal André
83a4124b37
feat(v2): manage session families across worktrees (#649)
## Summary

Manage complete session families across the opened local repository's
native OpenCode worktrees. This supersedes #642 with the V2
implementation and addresses #319.

- OpenCode owns `worktree.refresh/list/create/remove`; CodeNomad
supplies the default directory, named-branch policy, local repository
scope and verified family transactions.
- A project is the opened local checkout and its registered worktrees,
identified through the physical Git common directory. Independent clones
sharing an OpenCode project ID stay separate.
- Session rows, composer selection, search and the Git panel follow
native `SessionInfo.location.directory`. Durable metadata is preserved,
but old `worktreeSlug` metadata does not override native placement.
- Creation uses the selected checkout's revision and the main local
checkout's `.codenomad/worktrees` parent. Uncommitted edits stay in the
source checkout. External registered worktrees remain discoverable.
- Keep copy/open/delete actions in the accessible selector, remove the
redundant action bar, hide root-workspace badges, and explain “Create
and use” in all ten locales.

## Current base and native contract

This branch includes merged `dev@e47e01c6`, including #697's separately
reviewed discovery/status compatibility fix. UI/server pin
`@opencode/client@2.0.4`; the independently managed daemon has no
exact-version startup gate.

- Complete bounded inventories use opaque native cursors; continuations
send only the cursor.
- Moves are serialized across complete families, block active sessions,
verify authoritative native locations and roll back partial failures.
- Native move events refresh placement and the catalogue without
speculative cross-project transfers.
- Opaque worktree identifiers are separate from mutable branch labels.
The main checkout cannot be removed.
- Native detached creation is followed by ordinary Git branch selection,
preserving Git's refusal to reuse a checked-out branch;
branch-attachment failure cleans up through the native API.
- Agent placement instructions distinguish creating a checkout, one-off
commands and moving the conversation's execution context. Explicit
attachment choices are preserved.

## Deletion safety

- Physical checkout reservations cover published and in-flight logical
workspaces.
- Project serialization and deletion fences cover all family
source/destination checkouts.
- Complete inventories and cross-project checks run inside the deletion
fence, including nested workspaces and owned Shell/PTY resources.
- Canonical path, filesystem identity, registration, branch, HEAD and
active sessions are rechecked before removal. Replacement checkouts fail
closed; rollback requires the original identity.

## Recovery and Git-panel corrections

Validation on the real repository exposed serial enumeration of 162
worktrees and concurrent ownership misses launching overlapping
inventories. Git annotations now run with bounded concurrency, pending
catalogue reads are shared, and negative ownership results are
snapshot-cached. A regression exercises 40 concurrent misses.

The Git panel now treats its complete local staged/unstaged inventory as
authoritative instead of resurrecting native-only stale rows. It also
rechecks the selected worktree/request after waiting for native VCS
status.

## Validation

Latest integration validation:

- Isolated official **OpenCode 2.0.0 and 2.0.7**: production
discovery/status, native worktree discovery/create/remove, selected
HEAD/default parent/named branches, independent-clone scope, stable IDs,
nested paths, checked-out/dirty guards, complete family moves and
rollback.
- Real Solid selector browser tests: mouse, keyboard, touch, actions
without session movement, creation source and returned stable ID.
- Targeted server ownership/cache/manager/proxy/route/location tests; UI
session projection/request-authority/lifecycle tests; family
evacuation/rollback and Git model regressions.
- UI/server typechecks and production server build including the UI.
- Installed Windows Tauri application on the actual repository:
dedicated session creation/use, native location and row/composer badges,
Git marker visibility, move back, and agent `session_move` reflected in
both badges.
- Rebuilt UI/server resources installed; full Developer Mode restart
restored the original conversation. Disposable sessions, marker,
worktrees and branches cleaned up. The original conversation remained
attached to `pr649-final`.
- `git diff --check`.

An immediate post-restart desktop run exceeded a 30-second
refresh-button wait; the subsequent completed run passed. These checks
validate the workflows, not a startup latency bound or exhaustive
compatibility of every OpenCode payload.

Earlier branch validation also covered Electron/Tauri native actions,
packaging and desktop parity; those results remain in the PR's
historical validation comments. Detailed contract and latest evidence:
`dev-docs/WORKTREE_SESSION_PLACEMENT.md`.

## Residual limit

OpenCode and Git expose no shared snapshot/CAS transaction. CodeNomad
narrows races with reservations, locks, fences and repeated
authoritative checks; unrelated processes can still mutate state outside
those controls.
2026-09-17 22:57:37 +02:00
Pascal André
aa51cbb9ff
fix(opencode): support earlier and modern V2 runtime contracts (#695)
Closes #694

## Status

This PR contains the stable 2.0.4 client migration, authenticated V2
discovery fallback and shared cross-runtime compatibility
implementation. The validation results below are local execution
evidence; the newly added CI matrix must also run on the updated PR
head.

## Published changes

- Pin UI/server to official `@opencode/client@2.0.4` and the bundled
pruning plugin to `@opencode/plugin@2.0.4`, with the corresponding
lockfile migration.
- Probe authenticated `/api/status` first. Fall back to earlier V2
`/api/health` **only on HTTP 404**, retaining the endpoint, credentials,
64 KiB response bound and absolute deadline. Authentication, transport,
server and malformed-status failures do not trigger fallback.
- Migrate the canonical UI/server contract to stable Forms, permission
decisions, command names, interrupts, renaming, forks, message lookup
and inbox delivery.
- Update the guarded proxy for stable methods/paths, native
active-session envelopes, native `cursor.next`, global Form directory
headers and current resource/plugin events.
- Follow the renamed upstream platform binary `bin/opencode(.exe)` while
retaining public CLI aliases.

Discovery success alone does not establish compatibility with an earlier
runtime's conversation APIs.

## Shared cross-runtime compatibility

### Shared cross-runtime integration

- Introduce one connection-scoped adapter under
`packages/server/src/opencode/compatibility/`, used by both the guarded
UI proxy and direct server callers, including Yolo.
- Select the contract using authenticated daemon identity rather than
the CLI executable's version. Recognize unknown publications through
authenticated, bounded OpenAPI negotiation instead of an exact
runtime-version gate.
- Bind authorization, client, transport and profile to one connection
generation. Fence actual mutation dispatch after asynchronous body
preparation; prevent late old streams from publishing or invalidating
their replacement.
- Translate earlier V2 routes, methods and payloads before sending.
Never retry a mutation speculatively after 400, 404, authentication or
transport failures.
- Normalize legacy HTTP inbox timestamps, including compaction
admission, before the pinned Solid reducer. Preserve the distinct native
SSE inbox schema and durable event metadata.
- Restore legacy catalog/content invalidation and permission-event
convergence. Preserve meaningful method/path/status/profile diagnostics
and native 401 error envelopes.

### Location authority and pruning

- Preserve legacy workspace identity internally through request
serialization, catalog/cache keys, Forms, imports, cursors, events and
exact move rollback. Modern public APIs continue to reject obsolete
workspace selectors.
- Authorize complete locations before translating directories or
synthesizing upstream Form/location headers. Keep native cursor tokens
unchanged.
- Preserve session/path ownership, worktree mutation fences and the
restricted proxy allowlist. Generic RPC, plugin management and
destructive revert commit remain blocked.
- Carry verified legacy identity through pruning membership checks,
preview and the existing transactional storage/claim fence; do not relax
deletion checks.
- Treat native idle records as control records, retaining
identity/outcome without fabricated assistant text.
- Add a common multi-runtime CI matrix and the audit/evidence register
in `dev-docs/OPENCODE_V2_COMPATIBILITY.md`, including preserved
historical architecture findings.

## Local validation

All native tests use isolated synthetic daemons, configuration and
databases, never the shared daemon or user storage.

| Check | Result |
| --- | --- |
| Same native suite on beta-19271, 2.0.3, 2.0.4 and 2.0.5 with pinned
client/plugin 2.0.4 | Passed |
| Full native pruning suite with non-null legacy workspace identity on
beta-19271 and 2.0.3 | Passed |
| Rendered UI on modern 2.0.5 and beta-19271 with non-null identity |
Passed |
| Native 2.0.5 suite inside Ubuntu/WSL, using a temporary Linux
filesystem root | Passed |
| Server tests (after CI follow-up) | 500 passed, 2 skipped |
| UI store tests | 441 passed |
| Electron native tests | 194 passed, 4 skipped |
| UI/server/Electron typechecks | Passed |
| UI/server and Electron production builds | Passed |
| Windows Tauri release executable (`--no-bundle`) | Passed |
| Electron/Tauri packaged-resource smoke checks | Passed |
| Desktop packaging invariants | 4 passed |
| `git diff --check` | Passed |

The native matrix exercises the actual shared connection, generated
client, UI fetch adapter and guarded proxy: voice-off/on instructions,
prompts, commands, session Shell, background Shell output
cursors/removal, UI/Yolo permission acceptance and rejection, busy inbox
delivery/cancellation, interrupt/wait, staged revert clearing,
session/global/worktree Forms, native pagination, export/import,
same-directory legacy identities, scoped events, foreign authority
refusal and exact rollback.

Pruning coverage includes actual storage identity and execution claims,
busy refusal, idempotency, competing admission, next-model payload, fork
isolation, pre-compaction history, restart, backend presence
disposal/reopening and crash expiry. Rendered tests cover
individual/group/response/session cleanup, confirmation counts,
persistence and reload.

## Autonomous gatekeeper review

Review/fix/retest loops concluded with no remaining actionable findings
in the reviewed transport/lifecycle/proxy,
identity/UI/events/pruning/rollback, scripts/CI and rendered-fixture
scopes.

Corrections included dispatch-generation races, compaction admission
normalization, independent negotiation cancellation, first-request
profile resolution, preservation of streamed 401 envelopes and direct
Shell/PTY identity propagation. A final rendered failure was traced to
the fixture awaiting only the first RPC of a cross-message deletion; the
fixture and regression now await every affected message. Production
deletion guards were not relaxed.

This scoped approval does not close the separately preserved historical
architecture findings.

## Validation boundaries

### CI follow-up

The first run on `a0c1c943`
([35142559235](https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/35142559235))
failed in five native jobs. The local bundle tests had missed the
standalone npm archive's missing sibling import, and Windows legacy jobs
exposed a short-path versus canonical-path project comparison. The
dependent artifact-comment job reported that same build failure.

The follow-up makes the plugin's identity primitives self-contained,
adds an isolated npm-file-list regression for all exported entrypoints,
and corrects project identity selection with alias and nested-repository
regressions. The packed-plugin failure was reproduced before correction;
the corrected installed package passes the native suite on Windows 2.0.4
and Linux/WSL 2.0.4/2.0.5. The corrected 2.0.4 shipped bundle also
passes rendered/native pruning. Fresh full beta-19271 and 2.0.3
`--legacy-pruning` suites pass under a reproducing Windows short-path
TEMP root after the final exact-directory fix. Independent final reviews
approve packaging/documentation and worktree identity with zero
actionable findings. Remote checks on the new head remain the CI
authority; these are local follow-up results.

- Full interaction with the installed desktop application through
Developer Mode was not verified because Developer Mode is inactive. The
release executable and packaged-resource checks above are build/smoke
evidence, not a fresh-install interactive certification.
- Remote run
[35146390688](https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/35146390688)
at `486e856d` passes all runtime-contract jobs, Windows/Linux native
pruning, service compatibility, general tests and both Tauri checks.
macOS passes packed-plugin loading/pruning, then times out on late
bundle discovery. The fixture now canonicalizes its root before daemon
startup to align `/var` configuration paths with `/private/var` FSEvents
paths. Late installation remains mandatory and asserts the plugin was
initially absent; failures now upload isolated diagnostic
logs/inventory/captures. Actual macOS confirmation remains pending on
the new head.
- Interactive native TUI validation was not performed.
- The passing WSL result is Linux-native execution inside WSL, not a
complete Windows-host/WSL desktop traversal. With the fixture's
configuration directory under `/mnt/c`, conversation/proxy checks passed
but late plugin discovery timed out; the otherwise equivalent
Linux-filesystem run passed. Mounted-configuration late discovery
remains a documented environment limitation.
- Other audited publications are declaration-reviewed, not individually
native-certified. The four-runtime matrix does not imply universal V2
compatibility.
- Earlier PR artifacts do not contain the completed cross-runtime
implementation; use artifacts built from the updated head. Local passing
results do not imply that the updated remote CI has completed.
2026-09-16 23:48:08 +02:00
Pascal André
52f0e62935
feat(opencode): migrate CodeNomad to native V2 (#647)
# OpenCode V2 Migration and Desktop Restructuring

## Summary

This branch replaces CodeNomad's OpenCode V1 SDK, custom plugin, and
per-workspace runtime architecture with the native OpenCode V2 client
and one shared OpenCode service. It intentionally ships no V1 runtime
fallback.

The scope includes native location ownership, Forms and Shell resources,
project-wide cursor pagination, bounded resident message windows,
streaming reconciliation, duplicate-folder instances, multi-window
Electron/Tauri behavior, content-addressed restore, worktree mutation
fencing, and reproducible desktop packaging.

The reviewed implementation head is `dea20996`. UI and server resolve
`@opencode-ai/client@beta` to `beta-18999`; the runtime CLI is managed
independently. The official comparison baseline remains `upstream/beta`
at `eb1ac54d73`.

Full details: [`MIGRATION_V2.md`](./MIGRATION_V2.md),
[`DESKTOP_V2_COMPARISON.md`](./DESKTOP_V2_COMPARISON.md), and
[`dev-docs/DEV_V2_CODE_REDUCTION.md`](./dev-docs/DEV_V2_CODE_REDUCTION.md).

## Stabilization Fixes

- Preserve manual scroll escape across pagination, remote updates,
capped-window shifts, tab changes, and desktop restore; only a local
prompt submission forces the bottom.
- Keep the timeline resident window capped at 200 messages. Ordered
window slides use Virtua shift, while reorder, pagination, and
non-aligned replacement remount with a fresh measurement epoch.
- Finalize the temporary `200 -> 201 -> 200` transition in a
generation-guarded microtask before paint and compensate followed
content growth from a `ResizeObserver` attached to the mounted Virtua
root.
- Keep all pending inbox prompts after delivered transcript messages in
native inbox admission order.
- Add a persisted `steer`/`queue` follow-up preference; the alternate
shortcut uses the inverse while idle sends remain `steer`.
- Edit a pending prompt only after authoritative inbox cancellation
succeeds, then restore its text, structured payload, files, and agent
references to the composer.
- Expose native `session.background` through the ownership-checked
proxy, a prompt action, and `Ctrl/Cmd+B`.
- Remove the duplicate model-selector "show all" action and make the
favorites toggle label reflect its current action.
- Restore permission/Form synchronization plus skill, reference,
MCP-resource, and websearch-provider reads in the reviewed proxy
allowlist.
- Validate and preserve native location workspace identities for
root/worktree requests, session moves/imports, cursors, and global
Forms.

## Capability Decisions

| Capability | Native V2 availability | CodeNomad `DEV-v2` decision |
Revisit or complete when |
| --- | --- | --- | --- |
| Assistant content mutation | `session.messageUpdate` authoritatively
replaces the text, reasoning, and tool content of a completed assistant
message. There is still no generic deletion of a complete delivered
message or mutation of user messages. | Restores individual
tool/reasoning deletion through the native update route. Arbitrary
whole-message deletion remains absent rather than locally simulated. |
Add broader deletion only if V2 exposes an authoritative operation for
the required message type. |
| Bulk tool and reasoning cleanup | No native bulk operation, but
`session.messageUpdate` can safely compose cleanup one assistant message
at a time. | Restores selected-group and full-session technical-part
cleanup through authoritative per-message updates. | A native bulk
operation is only needed if per-message updates become a measured
performance problem. |
| Delete-to-boundary / undo | `session.revert.stage` and
`session.revert.clear` use V2 staged-revert semantics instead of
arbitrary deletion. | Command-palette Undo uses `revert.stage`; Redo
clears the staged revert through `revert.clear`. | Revisit only if V2
adds broader authoritative transcript deletion. |
| Compaction | Native checkpoint compaction summarizes the older head
and retains a server-selected recent tail controlled by
`compaction.keep.tokens`. | Uses `session.compact`; there is no
message-level selective compaction. CodeNomad displays the partial
summary through the same reactive streaming path as text and reasoning,
then replaces it with the terminal summary. | Add scoped controls only
if V2 defines scoped compaction semantics. |
| Transcript pagination authority | Message pages expose only opaque
previous/next cursors. They provide no transcript revision, total,
absolute range, position, or random seek target. | Uses bounded cursor
traversal and a 200-message resident window, with defensive
reconciliation after destructive events. It cannot prove that pages
loaded across compaction or revert belong to one snapshot. | V2 adds
snapshot revision authority
([#43766](https://github.com/anomalyco/opencode/issues/43766)) and
navigable position metadata
([#44660](https://github.com/anomalyco/opencode/issues/44660)). |
| Full-session search | `session.list(search)` filters session titles
only. There is no server transcript-search endpoint returning message
identity, excerpt, navigable position, and transcript revision. |
Retained through exhaustive message-cursor traversal while keeping only
the 200-message resident window and collected matches. Large searches
still fetch every page. | V2 exposes transcript search
([#45801](https://github.com/anomalyco/opencode/issues/45801)) with a
target that composes with transcript revision and seek metadata. |
| Queued prompt management | Native inbox list, cancel, steer, and queue
operations cover authoritative follow-up delivery. The TUI's edit action
cancels a queued prompt before restoring it to the composer; it is not
an atomic inbox update. | Implements persisted primary `steer`/`queue`
delivery, inverse alternate shortcut, delivery switching, cancellation,
cancel-first composer restoration with structured payload retention, and
native-order timeline projection. | Revisit atomic editing or reordering
only if V2 adds an authoritative operation and a concrete product need
is established. |
| Background execution | Native `session.background` moves blocking
tools out of the foreground; Shell resources separately support listing,
bounded output, and removal. | Exposes `session.background` through the
proxy and UI with `Ctrl/Cmd+B`, and replaces the custom process manager
with native Shells. Unsupported controls such as rename remain removed.
| Add controls only when the native session or Shell APIs support them.
|
| Service lifecycle | V2 uses one shared externally owned service rather
than one runtime per workspace. | CodeNomad discovers or starts the
service. Stop Workspace evicts the native location after its final
logical owner is removed; application shutdown never stops the daemon. |
No parity work planned unless V2 changes service ownership semantics. |

## Validation

Migration gate (`878550ca`):

- UI and server TypeScript typechecks.
- 86 focused UI tests covering follow, pagination, queue ordering,
bottom pinning, shortcuts, delivery resolution, and model visibility.
- 64 focused server tests covering proxy ownership/location enforcement
and shared-service workspace identity.
- Production UI/server build.
- Tauri `cargo check` and all 121 Rust tests.
- `git diff --check`.

Timeline stabilization (`dea20996`):

- UI TypeScript typecheck and all 68 focused timeline, pagination,
request-authority, and restore tests.
- Tauri release build against the `beta-18999` lock.
- Native Developer Mode validation: no remount or empty frame during
capped shifts, same-cycle growth compensation, preserved manual escape,
and inactive-tab anchor restore within 0.3125 px.

## Remaining Gaps

- Active-session-location authority for MCP/plugin status.
- Optional interactive PTY, session export, and reference/MCP-resource
attachment UI.
- Desktop release signing/notarization hardening.
2026-09-04 11:36:11 +01:00
fitzgpt
14586cb33e
feat(ui): add Turkish localization (#662)
Adds Turkish (tr-TR) as a supported UI language, following the same
structure as the existing German/Nepali localization (#523).

## What's included

- `packages/ui/src/lib/i18n/messages/tr/` — all 16 message modules +
`index.ts`, mirroring the English files. **1,602/1,602 keys translated**
(verified against `en/`: no missing, no extra, every `{placeholder}`
preserved).
- `packages/ui/src/lib/i18n/index.tsx` — `tr` added to the `Locale`
union, `SUPPORTED_LOCALES`, and `localeLoaders` (lazy import, same as
other locales).
- `packages/ui/src/components/locale-selector.tsx` — `Türkçe` added to
the language options.
- `CONTRIBUTING.md` — translation-files row updated to list the current
locale set.

## Translation conventions

Following the repo's i18n rule ("add to `en/` first, then every other
locale"), plus the convention visible in existing locales:

- Developer jargon stays English: session, workspace, instance,
provider, agent, prompt, token, diff, commit, worktree, branch, SideCar,
plugin.
- Product names and acronyms stay literal: CodeNomad, OpenCode, GitHub,
VS Code, API, CLI, SSH, TLS, TTS/STT.
- Turkish orthography (İ/ı casing, apostrophe suffixes on jargon:
session'ın, agent'ler).

## Verification

- `npx tsc --noEmit -p tsconfig.json` (packages/ui) — pass
- `npx vite build` (packages/ui) — pass (build also exercises
`mergeMessageParts`, so no duplicate keys)
- Runtime check on `vite dev`: with a Turkish browser locale the app
auto-detects and renders fully in Turkish; the language picker lists and
selects `Türkçe` (screenshots below)

## Screenshots

**Before — English UI (fresh profile, en-US locale):**
<img width="640" alt="before-english"
src="https://raw.githubusercontent.com/fitzgpt/CodeNomad/tr-evidence/evidence/cn-before-english-home.png"
/>

**After — Turkish UI (auto-detected from browser locale):**
<img width="640" alt="after-turkish"
src="https://raw.githubusercontent.com/fitzgpt/CodeNomad/tr-evidence/evidence/cn-after-turkish-home.png"
/>

**After — language picker with Türkçe selected:**
<img width="640" alt="after-picker"
src="https://raw.githubusercontent.com/fitzgpt/CodeNomad/tr-evidence/evidence/cn-after-turkish-picker-open.png"
/>

---------

Co-authored-by: fitzgpt <fitzgpt@users.noreply.github.com>
2026-08-26 19:14:20 +02:00
Dark
17547a15d8
docs: add CONTRIBUTING.md guide for new contributors (#484)
## Summary
Adds a CONTRIBUTING.md file to help new contributors get started.

## Contents
- Quick start setup
- Finding issues to work on (label guide)
- Branch naming conventions
- Development workflow (fork, branch, commit, PR)
- Project structure overview with key file paths
- Styling conventions and file size guidelines
- i18n workflow for adding translations
- Code principles (KISS, DRY, single responsibility)

This gives new contributors everything they need in one place to start
contributing effectively.

---------
2026-06-13 14:01:04 +02:00